auth.service.ts 3.9 KB

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