auth-guard.ts 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
  2. import { Reflector } from '@nestjs/core';
  3. import { GqlExecutionContext } from '@nestjs/graphql';
  4. import { Request, Response } from 'express';
  5. import { Permission } from 'shared/generated-types';
  6. import { ConfigService } from '../../config/config.service';
  7. import { Session } from '../../entity/session/session.entity';
  8. import { AuthService } from '../../service/services/auth.service';
  9. import { extractAuthToken } from '../common/extract-auth-token';
  10. import { REQUEST_CONTEXT_KEY, RequestContextService } from '../common/request-context.service';
  11. import { setAuthToken } from '../common/set-auth-token';
  12. import { PERMISSIONS_METADATA_KEY } from '../decorators/allow.decorator';
  13. /**
  14. * A guard which checks for the existence of a valid session token in the request and if found,
  15. * attaches the current User entity to the request.
  16. */
  17. @Injectable()
  18. export class AuthGuard implements CanActivate {
  19. strategy: any;
  20. constructor(
  21. private reflector: Reflector,
  22. private configService: ConfigService,
  23. private authService: AuthService,
  24. private requestContextService: RequestContextService,
  25. ) {}
  26. async canActivate(context: ExecutionContext): Promise<boolean> {
  27. const ctx = GqlExecutionContext.create(context).getContext();
  28. const req: Request = ctx.req;
  29. const res: Response = ctx.res;
  30. const authDisabled = this.configService.authOptions.disableAuth;
  31. const permissions = this.reflector.get<Permission[]>(PERMISSIONS_METADATA_KEY, context.getHandler());
  32. const isPublic = !!permissions && permissions.includes(Permission.Public);
  33. const hasOwnerPermission = !!permissions && permissions.includes(Permission.Owner);
  34. const session = await this.getSession(req, res, hasOwnerPermission);
  35. const requestContext = await this.requestContextService.fromRequest(req, permissions, session);
  36. req[REQUEST_CONTEXT_KEY] = requestContext;
  37. if (authDisabled || !permissions || isPublic) {
  38. return true;
  39. } else {
  40. return requestContext.isAuthorized || requestContext.authorizedAsOwnerOnly;
  41. }
  42. }
  43. private async getSession(
  44. req: Request,
  45. res: Response,
  46. hasOwnerPermission: boolean,
  47. ): Promise<Session | undefined> {
  48. const authToken = extractAuthToken(req, this.configService.authOptions.tokenMethod);
  49. if (authToken) {
  50. const session = await this.authService.validateSession(authToken);
  51. if (!session) {
  52. // if there is a token but it cannot be validated to a Session,
  53. // then the token is no longer valid and should be unset.
  54. setAuthToken({
  55. req,
  56. res,
  57. authOptions: this.configService.authOptions,
  58. rememberMe: false,
  59. authToken: '',
  60. });
  61. }
  62. return session;
  63. } else if (hasOwnerPermission) {
  64. const session = await this.authService.createAnonymousSession();
  65. setAuthToken({
  66. authToken: session.token,
  67. rememberMe: true,
  68. authOptions: this.configService.authOptions,
  69. req,
  70. res,
  71. });
  72. return session;
  73. }
  74. }
  75. }