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
onSync
method of theSettingsManager
before 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_MANAGEMENT
andROLE_CS_ROOT
. - A unique user with the username
USER_A
and the rolesROLE_USER
andROLE_MANAGEMENT
(in this order, meaning thatROLE_USER
is 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/preferences
roles/ROLE_USER/preferences
roles/ROLE_MANAGEMENT/preferences
users/USER_A/preferences
default/permissions
roles/ROLE_USER/permissions
roles/ROLE_MANAGEMENT/permissions
users/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_MANAGEMENT
but 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.