roles-guard.ts 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import { CanActivate, ExecutionContext, UseGuards } from '@nestjs/common';
  2. import { AuthGuard } from '@nestjs/passport';
  3. import { ExtractJwt, Strategy } from 'passport-jwt';
  4. import { UserEntity } from '../entity/user/user.entity';
  5. import { Role } from './role';
  6. /**
  7. * A guard which combines the JWT passport auth method with restrictions based on
  8. * the authenticated user's roles.
  9. *
  10. * @example
  11. * ```
  12. * @RolesGuard([Role.Superadmin])
  13. * @Query('administrators')
  14. * getAdministrators() {
  15. * // ...
  16. * }
  17. * ```
  18. */
  19. export function RolesGuard(roles: Role[]) {
  20. const guards: CanActivate[] = [AuthGuard('jwt')];
  21. if (roles.length && !authenticatedOnly(roles)) {
  22. guards.push(forRoles(roles));
  23. }
  24. return UseGuards(...guards);
  25. }
  26. function authenticatedOnly(roles: Role[]): boolean {
  27. return roles.length === 1 && roles[0] === Role.Authenticated;
  28. }
  29. /**
  30. * A guard which specifies which roles are authorized to access a given
  31. * route or property in a Controller / Resolver.
  32. */
  33. function forRoles(roles: Role[]) {
  34. return {
  35. canActivate(context: ExecutionContext) {
  36. const user: UserEntity = context.switchToHttp().getRequest().user;
  37. if (!user) {
  38. return false;
  39. }
  40. return arraysIntersect(roles, user.roles);
  41. },
  42. } as CanActivate;
  43. }
  44. /**
  45. * Returns true if any element of arr1 appears in arr2.
  46. */
  47. function arraysIntersect(arr1, arr2): boolean {
  48. return arr1.reduce((intersects, role) => {
  49. return intersects || arr2.includes(role);
  50. }, false);
  51. }