auth.service.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import { HttpService } from '@nestjs/axios';
  2. import { HttpException, Injectable } from '@nestjs/common';
  3. import { ConfigService } from '@nestjs/config';
  4. import { JwtService } from '@nestjs/jwt';
  5. import { InjectModel } from '@nestjs/mongoose';
  6. import { Model } from 'mongoose';
  7. import { catchError, lastValueFrom, map } from 'rxjs';
  8. import { User, UserDocument } from './models/user.model';
  9. @Injectable()
  10. export class AuthService {
  11. constructor(
  12. @InjectModel('user')
  13. private readonly userModel: Model<UserDocument>,
  14. private config: ConfigService,
  15. private httpService: HttpService,
  16. private jwtService: JwtService,
  17. ) {}
  18. async login(code: string): Promise<string> {
  19. const [token, refreshToken] = await lastValueFrom(
  20. this.httpService
  21. .post(
  22. `${this.config.get<string>(
  23. 'vatsim-auth.base-url',
  24. )}/${this.config.get<string>('vatsim-auth.token-endpoint')}`,
  25. {
  26. grant_type: 'authorization_code',
  27. client_id: this.config.get<string>('vatsim-auth.client-id'),
  28. client_secret: this.config.get<string>('vatsim-auth.client-secret'),
  29. redirect_uri: 'http://localhost:3000/auth/vatsim',
  30. code,
  31. },
  32. )
  33. .pipe(
  34. map((response) => [
  35. response.data.access_token,
  36. response.data.refresh_token,
  37. ]),
  38. catchError((err) => {
  39. throw new HttpException(err.response.data, err.response.status);
  40. }),
  41. ),
  42. );
  43. const userdata = await lastValueFrom(
  44. this.httpService
  45. .get(
  46. `${this.config.get<string>(
  47. 'vatsim-auth.base-url',
  48. )}/${this.config.get<string>('vatsim-auth.user-endpoint')}`,
  49. {
  50. headers: {
  51. Authorization: `Bearer ${token}`,
  52. Accept: 'application/json',
  53. },
  54. },
  55. )
  56. .pipe(
  57. map((response) => response.data.data),
  58. catchError((err) => {
  59. throw new HttpException(err.response.data, err.response.status);
  60. }),
  61. ),
  62. );
  63. if (userdata.oauth.token_valid) {
  64. let fullName = '';
  65. if (userdata.personal !== undefined) {
  66. fullName = userdata.personal.name_full;
  67. }
  68. this.userModel.findOne({ vatsimId: userdata.cid }).then((user) => {
  69. if (!user) {
  70. this.userModel.create({
  71. vatsimId: userdata.cid,
  72. fullName,
  73. vatsimToken: token,
  74. vatsimRefreshToken: refreshToken,
  75. });
  76. } else {
  77. this.userModel.findOneAndUpdate(
  78. { vatsimId: userdata.cid },
  79. {
  80. fullName,
  81. vatsimToken: token,
  82. vatsimRefreshToken: refreshToken,
  83. },
  84. );
  85. }
  86. });
  87. const payload = { vatsimId: userdata.cid, sub: token };
  88. return this.jwtService.sign(payload);
  89. }
  90. return undefined;
  91. }
  92. async user(token: string): Promise<User> {
  93. const payload = this.jwtService.verify(token, {
  94. secret: this.config.get<string>('server.jwt-secret'),
  95. });
  96. return this.userModel
  97. .findOne({ vatsimId: payload.vatsimId })
  98. .then((user) => {
  99. if (!user) return undefined;
  100. return user;
  101. });
  102. }
  103. }