import { HttpService } from '@nestjs/axios'; import { HttpException, Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { JwtService } from '@nestjs/jwt'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { catchError, lastValueFrom, map } from 'rxjs'; import { User, UserDocument } from './models/user.model'; @Injectable() export class AuthService { constructor( @InjectModel('user') private readonly userModel: Model, private config: ConfigService, private httpService: HttpService, private jwtService: JwtService, ) {} async login(code: string): Promise { const [token, refreshToken] = await lastValueFrom( this.httpService .post( `${this.config.get( 'vatsim-auth.base-url', )}/${this.config.get('vatsim-auth.token-endpoint')}`, { grant_type: 'authorization_code', client_id: this.config.get('vatsim-auth.client-id'), client_secret: this.config.get('vatsim-auth.client-secret'), redirect_uri: 'http://localhost:3000/auth/vatsim', code, }, ) .pipe( map((response) => [ response.data.access_token, response.data.refresh_token, ]), catchError((err) => { throw new HttpException(err.response.data, err.response.status); }), ), ); const userdata = await lastValueFrom( this.httpService .get( `${this.config.get( 'vatsim-auth.base-url', )}/${this.config.get('vatsim-auth.user-endpoint')}`, { headers: { Authorization: `Bearer ${token}`, Accept: 'application/json', }, }, ) .pipe( map((response) => response.data.data), catchError((err) => { throw new HttpException(err.response.data, err.response.status); }), ), ); if (userdata.oauth.token_valid) { let fullName = ''; if (userdata.personal !== undefined) { fullName = userdata.personal.name_full; } this.userModel.findOne({ vatsimId: userdata.cid }).then((user) => { if (!user) { this.userModel.create({ vatsimId: userdata.cid, fullName, vatsimToken: token, vatsimRefreshToken: refreshToken, }); } else { this.userModel.findOneAndUpdate( { vatsimId: userdata.cid }, { fullName, vatsimToken: token, vatsimRefreshToken: refreshToken, }, ); } }); const payload = { vatsimId: userdata.cid, sub: token }; return this.jwtService.sign(payload); } return undefined; } async user(token: string): Promise { const payload = this.jwtService.verify(token, { secret: this.config.get('server.jwt-secret'), }); return this.userModel .findOne({ vatsimId: payload.vatsimId }) .then((user) => { if (!user) return undefined; return user; }); } }