Skip to main content

2FA (Two-factor Auth)

Permissions могут работать сообща с 2FAService.

Пример

Требования

Создание документа доступно только администратору с активной 2FA.

Реализация

modules/permissions/domain/stores/PermissionsStore/policies/AdministrationPolicyStore

export class AdministrationPolicyStore {
private readonly policy: Policy;

constructor(
private readonly policyManager: PolicyManagerStore,
private readonly userRepo: UserRepository,
private readonly twoFA: TwoFAService,
) {
makeAutoObservable(this, {}, { autoBind: true });

this.policy = this.policyManager.createPolicy({
name: 'administration',
prepareData: async (): Promise<void> => {
await Promise.all([this.userRepo.getRolesQuery().async()]);
},
});
}

/**
* Доступ к действиям администратора
*/
public get administrationActions() {
return this.policy.createPermission((allow, deny) => {
// Если twoFA не пройдена, то отказываем в доступе с причиной, которая будет обработана в features
// Также, по необходимости, можно вызвать логику запроса от пользователя прохождения 2FA
if (!twoFA.isPassed) {
return deny(PermissionDenialReason.TwoFA);
}

if (this.userRepo.getRolesQuery().data?.isAdmin) {
return allow();
}

deny(PermissionDenialReason.NoAdmin);
});
}
}

modules/layout/features/MainLayout/Sidebar/UIStore

export class UIStore {
constructor(
private readonly permissions: PermissionsStore,
private readonly twoFA: TwoFAService,
private readonly notifyService: Notify,
private readonly router: Router,
) {
makeAutoObservable(this, {}, { autoBind: true });
}

public openDocCreation = () => {
const permission = this.permissions.administration.administrationActions;

if (permission.isAllowed) {
this.router.push(APP_ROUTES.createDoc.getRedirectPath());

return;
}

if (permission.hasReason(PermissionDenialReason.NoAdmin)) {
this.notifyService.error(
'Доступно только администратору'
);

return;
}

if (permission.hasReason(PermissionDenialReason.TwoFA)) {
// Здесь можно, например, реализовать открытие модалки для 2FA
this.notifyService.error(
'Нужно пройти 2FA',
);

return;
}

this.notifyService.error(
'Добавить документ на полку нельзя. Попробуйте сменить аккаунт',
);
};
}