Settings

How to Use the Settings

Presentation #

ActiveUI has built-in support for user and role based settings. Depending on the current user and their roles, settings allow to:

  • Let or prevent the user from performing specific actions in the interface.
  • Customize how some components should render and behave.

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 settings folder just under the ActiveUI Content Server root folder.

Important

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 changes their theme setting in order not to use the default one, it can lead to a “glitch” effect. In fact, the application will first be rendered with the default theme but as soon as the user favorite theme is retrieved from the Content Server, the application will re-render everything with the new palette. To avoid this issue you can:

Preferences Vs. Permissions #

Let’s say that our project has:

  • A unique setting with the key settingExample.
  • 3 different roles: ROLE_USER (the one all users have), ROLE_MANAGEMENT and ROLE_ROOT.
  • A unique user with the username USER_A and the roles ROLE_USER and ROLE_MANAGEMENT (in this order, meaning that ROLE_USER is less important than ROLE_MANAGEMENT).

Then settingExample could be declared in all of these files:

  • default/preferences (reader: ROLE_USER, owner: ROLE_ROOT)
  • default/permissions (reader: ROLE_USER, owner: ROLE_ROOT)
  • roles/ROLE_USER/preferences (reader: ROLE_USER, owner: ROLE_ROOT)
  • roles/ROLE_USER/permissions (reader: ROLE_USER, owner: ROLE_ROOT)
  • roles/ROLE_MANAGEMENT/preferences (reader: ROLE_MANAGEMENT, owner: ROLE_ROOT)
  • roles/ROLE_MANAGEMENT/permissions (reader: ROLE_MANAGEMENT, owner: ROLE_ROOT)
  • roles/ROLE_ROOT/preferences (reader: ROLE_ROOT, owner: ROLE_ROOT)
  • roles/ROLE_ROOT/permissions (reader: ROLE_ROOT, owner: ROLE_ROOT)
  • users/USER_A/preferences (reader: USER_A, owner: USER_A)
  • users/USER_A/permissions (reader: USER_A, owner: ROLE_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 permissions and a preferences 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 #

For USER_A, the settings files will be merged on top of each others in this order:

  1. default/preferences
  2. roles/ROLE_USER/preferences
  3. roles/ROLE_MANAGEMENT/preferences
  4. users/USER_A/preferences
  5. default/permissions
  6. roles/ROLE_USER/permissions
  7. roles/ROLE_MANAGEMENT/permissions
  8. 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 accordingly to the order in which these roles were granted to the user.

Reader and Owner Roles of the Settings Files #

The other thing to notice is the reader and owner roles of the settings files. The only file that USER_A can edit is the users/USER_A/preferences one. It means that if a setting value is specified in a file merged after users/USER_A/preferences, then this value will be enforced to USER_A.

Structure of a Settings File #

Settings files are written in JSON and have the following structure:

{
  "allow": [
    /* array of patterns matching settings keys which value should be set to true */
  ],
  "deny": [
    /* array of patterns matching settings keys which value should be set to false */
  ],
  "map": {
    "settingKey1": "value",
    "settingKey2": ["value"],
    "...": "..."
  }
}

The allow and deny arrays are optionals. They contain regex patterns matching setting keys. If a setting key is matched by an element in the allow array and also in the deny one, it will be set to false. The map object allows to set the value of settings by using their key. If there is a conflict between allow/deny and map, it’s map, which is more explicit, that has the last word.

Example #

Let’s say the default settings are:

  • component1.clickButton1: true
  • component1.clickButton2: false
  • component2.clickButton1: false
  • component2.clickButton2: true
  • component2.clickButton3: true

and the setting file is:

{
  "allow": ["component1..+"],
  "deny": ["component1.clickButton2", "component2..+"],
  "map": {
    "component2.clickButton2": true
  }
}

then after applying the allow pattern we get:

  • component1.clickButton1: true
  • component1.clickButton2: true
  • component2.clickButton1: false
  • component2.clickButton2: true
  • component2.clickButton3: true

after deny:

  • component1.clickButton1: true
  • component1.clickButton2: false
  • component2.clickButton1: false
  • component2.clickButton2: false
  • component2.clickButton3: false

and finally, after map:

  • component1.clickButton1: true
  • component1.clickButton2: false
  • component2.clickButton1: false
  • component2.clickButton2: true
  • component2.clickButton3: false

Settings Manager #

The SettingsManager can be retrieved through the ActiveUIAPI.

Default Settings #

The list of default settings is available here.