Skip to main content

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",    ...  ],  ...}

Funtionalities#

When 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.

FunctionalityScope#

The 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 chapters#

Navigation to chapters should be shown based upon the 'View' scope on a functionality.

Example#

When 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 functionality#

When 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.

Example#

import { 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>  );};