Access Control Cookbook
Обмежити доступ до розділу
Route Access Guard має це зробити, якщо на роут правильно вказані метадані.
// router.ts
import { WtApplication, CrmSections, WtObject } from '@webitel/ui-sdk/enums';
const routes = [
{
path: '/',
name: 'crm-workspace',
meta: {
WtApplication: WtApplication.Crm,
},
children: [
// ...
{
path: 'contacts',
meta: {
UiSection: CrmSections.Contacts,
WtObject: WtObject.Contact,
},
},
],
},
];IMPORTANT
Якщо не робе, а все налаштовано правильно, то перевірте чи ініціалізований роут гард в main.ts
В середині компонента-карточки перевірити права для сутності, вказаної в роутинг метадаті
Про router meta приклад вище.
// opened-user-general.vue
import { useUserAccessControl } from './.. ../app/composables/useUserAccessControl';
const {
disableUserInput,
hasCreateAccess,
hasDeleteAccess,
hasUpdateAccess,
} = useUserAccessControl(/* ! */); // якщо немає параметра, то роздупляється по route metaПеревірка прав до певного Обʼєкта
Типовий кейс: заборонити редагувати конкретне поле-селект в карточці, якщо немає прав на Обʼєкт, який в тому селекті обирається.
Наприклад: User має поле Contact, але якщо немає прав на читання Contact, то і поле показувати немає сенсу – буде помилка.
// opened-user-general.vue
import { WtObject } from '@webitel/ui-sdk/enums';
import { useUserAccessControl } from './.. ../app/composables/useUserAccessControl';
const { hasReadAccess: hasContactsReadAccess } = useUserAccessControl(
WtObject.Contact,
);Перевірка Прав на конкретний роут за межами роутера
Наприклад, нам треба порахувати в компоненті чи сторі доступну для користувача навігацію.
А отже треба певні роути перевірити на access guard, але не як beforeEnter роутер хук, а всі ті роути "прогнати" через гард, щоб задізейблити недоступні.
// crm -> navStore.ts
const router = useRouter();
const { routeAccessGuard } = useUserinfoStore();
const nav = computed(() => {
const contactsRoutePath = '/contacts';
const contactsRoute = router.resolve({
path: contactsRoutePath,
});
const hasContactsAccess = routeAccessGuard(contactsRoute) === true;
// ...
});Перевірка на Специфічні Права Ролі
Наприклад, треба перевірити чи (цей) користувач може переглядати екран операторів у супервізорі (за це відповідає окреме право у Admin/Permissions/Roles -> Permissions tab)
import { SpecialGlobalAction } from '@webitel/ui-sdk/modules/Userinfo';
import { useUserinfoStore } from '../.. ../userinfoStore'; // this app userinfoStore
const userinfoStore = useUserinfoStore();
const isControlAgentScreenAllow = computed(() =>
userinfoStore.hasSpecialGlobalActionAccess(
SpecialGlobalAction.ControlAgentScreen,
),
);Сховати колонку таблиці, до якої немає прав
show у хедера — це налаштування користувача, а не право. Тому в хедерс-сторі ui-datalist у хедера є окремий опційний геттер access.
Типовий кейс: у реєстрі є колонка, яка показує сутність, до якої у користувача може не бути доступу.
Наприклад: History / Registry має колонку "Запис екрану", але якщо немає права Control agent screen, то і колонки бути не повинно – вкладка запису екрану в візуалізації дзвінка вже і так схована.
// cc-history -> registry/store/headers/headers.ts
import { SpecialGlobalAction } from '@webitel/ui-sdk/modules/Userinfo';
import { useUserinfoStore } from '../.. ../userinfoStore'; // this app userinfoStore
const controlAgentScreenAccess = () =>
useUserinfoStore().hasSpecialGlobalActionAccess(
SpecialGlobalAction.ControlAgentScreen,
);
const rawHeaders: DatalistTableHeader[] = [
// ...
{
value: 'screencast',
field: 'screencast',
show: false,
access: controlAgentScreenAccess,
},
];Якщо access повертає false, колонка зникає повністю, а не просто стає show: false:
- її немає в пікері колонок (тобто її не можна додати назад руками);
- вона не рендериться в таблиці;
- її
fieldне потрапляє вfieldsзапиту – бекенд ці дані навіть не віддає; - її не відновить збережений стан (
localStorageчи?fields=в роуті).
Так само можна перевіряти і права на Обʼєкт:
import { WtObject } from '@webitel/ui-sdk/enums';
const readAccessTo = (object: WtObject) => () =>
useUserinfoStore().hasReadAccess(object);
// ...
{
value: 'agent',
field: 'agent',
access: readAccessTo(WtObject.Agent),
},IMPORTANT
Беріть методи прямо зі стора (hasReadAccess, hasSpecialGlobalActionAccess), а не useUserAccessControl. Композабл всередині кличе useRoute(), а access виконується в тілі стора, де роута може не бути. Але якщо дуже треба – Ref<boolean> теж приймається.
TIP
access рахується один раз, коли створюється хедерс-стор. Це нормально: права приїжджають на старті апки і в межах сесії не міняються. Якщо access не вказано – колонка доступна. Тобто всі старі хедери працюють як і працювали.
Перевірка Прав на вкладену сутність в карточці через Update
TIP
Читайте вдумливо, кейс специфічний і важливий!
Це специфічна перевірка прав для табличок які є табами в карточках, утворюючи звʼязок one-to-many між цими сутностями.
Або просто child-сутності, Create/Read/Delete робота з якими все одно керується тільки правом Update перента.
Наприклад:
- Admin / Contact Center / Agents -> Skills tab
В карточці Агента, в табі його (!) Скілів у нас є дії Додавання, Редагування і Видалення.
Але фактично вони регулюються одним правом: правом на Update цього Агента, в карточці якого ми знаходимось.
Тому що, фактично, ми апдейтимо Запис Агента, Додаючи/Оновлюючи/Забираючи його Навичку.

// Admin -> opened-agent-skills.vue
const { disableUserInput } = useUserAccessControl({
useUpdateAccessAsAllMutableChecksSource: true,
});Ще приклади, де таке зустрічається:
- CRM / Cases -> Case links
- CRM / SLA -> SLA Conditions
- Admin / Queues -> Skills
- Admin / Queues -> Members
useUserAccessStore() з Global Role Permissions
Коли ми працюємо із якимось специфічним обʼєктом, який не має свого власного ObAC, і має керуватися глобальними правами ролі.
Наприклад:
- Users -> Tokens
- Permissions tab в карточках сутностей
- License
// Admin -> hasUserTokensAccess.ts
const {
hasReadAccess: hasGlobalReadAccess,
disableUserInput: disableUserInputGlobalAccess,
hasDeleteAccess: hasGlobalDeleteAccess,
hasCreateAccess: hasGlobalCreateAccess,
hasUpdateAccess: hasGlobalUpdateAccess,
} = useUserAccessControl({
useGlobalAccessAsChecksSource: true,
});Перевірка наявності конкретної ліцензії
Наразі це специфічні кейси для Workspace, де треба перевірити чи є у користувача конкретна ліцензія для роботи з певним функціоналом.
Наприклад, для роботи агента з контактами:
// Workspace -> call-contacts-container.vue
import {
WebitelLicense,
} from '@webitel/ui-sdk/modules/Userinfo';
const { hasLicense } = useUserinfoStore();
const hasCallCenterLicense = computed(() =>
hasLicense(WebitelLicense.CallCenter),
);