This commit is contained in:
2026-03-10 12:21:25 +03:30
parent ef2f4bf796
commit 0c0774bdca
19 changed files with 26 additions and 657 deletions
+13 -28
View File
@@ -3,13 +3,12 @@ import { EntityManager } from '@mikro-orm/postgresql';
import { LockMode } from '@mikro-orm/core';
import { Injectable, Logger, UnauthorizedException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AuthMessage } from '../../../common/enums/message.enum';
import { RefreshToken } from '../entities/refresh-token.entity';
import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload';
import { JwtService } from '@nestjs/jwt';
import dayjs from 'dayjs';
import { AuthMessage } from '../../../common/enums/message.enum';
import { RefreshToken, RefreshTokenType } from '../entities/refresh-token.entity';
import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload';
@Injectable()
export class TokensService {
private readonly logger = new Logger(TokensService.name);
@@ -17,28 +16,23 @@ export class TokensService {
private readonly configService: ConfigService,
private readonly jwtService: JwtService,
private readonly em: EntityManager,
) {}
) { }
async generateAccessAndRefreshToken(
ownerId: string,
restaurantId: string,
isAdmin: boolean,
slug: string,
adminId: string,
businessId: string,
em?: EntityManager,
) {
const refreshExpire = this.configService.getOrThrow<number>('REFRESH_TOKEN_EXPIRE');
const accessExpire = this.configService.getOrThrow<number>('JWT_EXPIRATION_TIME');
const payload: ITokenPayload | IAdminTokenPayload = isAdmin
? { adminId: ownerId, restId: restaurantId }
: { userId: ownerId, restId: restaurantId, slug };
const payload: IAdminTokenPayload = { adminId: adminId, restId: businessId }
const accessToken = await this.generateAccessToken(payload, accessExpire);
const refreshToken = this.generateRefreshToken();
const type = isAdmin ? RefreshTokenType.ADMIN : RefreshTokenType.USER;
// Only pass em if it's a transaction manager (not this.em), otherwise pass undefined to trigger flush
await this.storeRefreshToken(ownerId, restaurantId, refreshToken, type, em);
await this.storeRefreshToken(adminId, businessId, refreshToken, em);
return {
accessToken: { token: accessToken, expire: dayjs().add(accessExpire, 'seconds').valueOf() },
@@ -57,7 +51,6 @@ export class TokensService {
ownerId: string,
restId: string,
refreshToken: string,
type: RefreshTokenType,
em?: EntityManager,
) {
const entityManager = em || this.em;
@@ -68,9 +61,8 @@ export class TokensService {
const token = entityManager.create(RefreshToken, {
hashedToken,
ownerId,
restId,
type,
adminId: ownerId,
businessId: restId,
expiresAt,
});
@@ -104,20 +96,13 @@ export class TokensService {
}
// Store token data before removal
const ownerId = token.ownerId;
const restId = token.restId;
const isAdmin = token.type === RefreshTokenType.ADMIN;
// Verify restaurant still exists
// const restaurant = await em.findOne(Restaurant, { id: restId });
// if (!restaurant) {
// throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN);
// }
const adminId = token.adminId;
const businessId = token.businessId;
try {
// Generate new tokens first (before removing old token)
// Pass the transaction EntityManager to ensure operations are within the transaction
const tokens = await this.generateAccessAndRefreshToken(ownerId, "restaurant.id", isAdmin, "restaurant.slug", em);
const tokens = await this.generateAccessAndRefreshToken(adminId, businessId, em);
// Remove old token only after new token is created
em.remove(token);