diff --git a/src/__tests__/auth/AuthService/createTestingSessionTokens.test.ts b/src/__tests__/auth/AuthService/createTestingSessionTokens.test.ts new file mode 100644 index 000000000..9be4fd58f --- /dev/null +++ b/src/__tests__/auth/AuthService/createTestingSessionTokens.test.ts @@ -0,0 +1,40 @@ +import { JwtPayload } from "jsonwebtoken"; +import { AuthService } from "../../../auth/auth.service"; +import AuthModule from '../modules/auth.module'; + +describe('AuthService.createTestingSessionTokens() test suite', () => { + let authService: AuthService; + + beforeEach(async () => { + authService = await AuthModule.getAuthService(); + }); + + it('Should return access and refresh tokens and expiration dates', async () => { + const payload = { + profile_id: '12345', + player_id: '12345', + tokenVersion: 0, + }; + + const result = await authService.createTestingSessionTokens(payload); + + const accessToken = authService['jwtService'].decode( + result.accessToken, + ) as JwtPayload; + + const refreshToken = authService['jwtService'].decode( + result.refreshToken, + ) as JwtPayload; + + expect(accessToken.profile_id).toBe(payload.profile_id); + expect(accessToken.player_id).toBe(payload.player_id); + + expect(refreshToken.profile_id).toBe(payload.profile_id); + expect(refreshToken.player_id).toBe(payload.player_id); + expect(refreshToken.tokenVersion).toBe(payload.tokenVersion); + expect(refreshToken.type).toBe('refresh'); + + expect(result.tokenExpires).toBe(accessToken.exp); + expect(result.refreshTokenExpires).toBe(refreshToken.exp); + }); +}); diff --git a/src/__tests__/auth/box/BoxAuthService/signIn.test.ts b/src/__tests__/auth/box/BoxAuthService/signIn.test.ts index 7761c92ae..8d91db325 100644 --- a/src/__tests__/auth/box/BoxAuthService/signIn.test.ts +++ b/src/__tests__/auth/box/BoxAuthService/signIn.test.ts @@ -128,14 +128,17 @@ describe('BoxAuthService.signIn() test suite', () => { await boxAuthService.signIn(validUsername, validPassword); - const expectedPayload = { - profile_id: existingAdminProfile._id.toString(), - player_id: createdPlayer._id.toString(), - box_id: existingBox._id.toString(), - groupAdmin: true, - }; - - expect(signAsyncSpy).toHaveBeenCalledWith(expectedPayload); + expect(signAsyncSpy).toHaveBeenCalledWith( + { + profile_id: existingAdminProfile._id.toString(), + player_id: createdPlayer._id.toString(), + box_id: existingBox._id.toString(), + groupAdmin: true, + tokenVersion: 0, + type: 'refresh', + }, + { expiresIn: '2d' }, + ); }); it('Should call signAsync() with payload containing groupAdmin set to true if the profile is group admin', async () => { @@ -144,14 +147,17 @@ describe('BoxAuthService.signIn() test suite', () => { await boxAuthService.signIn(validUsername, validPassword); - const expectedPayload = { - profile_id: existingAdminProfile._id.toString(), - player_id: createdPlayer._id.toString(), - box_id: existingBox._id.toString(), - groupAdmin: true, - }; - - expect(signAsyncSpy).toHaveBeenCalledWith(expectedPayload); + expect(signAsyncSpy).toHaveBeenCalledWith( + { + profile_id: existingAdminProfile._id.toString(), + player_id: createdPlayer._id.toString(), + box_id: existingBox._id.toString(), + groupAdmin: true, + tokenVersion: 0, + type: 'refresh', + }, + { expiresIn: '2d' }, + ); }); it('Should not return clan data if player is not in any clan', async () => { diff --git a/src/__tests__/auth/modules/authCommonModule.ts b/src/__tests__/auth/modules/authCommonModule.ts index 647f59b11..37cf72ef6 100644 --- a/src/__tests__/auth/modules/authCommonModule.ts +++ b/src/__tests__/auth/modules/authCommonModule.ts @@ -15,6 +15,7 @@ import { ProfileSchema } from '../../../profile/profile.schema'; import { PlayerSchema } from '../../../player/schemas/player.schema'; import { ClanSchema } from '../../../clan/clan.schema'; import { BoxTestingSessionGuard } from '../../../box/auth/boxTestingSession.guard'; +import { ProfileModule } from '../../../profile/profile.module'; export default class AuthCommonModule { private constructor() {} @@ -39,6 +40,7 @@ export default class AuthCommonModule { { name: ModelName.BOX, schema: BoxSchema }, { name: ModelName.GROUP_ADMIN, schema: GroupAdminSchema }, ]), + ProfileModule, ], providers: [ AuthService, diff --git a/src/__tests__/box/auth/BoxAuthHandler/getGroupAdminToken.test.ts b/src/__tests__/box/auth/BoxAuthHandler/getGroupAdminToken.test.ts index e1f377a41..e4840474b 100644 --- a/src/__tests__/box/auth/BoxAuthHandler/getGroupAdminToken.test.ts +++ b/src/__tests__/box/auth/BoxAuthHandler/getGroupAdminToken.test.ts @@ -1,37 +1,42 @@ +import ProfileBuilderFactory from '../../../../__tests__/profile/data/profileBuilderFactory'; import BoxAuthHandler from '../../../../box/auth/BoxAuthHandler'; import BoxBuilderFactory from '../../data/boxBuilderFactory'; import BoxModule from '../../modules/box.module'; -import { JwtService } from '@nestjs/jwt'; +import ProfileModule from '../../../../__tests__/profile/modules/profile.module'; describe('BoxAuthHandler.getGroupAdminToken() test suite', () => { let boxAuthHandler: BoxAuthHandler; const boxUserBuilder = BoxBuilderFactory.getBuilder('BoxUser'); const boxAdminUser = boxUserBuilder.setGroupAdmin(true).build(); + const profileModel = ProfileModule.getProfileModel(); + const profileBuilder = ProfileBuilderFactory.getBuilder('Profile'); + const profile = profileBuilder.set_id(boxAdminUser.profile_id).build(); + beforeEach(async () => { boxAuthHandler = await BoxModule.getBoxAuthHandler(); }); - it('Should call the JWTService.signAsync() with correct params', async () => { - const jwtMethod = jest - .spyOn(JwtService.prototype, 'signAsync') - .mockResolvedValueOnce('token'); - - await boxAuthHandler.getGroupAdminToken(boxAdminUser); + it('Should return access and refresh tokens and expiration times', async () => { + await profileModel.create(profile); - const { clan_id: _clan_id, ...clanIdOmittedUser } = boxAdminUser; + const [result, errors] = await boxAuthHandler.getGroupAdminToken(boxAdminUser); - expect(jwtMethod).toHaveBeenCalledTimes(1); - expect(jwtMethod).toHaveBeenCalledWith(clanIdOmittedUser); + expect(errors).toBeNull(); + expect(result).toEqual( + expect.objectContaining({ + accessToken: expect.any(String), + tokenExpires: expect.any(Number), + refreshToken: expect.any(String), + refreshTokenExpires: expect.any(Number), + }), + ); }); - it('Should return token from the JWTService.signAsync() response', async () => { - const jwtToken = 'returned-token'; - jest - .spyOn(JwtService.prototype, 'signAsync') - .mockResolvedValueOnce(jwtToken); + it('Should return NOT_FOUND error when profile does not exist', async () => { + const [result, errors] = await boxAuthHandler.getGroupAdminToken(boxAdminUser); - const returnedToken = await boxAuthHandler.getGroupAdminToken(boxAdminUser); - expect(returnedToken).toBe(jwtToken); + expect(result).toBeNull(); + expect(errors).toContainSE_NOT_FOUND(); }); }); diff --git a/src/__tests__/box/modules/boxCommon.ts b/src/__tests__/box/modules/boxCommon.ts index 9c431a359..c282269ee 100644 --- a/src/__tests__/box/modules/boxCommon.ts +++ b/src/__tests__/box/modules/boxCommon.ts @@ -32,6 +32,7 @@ import { envVars } from '../../../common/service/envHandler/envVars'; import UniqueFieldGenerator from '../../../box/util/UniqueFieldGenerator'; import { ItemSchema } from '../../../clanInventory/item/item.schema'; import { GameSchema } from '../../../gameData/game.schema'; +import { AuthModule } from '../../../auth/auth.module'; export default class BoxCommonModule { private constructor() {} @@ -67,6 +68,7 @@ export default class BoxCommonModule { JwtModule, DailyTasksModule, ChatModule, + AuthModule, ], providers: [ BoxService, diff --git a/src/auth/auth.module.ts b/src/auth/auth.module.ts index 35fef423b..d0e93018a 100644 --- a/src/auth/auth.module.ts +++ b/src/auth/auth.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { AuthService } from './auth.service'; import { AuthController } from './auth.controller'; import { RequestHelperModule } from '../requestHelper/requestHelper.module'; @@ -13,6 +13,7 @@ import { MongooseModule } from '@nestjs/mongoose'; import { PlayerSchema } from '../player/schemas/player.schema'; import { ProfileSchema } from '../profile/profile.schema'; import { ClanSchema } from '../clan/clan.schema'; +import { ProfileModule } from '../profile/profile.module'; @Module({ imports: [ @@ -29,9 +30,10 @@ import { ClanSchema } from '../clan/clan.schema'; { name: ModelName.BOX, schema: BoxSchema }, { name: ModelName.GROUP_ADMIN, schema: GroupAdminSchema }, ]), + forwardRef(() => ProfileModule), ], providers: [AuthService, BoxAuthService, AuthServiceProvider], controllers: [AuthController], - exports: [AuthService], + exports: [AuthService, BoxAuthService], }) export class AuthModule {} diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index a06fc2b81..5b1917738 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -10,6 +10,10 @@ import { InjectModel } from '@nestjs/mongoose'; import { Player } from '../player/schemas/player.schema'; import { Profile } from '../profile/profile.schema'; import { Clan } from '../clan/clan.schema'; +import { envVars } from '../common/service/envHandler/envVars'; +import { StringValue } from 'ms'; +import { TokensDto } from './dto/tokens.dto'; +import { TokenPayload } from './dto/tokenPayload.dto'; @Injectable() export class AuthService { @@ -174,4 +178,41 @@ export class AuthService { ]; } } + + /** + * Create Access and Refresh tokens + * + * Extracts the expiration time in Unix timestamp format + * + * @param payload User info used to create tokens + * @returns Access and Refresh tokens + expiration dates if successful + */ + public async createTestingSessionTokens( + payload: TokenPayload, + ):Promise { + const expiresIn = (envVars.JWT_EXPIRES ?? '30d') as StringValue; + + const refreshToken = await this.jwtService.signAsync( + {...payload, type: 'refresh'}, + { expiresIn }, + ); + const decodedRefreshToken = this.jwtService.decode(refreshToken); + const refreshTokenExpires = decodedRefreshToken?.exp; + + const { tokenVersion, ...accessPayload } = payload; + + const accessToken = await this.jwtService.signAsync( + accessPayload, + { expiresIn }, + ); + const decodedAccessToken = this.jwtService.decode(accessToken); + const tokenExpires = decodedAccessToken?.exp; + + return { + accessToken, + tokenExpires, + refreshToken, + refreshTokenExpires, + }; + } } diff --git a/src/auth/box/BoxAuthService.ts b/src/auth/box/BoxAuthService.ts index 48ee941aa..5232f0d9a 100644 --- a/src/auth/box/BoxAuthService.ts +++ b/src/auth/box/BoxAuthService.ts @@ -89,12 +89,10 @@ export default class BoxAuthService extends AuthService { player_id: player?._id, box_id, groupAdmin, + tokenVersion: profile.tokenVersion ?? 0, }; - const accessToken = await this.jwt.signAsync(payload); - const decodedAccessToken: any = this.jwt.decode(accessToken); - // Extract the expiration time in Unix timestamp format - const tokenExpires = decodedAccessToken?.exp; + const tokens = await this.createTestingSessionTokens(payload); profile['Player'] = player; @@ -108,8 +106,7 @@ export default class BoxAuthService extends AuthService { return { ...serializedProfile, - accessToken, - tokenExpires, + ...tokens, }; }; } diff --git a/src/auth/dto/signInResponse.dto.ts b/src/auth/dto/signInResponse.dto.ts index f794a20d8..14696218b 100644 --- a/src/auth/dto/signInResponse.dto.ts +++ b/src/auth/dto/signInResponse.dto.ts @@ -21,6 +21,22 @@ export class SignInResponseDto extends ProfileDto { @Expose() tokenExpires: number; + /** + * Refresh token to create new access token + * + * @example "eyJhbGciOiJIUzI1NiIsInR..." + */ + @Expose() + refreshToken: string; + + /** + * Refresh token expiration date + * + * @example 1735689600 + */ + @Expose() + refreshTokenExpires: number; + /** * Whether the profile has configured a security question. * diff --git a/src/auth/dto/tokenPayload.dto.ts b/src/auth/dto/tokenPayload.dto.ts new file mode 100644 index 000000000..038362af5 --- /dev/null +++ b/src/auth/dto/tokenPayload.dto.ts @@ -0,0 +1,51 @@ +import { Expose } from 'class-transformer'; +import AddType from '../../common/base/decorator/AddType.decorator'; + +@AddType('TokenPayload') +export class TokenPayload { + /** + * Profile Id + * + * @example "67fe4e2d8a54d4cc39266a43" + */ + @Expose() + profile_id: string; + + /** + * Player Id + * + * @example "67fe4e2d8a54d4cc39266a43" + */ + @Expose() + player_id: string; + + /** + * Id of Box session + */ + @Expose() + box_id?: string; + + /** + * Whether user is GroupAdmin or not + * + * @example false + */ + @Expose() + groupAdmin?: boolean; + + /** + * Token version + * + * @example 0 + */ + @Expose() + tokenVersion: number; + + /** + * Clan Id + * + * @example "67fe4e2d8a54d4cc39266a43" + */ + @Expose() + clan_id?: string; +} diff --git a/src/auth/dto/tokens.dto.ts b/src/auth/dto/tokens.dto.ts new file mode 100644 index 000000000..51f020b35 --- /dev/null +++ b/src/auth/dto/tokens.dto.ts @@ -0,0 +1,37 @@ +import { Expose } from 'class-transformer'; +import AddType from '../../common/base/decorator/AddType.decorator'; + +@AddType('TokensDto') +export class TokensDto { + /** + * Access token + * + * @example "eyJhbGciOiJIUzI1NiIsInR..." + */ + @Expose() + accessToken: string; + + /** + * Access token expiration time + * + * @example 1735689600 + */ + @Expose() + tokenExpires: number; + + /** + * Refresh token + * + * @example "eyJhbGciOiJIUzI1NiIsInR..." + */ + @Expose() + refreshToken: string; + + /** + * Refresh token expiration time + * + * @example 1735689600 + */ + @Expose() + refreshTokenExpires: number; +} diff --git a/src/box/accountClaimer/accountClaimer.service.ts b/src/box/accountClaimer/accountClaimer.service.ts index 66b709a30..44dbe9d00 100644 --- a/src/box/accountClaimer/accountClaimer.service.ts +++ b/src/box/accountClaimer/accountClaimer.service.ts @@ -1,5 +1,4 @@ import { Injectable } from '@nestjs/common'; -import { JwtService } from '@nestjs/jwt'; import ServiceError from '../../common/service/basicService/ServiceError'; import { SEReason } from '../../common/service/basicService/SEReason'; import BasicService from '../../common/service/basicService/BasicService'; @@ -15,13 +14,14 @@ import { endTransaction, initializeSession, } from '../../common/function/Transactions'; +import BoxAuthService from '../../auth/box/BoxAuthService'; @Injectable() export default class AccountClaimerService { constructor( @InjectModel(Box.name) private readonly boxModel: Model, private readonly testerService: TesterAccountService, - private readonly jwtService: JwtService, + private readonly boxAuthService: BoxAuthService, @InjectConnection() private readonly connection: Connection, ) { this.basicService = new BasicService(boxModel); @@ -86,19 +86,22 @@ export default class AccountClaimerService { if (clanAssigningErrors) return await cancelTransaction(session, clanAssigningErrors); - const accessToken = await this.jwtService.signAsync({ + const payload = { player_id: account.Player._id.toString(), profile_id: account.Profile._id.toString(), clan_id: accountClan._id.toString(), box_id: box._id.toString(), groupAdmin: false, - }); + tokenVersion: account.Profile.tokenVersion ?? 0, + }; + + const tokens = await this.boxAuthService.createTestingSessionTokens(payload); return await endTransaction(session, { ...account.Player, password: account.Profile.username, profile_id: account.Profile._id.toString(), - accessToken, + ...tokens, clan_id: accountClan._id.toString(), Clan: accountClan as ClanDto, }); diff --git a/src/box/accountClaimer/dto/claimedAccount.dto.ts b/src/box/accountClaimer/dto/claimedAccount.dto.ts index 21055c2e1..0fd42807e 100644 --- a/src/box/accountClaimer/dto/claimedAccount.dto.ts +++ b/src/box/accountClaimer/dto/claimedAccount.dto.ts @@ -3,8 +3,9 @@ import { ClanDto } from '../../../clan/dto/clan.dto'; import { ExtractField } from '../../../common/decorator/response/ExtractField'; import { GameStatisticsDto } from '../../../player/dto/gameStatistics.dto'; import { CustomCharacterDto } from '../../../player/customCharacter/dto/customCharacter.dto'; +import { TokensDto } from '../../../auth/dto/tokens.dto'; -export default class ClaimedAccountDto { +export default class ClaimedAccountDto extends TokensDto{ /** * Unique ID of the claimed account * @@ -101,14 +102,6 @@ export default class ClaimedAccountDto { @Expose() CustomCharacter: CustomCharacterDto[]; - /** - * Access token to authenticate future API requests - * - * @example "eyJhbGciOiJIUzI1NiIsInR..." - */ - @Expose() - accessToken: string; - /** * Player's account password * diff --git a/src/box/accountClaimer/payloads/claimedAccount.ts b/src/box/accountClaimer/payloads/claimedAccount.ts index 8cb0c307c..dc5e0a10b 100644 --- a/src/box/accountClaimer/payloads/claimedAccount.ts +++ b/src/box/accountClaimer/payloads/claimedAccount.ts @@ -1,7 +1,8 @@ +import { TokensDto } from '../../../auth/dto/tokens.dto'; import { ClanDto } from '../../../clan/dto/clan.dto'; import { ObjectId } from 'mongodb'; -export default class ClaimedAccount { +export default class ClaimedAccount extends TokensDto{ /** * Unique ID of the claimed account * @@ -70,13 +71,6 @@ export default class ClaimedAccount { */ Clan: ClanDto; - /** - * Access token to authenticate future API requests - * - * @example "eyJhbGciOiJIUzI1NiIsInR..." - */ - accessToken: string; - /** * Player's account password * diff --git a/src/box/auth/BoxAuthHandler.ts b/src/box/auth/BoxAuthHandler.ts index 74bbe787a..9ad2521bc 100644 --- a/src/box/auth/BoxAuthHandler.ts +++ b/src/box/auth/BoxAuthHandler.ts @@ -8,6 +8,9 @@ import { Model } from 'mongoose'; import { GroupAdmin } from '../groupAdmin/groupAdmin.schema'; import ServiceError from '../../common/service/basicService/ServiceError'; import { SEReason } from '../../common/service/basicService/SEReason'; +import { ProfileService } from '../../profile/profile.service'; +import BoxAuthService from '../../auth/box/BoxAuthService'; +import { TokensDto } from '../../auth/dto/tokens.dto'; type AuthTokenPayload = { profile_id: string; @@ -22,22 +25,33 @@ export default class BoxAuthHandler { @InjectModel(Box.name) public readonly boxModel: Model, @InjectModel(GroupAdmin.name) public readonly groupAdminModel: Model, + private readonly profileService: ProfileService, + private readonly boxAuthService: BoxAuthService, ) {} /** - * Generates am auth token for a group admin + * Generates auth tokens for a group admin * @param authPayload - * @returns auth token for the group admin + * @returns auth tokens for the group admin */ - async getGroupAdminToken(authPayload: AuthTokenPayload) { + async getGroupAdminToken(authPayload: AuthTokenPayload) + :Promise> + { + const [profile, profileErrors] = + await this.profileService.basicService.readOneById( + authPayload.profile_id + ); + if (profileErrors) return [null, profileErrors]; + const payload = { profile_id: authPayload.profile_id, player_id: authPayload.player_id, box_id: authPayload.box_id, groupAdmin: true, + tokenVersion: profile.tokenVersion ?? 0, }; - return this.jwt.signAsync(payload); + return [await this.boxAuthService.createTestingSessionTokens(payload), null]; } /** diff --git a/src/box/box.controller.ts b/src/box/box.controller.ts index 9f8796fc3..eaedfa074 100644 --- a/src/box/box.controller.ts +++ b/src/box/box.controller.ts @@ -35,10 +35,10 @@ import { GroupAdmin } from './groupAdmin/groupAdmin.schema'; import { Model } from 'mongoose'; import BasicService from '../common/service/basicService/BasicService'; import { NoBoxIdFilter } from './auth/decorator/NoBoxIdFilter.decorator'; -import { AdminSignInDto } from './dto/adminSignIn.dto'; import { Authorize } from '../authorization/decorator/Authorize'; import { Action } from '../authorization/enum/action.enum'; import { BoxTestingSessionGuard } from './auth/boxTestingSession.guard'; +import { TokensDto } from '../auth/dto/tokens.dto'; @Controller('box') @UseGuards(BoxAuthGuard, BoxTestingSessionGuard) @@ -79,13 +79,17 @@ export class BoxController { const [createdBox, errors] = await this.boxCreator.createBox(body); if (errors) return [null, errors]; - const groupAdminAccessToken = await this.authHandler.getGroupAdminToken({ + const [tokenData, tokenErrors] = await this.authHandler.getGroupAdminToken({ box_id: createdBox._id.toString(), player_id: createdBox.adminPlayer_id.toString(), profile_id: createdBox.adminProfile_id.toString(), }); + if (tokenErrors) return [null, tokenErrors]; - return [{ ...createdBox, accessToken: groupAdminAccessToken }, null]; + return [{ + ...createdBox, + ...tokenData, + }, null]; } /** @@ -96,7 +100,7 @@ export class BoxController { @ApiResponseDescription({ success: { status: 201, - dto: AdminSignInDto, + dto: TokensDto, modelName: ModelName.BOX, }, errors: [400, 404], @@ -104,19 +108,20 @@ export class BoxController { }) @NoAuth() @NoBoxIdFilter() - @UniformResponse(ModelName.BOX, AdminSignInDto) + @UniformResponse(ModelName.BOX, TokensDto) @Post('admin/signIn') async signIn(@Body() body: CreateBoxDto) { const [box, errors] = await this.service.readAdminBox(body); if (errors) return [null, errors]; - const groupAdminAccessToken = await this.authHandler.getGroupAdminToken({ + const [tokenData, tokenErrors] = await this.authHandler.getGroupAdminToken({ box_id: box._id.toString(), player_id: box.adminPlayer_id.toString(), profile_id: box.adminProfile_id.toString(), }); + if (tokenErrors) return [null, tokenErrors]; - return { accessToken: groupAdminAccessToken }; + return tokenData; } /** diff --git a/src/box/box.module.ts b/src/box/box.module.ts index 60d8ba7e2..64c0d23f2 100644 --- a/src/box/box.module.ts +++ b/src/box/box.module.ts @@ -31,6 +31,7 @@ import AccountClaimerService from './accountClaimer/accountClaimer.service'; import { TesterAccountService } from './accountClaimer/testerAccount.service'; import UniqueFieldGenerator from './util/UniqueFieldGenerator'; import { ItemSchema } from '../clanInventory/item/item.schema'; +import { AuthModule } from '../auth/auth.module'; @Module({ imports: [ @@ -51,6 +52,7 @@ import { ItemSchema } from '../clanInventory/item/item.schema'; PlayerModule, DailyTasksModule, PlayerModule, + AuthModule, ], controllers: [BoxController, DailyTaskController, AccountClaimerController], providers: [ diff --git a/src/box/dto/adminSignIn.dto.ts b/src/box/dto/adminSignIn.dto.ts deleted file mode 100644 index bcc80822c..000000000 --- a/src/box/dto/adminSignIn.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { Expose } from 'class-transformer'; - -export class AdminSignInDto { - /** - * Token used by the admin to manage the box session - * - * @example "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." - */ - @Expose() - accessToken: string; -} diff --git a/src/box/dto/createdBox.dto.ts b/src/box/dto/createdBox.dto.ts index d5496dca9..46bd5002b 100644 --- a/src/box/dto/createdBox.dto.ts +++ b/src/box/dto/createdBox.dto.ts @@ -5,8 +5,9 @@ import { SessionStage } from '../enum/SessionStage.enum'; import { ExtractField } from '../../common/decorator/response/ExtractField'; import { PlayerDto } from '../../player/dto/player.dto'; import { ClanDto } from '../../clan/dto/clan.dto'; +import { TokensDto } from '../../auth/dto/tokens.dto'; -export class CreatedBoxDto { +export class CreatedBoxDto extends TokensDto{ /** * Unique ID of the newly created box * @@ -16,14 +17,6 @@ export class CreatedBoxDto { @Expose() _id: string; - /** - * Token used by the admin to manage the box session - * - * @example "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." - */ - @Expose() - accessToken: string; - /** * Current stage of the game session * diff --git a/src/profile/dto/profile.dto.ts b/src/profile/dto/profile.dto.ts index aeb7ea3fb..bdd25467b 100644 --- a/src/profile/dto/profile.dto.ts +++ b/src/profile/dto/profile.dto.ts @@ -25,4 +25,7 @@ export class ProfileDto { @Expose() expiresAt?: Date; + + @Expose() + tokenVersion?: number; } diff --git a/src/profile/profile.module.ts b/src/profile/profile.module.ts index 9c82fa1c9..c2ea12e6b 100644 --- a/src/profile/profile.module.ts +++ b/src/profile/profile.module.ts @@ -1,4 +1,4 @@ -import { Module } from '@nestjs/common'; +import { forwardRef, Module } from '@nestjs/common'; import { MongooseModule } from '@nestjs/mongoose'; import { ProfileSchema } from './profile.schema'; import ProfileController from './profile.controller'; @@ -17,7 +17,7 @@ import { AuthModule } from '../auth/auth.module'; ]), PlayerModule, RequestHelperModule, - AuthModule, + forwardRef(() => AuthModule), ], controllers: [ProfileController], providers: [ProfileService, isProfileExists, PasswordGenerator],