Dynamic configuration
At its heart, Finsemble is a config-driven framework. This was a purposeful design decision to allow for easy integration of third-party componentry and to support a user-configurable interface.
The most basic Finsemble implementations are driven by a static configuration, which we describe in the Configuration tutorial. However, many production implementations demand a dynamic configuration. That is, they require that configurations are determined at runtime, either by the application itself or by a remote server. For example, you might want to have Finsemble’s available components or default workspaces vary depending on [user entitlements](/docs/productivity/API-tutorials-and-refs/authentication/Authentication. In this scenario, Finsemble could prompt the user for authentication, relay the user’s credentials to a server, and then receive back a configuration for that user.
Only trusted components, i.e., components on the same domain as the the Finsemble services can make changes to the config. Note that changes to the config made at run time do not persist.
Listen for changes to component config
Components can add listeners to listen for changes to their own config and make necessary adjustments. To add a listener:
function configChanged(err, newConfig) {
// Do what you need to do here with newConfig
}
// Get component type of current component
var componentType = FSBL.Clients.WindowClient.options.customData.component.type;
// Add listener
FSBL.Clients.ConfigClient.addListener({ field: "finsemble.components." + componentType }, configChanged);
In fact, you can use the listener to listen for changes to any config item at any level. So if you only wanted to listen
to a change for a property called defaultChartType
, you could do this:
FSBL.Clients.ConfigClient.addListener(
{ field: "finsemble.components." + componentType + ".defaultChartType" },
function (err, defaultChartType) {
setChartType(defaultChartType);
}
);
Dynamically load apps based on authentication
Sometimes you might want to present different apps to different users. You might want to also limit a user's access to apps, so that they can only see the apps they need, rather than all the apps available in your Finsemble installation. By using dynamic config you can define a specific Finsemble installation to make only certain apps accessible to an authenticated user. To do this, you need to create a custom Authentication UI component and modify it to fetch the apps after the user has been authenticated.
Run yarn template Authentication
to install the authentication template in src/Authentication
. Write code to fetch the list of apps for the user and then either replace the entire finsemble.appd
config item or add to it by setting finsemble.appd[AppId]
for each app that you want to add.
Dynamic config example: Add this code to your Authentication component
const authenticate = async () => {
// This line of code assumes you have a server that takes username and password and returns AppD records.
// Replace this with your own code and appropriate error handling.
const { error, appdRecordsFromServer } = await sendToServer(payload.username, payload.password);
if(error){
setError(error);
return;
}
// This code will set the user's apps to what was returned by the server. The appdRecordsFromServer should
// be a map of AppD records, just like in `public/configs/application/appd.json`
// See the documentation for processAndSet() for more information on the `overwrite` and `replace` flags
await FSBL.Clients.ConfigClient.processAndSet({ newConfig : {
appd : appdRecordsFromServer
}, overwrite : true, replace: true});
// This line of code will close the Authentication component and instruct Finsemble to continue the boot process
publishAuthorization(payload.username, { username: payload.username });
};
authenticate();
During dynamic configuration, Finsemble can overwrite components already in the configuration when ConfigClient.processAndSet
is called. To prevent this from happening, set manifest.component.category = "system"
in the config of the component. This setting is used, for example, to prevent system UI components from being dropped out of the config.