base-auth.resolver.ts 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { Request, Response } from 'express';
  2. import { LoginMutationArgs, LoginResult } from '../../../../../shared/generated-types';
  3. import { InternalServerError } from '../../../common/error/errors';
  4. import { ConfigService } from '../../../config/config.service';
  5. import { User } from '../../../entity/user/user.entity';
  6. import { AuthService } from '../../../service/services/auth.service';
  7. import { UserService } from '../../../service/services/user.service';
  8. import { extractAuthToken } from '../../common/extract-auth-token';
  9. import { RequestContext } from '../../common/request-context';
  10. import { setAuthToken } from '../../common/set-auth-token';
  11. export class BaseAuthResolver {
  12. constructor(
  13. protected authService: AuthService,
  14. protected userService: UserService,
  15. protected configService: ConfigService,
  16. ) {}
  17. /**
  18. * Attempts a login given the username and password of a user. If successful, returns
  19. * the user data and returns the token either in a cookie or in the response body.
  20. */
  21. async login(
  22. args: LoginMutationArgs,
  23. ctx: RequestContext,
  24. req: Request,
  25. res: Response,
  26. ): Promise<LoginResult> {
  27. return await this.createAuthenticatedSession(ctx, args, req, res);
  28. }
  29. async logout(req: Request, res: Response): Promise<boolean> {
  30. const token = extractAuthToken(req, this.configService.authOptions.tokenMethod);
  31. if (!token) {
  32. return false;
  33. }
  34. await this.authService.deleteSessionByToken(token);
  35. setAuthToken({
  36. req,
  37. res,
  38. authOptions: this.configService.authOptions,
  39. rememberMe: false,
  40. authToken: '',
  41. });
  42. return true;
  43. }
  44. /**
  45. * Returns information about the current authenticated user.
  46. */
  47. async me(ctx: RequestContext) {
  48. const userId = ctx.activeUserId;
  49. const user = userId && (await this.userService.getUserById(userId));
  50. return user ? this.publiclyAccessibleUser(user) : null;
  51. }
  52. /**
  53. * Creates an authenticated session and sets the session token.
  54. */
  55. protected async createAuthenticatedSession(
  56. ctx: RequestContext,
  57. args: LoginMutationArgs,
  58. req: Request,
  59. res: Response,
  60. ) {
  61. const session = await this.authService.authenticate(ctx, args.username, args.password);
  62. setAuthToken({
  63. req,
  64. res,
  65. authOptions: this.configService.authOptions,
  66. rememberMe: args.rememberMe || false,
  67. authToken: session.token,
  68. });
  69. return {
  70. user: this.publiclyAccessibleUser(session.user),
  71. };
  72. }
  73. /**
  74. * Updates the password of an existing User.
  75. */
  76. protected async updatePassword(
  77. ctx: RequestContext,
  78. currentPassword: string,
  79. newPassword: string,
  80. ): Promise<boolean> {
  81. const { activeUserId } = ctx;
  82. if (!activeUserId) {
  83. throw new InternalServerError(`error.no-active-user-id`);
  84. }
  85. const user = await this.userService.getUserById(activeUserId);
  86. if (!user) {
  87. throw new InternalServerError(`error.no-active-user-id`);
  88. }
  89. return this.userService.updatePassword(user, currentPassword, newPassword);
  90. }
  91. /**
  92. * Exposes a subset of the User properties which we want to expose to the public API.
  93. */
  94. private publiclyAccessibleUser(user: User): any {
  95. return {
  96. id: user.id,
  97. identifier: user.identifier,
  98. channelTokens: this.getAvailableChannelTokens(user),
  99. };
  100. }
  101. private getAvailableChannelTokens(user: User): string[] {
  102. return user.roles.reduce((tokens, role) => role.channels.map(c => c.token), [] as string[]);
  103. }
  104. }