Settings
Presentation
ActiveUI has built-in support for user and role based settings. Depending on the current user and that user's roles, Settings determines the following:
- Whether or not the user is allowed to perform specific actions in the interface.
- The way that certain components will render and behave (i.e. the way in which they are customized).
A setting is a key-value pair, where the key is unique among all the settings and the value can be any native JavaScript type.
ActiveUI uses the Content Server to store and read, in real-time, the settings of the current user.
Everything happens under the /ui/settings directory.
The fact that settings are stored on the Content Server means that an asynchronous remote request has to be made to fetch their values.
It introduces a small time interval between the application start up and the first response of the Content Server during which reading a setting will always return its default value.
If a user's theme setting is changed so as not to use the default one, it can lead to a "glitch" effect. The application will first be rendered with the default theme but as soon as the user's chosen theme is retrieved from the Content Server, the application will re-render everything with the new palette. To avoid this issue you can:
- Change the default setting value.
- Wait for the settings to be synchronized with the Content Server, using the
onSyncmethod of theSettingsManagerbefore rendering anything.
Usage
The SettingsManager can be retrieved through the ActiveUI instance.
Here is a quick usage example:
const localeSettingKey = 'global.locale';
const {settings} = activeUI;
// Log the locale for the current.
// `en-US` for instance.
console.log(settings.get(localeSettingKey));
if (settings.canEdit(localeSettingKey)) {
// Switch to French if the user has permission to do it.
// The change is asynchronous because it calls to the Content Server.
await settings.set(localeSettingKey, 'fr-FR');
}
Available Settings
The list of available settings is here.
Controlling Settings Through the Content Server
Structure of a Settings File
Settings files are written in JSON and have the following structure:
{
"map": {
"settingKey1": "value",
"settingKey2": ["value"],
"...": "..."
}
}
Preferences Vs. Permissions
Suppose our project has:
- A unique setting with the key
settingExample. - 3 different roles:
ROLE_USER(the one all users should have),ROLE_MANAGEMENTandROLE_CS_ROOT. - A unique user with the username
USER_Aand the rolesROLE_USERandROLE_MANAGEMENT(in this order, meaning thatROLE_USERis less important thanROLE_MANAGEMENT).
Then settingExample could be declared in any of these files:
Subpath after /ui/setting | Readers roles | Owners roles |
|---|---|---|
default/preferences | ['ROLE_USER'] | ['ROLE_CS_ROOT'] |
default/permissions | ['ROLE_USER'] | ['ROLE_CS_ROOT'] |
roles/ROLE_USER/preferences | ['ROLE_USER'] | ['ROLE_CS_ROOT'] |
roles/ROLE_USER/permissions | ['ROLE_USER'] | ['ROLE_CS_ROOT'] |
roles/ROLE_MANAGEMENT/preferences | ['ROLE_MANAGEMENT'] | ['ROLE_CS_ROOT'] |
roles/ROLE_MANAGEMENT/permissions | ['ROLE_MANAGEMENT'] | ['ROLE_CS_ROOT'] |
roles/ROLE_CS_ROOT/preferences | ['ROLE_CS_ROOT'] | ['ROLE_CS_ROOT'] |
roles/ROLE_CS_ROOT/permissions | ['ROLE_CS_ROOT'] | ['ROLE_CS_ROOT'] |
users/USER_A/preferences | ['USER_A'] | ['USER_A'] |
users/USER_A/permissions | ['USER_A'] | ['ROLE_CS_ROOT'] |
As you can see, there is a concept of preferences and permissions .
The idea is that the value of settingExample can be declared both in a preferences and a permissions file.
However, the value written in the permissions file will override the one set in preferences.
In fact, there is a very specific order in which settings files are merged.
Merging Order
Settings can be defined for a particular user, for a group of users (a.k.a. role) or globally.
User specific settings takes precedence over role specific settings which take precedence over global settings.
Also, in the case where a user belongs to multiple roles as defined by AuthenticationHolder#getSortedRoles, the settings from the last roles take precedence.
In our example, for USER_A, the settings files will be merged on top of each other in this order:
default/preferencesroles/ROLE_USER/preferencesroles/ROLE_MANAGEMENT/preferencesusers/USER_A/preferencesdefault/permissionsroles/ROLE_USER/permissionsroles/ROLE_MANAGEMENT/permissionsusers/USER_A/permissions
The permissions files are merged last and thus override the preferences ones.
The ROLE_USER files are merged before the ROLE_MANAGEMENT so that the values written in the ROLE_MANAGEMENT files take precedence over the one in ROLE_USER according to the order in which these roles were granted to the user.
Readers and Owners Roles of the Settings Files
The other thing to be aware of is the readers and owners roles of the settings files.
The only file that USER_A can edit is the users/USER_A/preferences one.
This means that if a setting value is specified in a file that is merged after users/USER_A/preferences, then this value will be enforced and USER_A won't be able to change it.
Examples
- To force a setting value for all users, declare it in
default/permissions. - To force a setting value for users with role
ROLE_MANAGEMENT, declare it inroles/ROLE_MANAGEMENT/permissions. - To have a setting default to a given value for users with role
ROLE_MANAGEMENTbut allow these users to override it if they want to, declare it inroles/ROLE_MANAGEMENT/preferences.
The merging order detailed previously applies to all these examples and thus the setting values could be overridden in other places.