Permissioning
Note
Before going into details, an important clarification:
Permissions deal only with what is (or is not) displayed in the UI, it does NOT affect the state evaluation or the API calls.
App specific permissioning
Entire modules may be included or excluded from the app via permissioning.
This is a design time concern and is NOT user specific.
By default, all modules are available and presented in the UI (e.g. in the SettingsPanel)
This can be customised with the modules
prop of the component:
- Including only specific modules
<Adaptable.Provider
{...restOfProps}
modules={{
include: ['theme', 'calculatedColumn', 'styledCell'],
}}
>
<Adaptable.UI />
</Adaptable.Provider>
- excluding specific modules (meaning: everything, but...)
<Adaptable.Provider
{...restOfProps}
modules={{
exclude: ['flashingCell', 'styledCell'],
}}
>
<Adaptable.UI />
</Adaptable.Provider>
Note
The availability of a module wins over user permissions. More explicitly, a user can have access to a module but if that module is excluded, it won't be visible for the user, even if the user has the required permissions.
Note
By default, if a module is available, a user has all permissions that come with that module.
However, if userInfo.auth
is specified, that will override the default permissions.
This demo is configured with the following modules excluded: ['styledCell', 'quickSearch', 'flashingCell']
.
If you open the settings panel (by clicking the settings icon in the top-left corner), you will see that the excluded modules are not visible there.
Note
At any time you can re-render the <Adaptable.Provider />
component with a new value for the modules
prop and the UI will be updated accordingly.
Available permissions
Note
Any permission may be negated (excluded from the authorised roles) by prepending it with !
For example, you can authorize a User with the "styledCellAdmin"
role, so it will have all permissions on the Styled Cell Module (create, edit, addToView, etc.), except for "styledCell_delete"
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['styledCellAdmin'],
permissions: ['!styledCell_delete'],
},
}}
To read more on permissions and how to use them, see Using the Authorization Framework section.
The following permissions are available (together with their negated versions):
Alert
"alert_create"
"alert_delete"
"alert_edit"
"alert_add_to_view"
"alert_remove_from_view"
Calculated Columns
"calculatedColumn_create"
"calculatedColumn_delete"
"calculatedColumn_edit"
"calculatedColumn_add_to_view"
"calculatedColumn_remove_from_view"
Export
"export_create"
"export_delete"
"export_edit"
"export_run"
Flashing Cell
"flashingCell_create"
"flashingCell_delete"
"flashingCell_edit"
"flashingCell_add_to_view"
"flashingCell_remove_from_view"
Grid Filter
"gridFilter_create"
"gridFilter_delete"
"gridFilter_edit"
"gridFilter_add_to_view"
"gridFilter_remove_from_view"
Styled Cell
"styledCell_create"
"styledCell_delete"
"styledCell_edit"
"styledCell_add_to_view"
"styledCell_remove_from_view"
Available roles
Note
A role is a collection of permissions that are granted together.
You can use permission negations if you want to grant all permissions in a role except for a specific one.
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['flashingCellAdmin','calculatedColumnAdmin'],
permissions: ['!flashingCell_remove_from_view'],
},
}}
To read more on permissions and how to use them, see Using the Authorization Framework section.
The following roles are available:
Alert
"alertAdmin"
- has all the alert permissions
Calculated Column
"calculatedColumnViewer"
- has the following permissions:"calculatedColumn_add_to_view"
"calculatedColumn_remove_from_view"
"calculatedColumnAdmin"
- has all the calculated column permissions
Export
"exportViewer"
- has the"export_run"
permission"exportAdmin"
- has all the export permissions
Flashing Cell
"flashingCellViewer"
- has the following permissions:"flashingCell_add_to_view"
"flashingCell_remove_from_view"
"flashingCellAdmin"
- has all the flashing cell permissions
User specific permissioning
User session info may be provided via userInfo
prop of the component:
export type UserInformation = {
userId: string;
userName: string;
auth?: UserAuthorization;
};
export type UserAuthorization = {
// a list of roles or a function that returns a list of roles
roles?: AdaptableRole[] | ((context: AuthContext) => AdaptableRole[]);
// a list of permissions or a function that returns a list of permissions
// NOTE: you can also use negated permissions here (eg: "!calculatedColumn_edit")
permissions?:
| (AdaptablePermission | NegatedAdaptablePermission)[]
| ((context: AuthContext) => (AdaptablePermission | NegatedAdaptablePermission)[]);
// optionally, you can provide a custom function to have the final say
// on whether a user has a specific permission or not
checkPermission?: (context: CheckPermissionContext) => boolean;
};
<Adaptable.Provider
{...restOfProps}
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['styledCellAdmin'],
permissions: ['calculatedColumn_edit'],
},
}}
{...restOfProps}
>
<Adaptable.UI />
</Adaptable.Provider>
This example is configured to only allow access to the Calculated Column module.
All other modules that expose permissions are disabled.
This is accomplished by configuring userInfo.auth.roles
<Adaptable.Provider
{...restOfProps}
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['calculatedColumnAdmin'],
},
}}
>
<Adaptable.UI />
</Adaptable.Provider>
Authorization Framework
This may be customised using Adaptable's incredibly flexible authorisation framework, which is a variant of a role-based access control (RBAC) system:
-
Some actions/UI controls are available only if the the user has specific permissions: e.g.
"calculatedColumn_create"
,"calculatedColumn_delete"
, etc. -
Permissions are authorised for specific roles which Adaptable provides out of the box: e.g. Role
"calculatedColumnAdmin"
is authorised for permissions:"calculatedColumn_create"
,"calculatedColumn_delete"
,"calculatedColumn_edit"
,"calculatedColumn_add_to_view"
,"calculatedColumn_remove_from_view"
-
Custom Role-Permission mappings may be provided via AdaptableProps.authRoles:
<Adaptable.Provider
authRoles={{
calculatedColumnEditor: ['calculatedColumn_edit'],
}}
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['calculatedColumnEditor'],
},
}}
{...restOfProps}
>
<Adaptable.UI />
</Adaptable.Provider>
- Some object definitions may override the standard permissions with permission flags:
editable
,deletable
.
Customising user permissioning
Note
If no userInfo.auth
prop is provided, the user has all permissions for the available modules.
As soon as a custom UserAuthorization
is provided via userInfo.auth
, the user ONLY has the provided roles and/or permissions.
User specific permission checking is performed on 3 levels (3. has the highest priority, 1. the lowest):
- Declarative permissions defined via
UserAuthorization.roles
&UserAuthorization.permissions
:
E.g. user has all permissions authorised for styledCellAdmin
and additionally the calculatedColumn_edit
permission
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['styledCellAdmin'],
permissions: ['calculatedColumn_edit'],
},
}}
Note
A specific permission may be negated (excluded from the authorised roles) by prepending it with !
e.g. User is authorised for all "styledCellAdmin"
permission (create, edit, addToView, etc.), except for "styledCell_delete"
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['styledCellAdmin'],
permissions: ['!styledCell_delete'],
},
}}
- Custom object permission flags: editable, deletable
e.g. even if a user has the
"styledCell_delete"
permission, it won't be able to delete a StyledCell definition with thedeletable=false
flag:
'style-cell-1': {
label: 'style-cell-1',
scope: {
columns: ['name'],
},
style: {
background: 'fuchsia',
},
permissions: {
deletable: false,
},
},
- Custom permission check function
UserAuthorization.checkPermission?: (context: CheckPermissionContext) => boolean
export interface CheckPermissionContext extends BaseContext {
adaptableId: string;
userId: string;
userName: string;
permission: AdaptablePermission;
defaultPermissionCheckResult: boolean;
adaptableObject?: AdaptableObject<AdaptableObjectDef>;
userPermissions: AdaptablePermission[];
}
If provided, the function will be invoked for each permission check and will override the default permission check result (which is provided in the params).
<Adaptable.Provider
authRoles={{
calculatedColumnEditor: ['calculatedColumn_edit'],
}}
userInfo={{
userId: 'ID_123456',
userName: 'John Doe',
auth: {
roles: ['styledCellAdmin', 'calculatedColumnAdmin', 'calculatedColumnEditor'],
permissions: ['!calculatedColumn_edit'],
checkPermission: (context: CheckPermissionContext) => {
if (context.permission === 'calculatedColumn_add_to_view') {
return invokeSomeExternalService(context.userId, context.permission);
}
return context.defaultPermissionCheckResult;
},
},
}}
{...restOfProps}
>
<Adaptable.UI />
</Adaptable.Provider>