Authorization functionality
When building features in EVA Suite, we should make sure that only users with the right role can access/modify things in EVA.
In order to do that we use Functionalities
and FunctionalityScope
to make sure users won't get the option to use something that is not intended for them to use.
Here is a list where you can find every functionality and the services that require said functionality.
Structure:
{ "{FunctionalityScope}.{Functionality}": [ "service1", "service2", ... ], ...}
#
FuntionalitiesWhen logging in to a EVA Suite module you can see that we call the GetAuthorizationStructure
service. This is an example of part of a response you might get from this service:
{ "RoleName": "New Black", "ScopedFunctionalities": { "AccessPrivacyDataRequests": 0, "AccessPrivacyRemovalRequests": 0, "Accounts": 31, "AdjustStock": 0, "AnonymousTokens": 31, "ApiKeys": 31, "AppSettings": 31, ... }, ...}
RoleName
is the name of role the user has based on the organization unit and user account.ScopedFunctionalities
contains the functionalities the role has access to.
Access to a functionality is determined by name ('AppSettings') and by scope.
#
FunctionalityScopeThe FunctionalityScope determines what type of rights users have on a Functionality. These are the types that are available:
export enum FunctionalityScope { None = 0, Create = 1, Edit = 2, Delete = 4, View = 8, Manage = 31,}
The scopes are pretty self explanatory. The Manage
scope means that you have full access to the functionality.
#
Hide navigation to chaptersNavigation to chapters should be shown based upon the 'View' scope on a functionality.
#
ExampleWhen you have to build a chapter called: 'Orders' the corresponding functionality is 'Orders'. Only when a user has view rights to that order, the navigation label to the orders chapter in de sidenavigation should be shown.
// components/shared/side-navimport { useMemo } from 'react';import { useIntl } from 'react-intl';import { useHasFunctionality, FunctionalityScope,} from '@springtree/eva-suite-react-hooks';import { hooks, state } from '@springtree/eva-sdk-react-recoil';
const SideNav = () => { const intl = useIntl();
// Current Organization ID const ouID = hooks.useGetState(state.currentUser.currentUserState.response) ?.User.CurrentOrganizationID;
const { functionalityAllowed: ordersViewAllowed } = useHasFunctionality( 'Orders', FunctionalityScope.View, ouID );
const routes = useMemo<IRoute[]>(() => { const ordersRoute: IRoute = { name: intl.formatMessage({ id: 'orders.chapter.title' }), url: '/orders', icon: <FileCopyIcon />, };
const authorizedRoutes: IRoute[] = [];
if (ordersViewAllowed) { authorizedRoutes.push(ordersRoute); }
return authorizedRoutes; }, [intl, orchestrationViewAllowed, ordersViewAllowed]);
return ( <EvaSideNav closeSidebarText={intl.formatMessage({ id: 'sidebar.close' })} routes={routes} /> );};
#
Hide or disable actions based on functionalityWhen you create buttons to pages where things can be created or updated, you should also check if users have the rights to do so. So when you see a create/update/delete button you should check with the useHasFunctionality hook if the user has the right to do so. If not, you should disable or hide the button. When the issue does not describe what to do, disable the button. You could add a helpful tooltip why the user can not click on the button.
#
Exampleimport { useCallback } from 'react';import { useHasFunctionality, FunctionalityScope,} from '@springtree/eva-suite-react-hooks';import { hooks, state } from '@springtree/eva-sdk-react-recoil';
const UpdateProductButton = () => { // Current Organization ID const ouID = hooks.useGetState(state.currentUser.currentUserState.response) ?.User.CurrentOrganizationID;
const { functionalityAllowed: productUpdateAllowed } = useHasFunctionality( 'Product', FunctionalityScope.Edit, ouID );
const updateProduct = useCallback(() => { if (productUpdateAllowed) { console.log('update product'); } }, [productUpdateAllowed]);
return ( <Button onClick={updateProduct} disabled={!productUpdateAllowed}> Update product </Button> );};