Expand my Community achievements bar.

Admin Configuration Page Setup

Avatar

Employee Advisor

We have a requirement to create an admin page in our firefly app which will be configured to take all the API's endpoints and API key initially on App setup and set those values for all the app users. It's mostly all the fields that go in .env file but we want it to be configurable by admin.

1. Can we use aio-lib-state for this?

2. If yes, whether these configurations would be available for all users?

3. And how to initialize this as the first thing app loads for any user.

4. Also, we're not sure how to retrieve values from aio-lib-state from different action files.

This would be similar to how the ims object becomes available on bootstrapping the app in index.js

Thanks in advance.

Topics

Topics help categorize Community content and increase your ability to discover relevant content.

9 Replies

Avatar

Employee

@shelly-goel - a Firefly app is deployed to a workspace that you specify, which assigns a Runtime namespace and relevant State lib access for it.

Speaking about app state, there are 2 separate concepts:

  • build variables: used for building and deploying the app. Those are the values set in .env such as Runtime namespace and auth key, product API key, etc.
  • application variables: used by the application to manage its state (such as a list of customers, product names). You could use aio-lib-state for these.

Can you elaborate on the request? Which kind of variables are you asking about?

Avatar

Employee Advisor
Basically we have a requirement for fields in .env file to be configurable through UI so API endpoints etc. can be updated/ configured without changing and deploying .env file

Avatar

Employee
What kind of API endpoints do you configure? Something you add manually, like a 3rd party system? Do you have different endpoints for prod, stage, etc. like prod.ext-service.net, stage.ext-service.net? And they change per workspace deployment?

Avatar

Community Advisor

Hi @shelly-goel we have implemented something like this, maybe the following ideas give you a starting point.

 

"Define Admins": we use "Product Profiles" to define which user should be an admin. basically we created a new product profile and added users as needed. The benefit is that you can now check the ims object if the current user of the firefly app is an admin or not (by looping through ims.profile.roles - is some work to figure out the details about a specific role). remark: the Role ID is stored in the ENV-File, so you need to create the product profile before deployment. But since you might use the same product profile for all environments, you already need it for testing and therefore it is aready available for production.

 

"Store Config Settings": we store the config settings using aio-lib-files and store the config as json object in a single file. but you can use aio-lib-state as well, but don't forget to set the right expiry if using state... using this setup allows to change the config after deployment (see below) without the need to redeploy anything.
Remark: the filename for the config file is defined in the .env file so that all actions have access to the right file - no need to change all over the app...

 

"Admin Screen": the core of the solution is a defined view in react with special behaviour and some additional actions. here are some points about this admin screen

  1. Admins only: the screen is only accessible by admins - means in the component we check for the role and only display the real content if we can find the desired role in the ims profile. for everybody else we just display an error message like "no access - admins only"
  2. Display current settings: The settings are fetched with an action and they read the current JSON from aio-lib-files. If the file does not exists already, it will be created with some default content (defined during deployment). be careful to handle future "expansions" of the JSON ...
  3. Change settings: the current settings (see 2) are displayed in a form and allow to change the settings and "save". the submit is triggering an "update" action and request to save the input data to aio-lib-files. the action returns the result from the update process as well as a status (display update result to end user)

As an additional security step we implemented a manual check for the user permission on "fetch settings" and "change settings". Just in case somebody is able to see the admin screen, this additional check would prevent the display and modification of any data. How it works: on both actions (2+3 above) we make a manual API call to Adobe User Management and fetch the roles of the end user separately. Drawback is that you need some special permissions (and therefore additional API credentials) to access the User Management API. maybe it is enough if you just add an additional (almost hidden) key + timestamp to the action request which you check before doing anything.

 

"Use settings in the app/actions": last step is a class that allows to fetch the current app settings. basically you load the class and on init it returns the config object. this way all actions can access the same settings ...

 

While I think this setup allows a lot of flexibility, it also takes some time to make the setup. so be aware that this will cause more effort compared to just releasing a new version on the desired environment.

Happy to discuss pros and cons - or to answer additional questions 

Avatar

Employee Advisor
@Urs_Boller - Thanks a lot for this detailed explanation and sharing the drawbacks of this set up. SInce you've already implemented the check for ims profile and fetching/ storing values in aio-lib-files, is it possible for you to share the code snippets. We're currently stuck on how this would be implemented and sample code would be really helpful.

Avatar

Employee Advisor
@Urs_Boller - How are you appending the config details onto same file, for us it get's overridden each time we write something. Code snippets would really be a great help!

Avatar

Community Advisor
@shelly-goel what do you mean by "it get's overridden each time we write something"? don't you check for existing data before writing new data?

Avatar

Employee Advisor

@Urs_Boller- Below is how it would be written into the file, there's just write method and no append method that's why it's overridden.

await files.write('public/index.html', '<h1>Hello World!</h1>')

 Theoretically I understand what needs to be done but not getting the actual code implementation. I'm getting stuck with the code so if you have snippets that would be useful.

Avatar

Community Advisor

@shelly-goelyou need to check if there is any old file either by looping through all files with files.list or check files.property of desired file. if the file already exists and has valid content, then use this content, otherwise use some "hard coded" content (so default might be directly in your src code). hope this helps