@opentiny/tiny-toolkit-pro
Version:
TinyPro Vue:开箱即用、前后端分离的 Vue 后台管理模板
58 lines (55 loc) • 1.8 kB
text/typescript
import {
CanActivate,
ExecutionContext,
HttpException,
HttpStatus,
Injectable,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { UserService } from '../user/user.service';
import { Request } from 'express';
import { User } from '@app/models';
import { PERMISSION_KEYS } from '../public/permission.decorator';
import { I18nTranslations } from '../.generate/i18n.generated';
import { I18nContext } from 'nestjs-i18n';
interface CustomReq extends Request {
user: User;
}
()
export class PermissionGuard implements CanActivate {
constructor(private reflector: Reflector, private userSerivce: UserService) {}
async canActivate(ctx: ExecutionContext) {
const i18n = I18nContext.current<I18nTranslations>();
const req: CustomReq = ctx.switchToHttp().getRequest();
const requiredPermission = this.reflector.getAllAndOverride<string[]>(
PERMISSION_KEYS,
[ctx.getClass(), ctx.getHandler()]
);
if (!requiredPermission || requiredPermission.length === 0) {
return true;
}
const [, token] = (req.headers.authorization ?? '').split(' ') ?? ['', ''];
const permissionNames = await this.userSerivce.getUserPermission(
token,
req.user
);
const isContainedPermission = requiredPermission.every((item) =>
permissionNames.includes(item)
);
if (permissionNames.includes('*')) {
return true;
}
if (!isContainedPermission) {
throw new HttpException(
i18n.t('exception.common.forbidden', {
lang: I18nContext.current().lang,
args: {
permission: requiredPermission.join(','),
},
}),
HttpStatus.FORBIDDEN
);
}
return true;
}
}