update auth

This commit is contained in:
2025-12-09 16:28:50 +03:30
parent f2094f87c5
commit 07f3006aef
4 changed files with 24 additions and 5 deletions
+11
View File
@@ -26,6 +26,10 @@ export class AuthGuard implements CanActivate {
try { try {
const secret = this.configService.getOrThrow<string>('JWT_SECRET'); const secret = this.configService.getOrThrow<string>('JWT_SECRET');
const token = this.extractTokenFromHeader(request); const token = this.extractTokenFromHeader(request);
const slug = this.extractSlugFromHeader(request);
if (!slug) {
throw new UnauthorizedException('Slug is required');
}
if (!token) { if (!token) {
throw new UnauthorizedException(); throw new UnauthorizedException();
} }
@@ -38,6 +42,9 @@ export class AuthGuard implements CanActivate {
this.logger.error('Invalid token payload structure', payload); this.logger.error('Invalid token payload structure', payload);
throw new UnauthorizedException('Invalid token payload'); throw new UnauthorizedException('Invalid token payload');
} }
if (payload.slug !== slug) {
throw new UnauthorizedException('Invalid slug');
}
request['userId'] = payload.userId; request['userId'] = payload.userId;
request['restId'] = payload.restId; request['restId'] = payload.restId;
} catch { } catch {
@@ -57,4 +64,8 @@ export class AuthGuard implements CanActivate {
const [type, token] = request.headers.authorization?.split(' ') ?? []; const [type, token] = request.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined; return type === 'Bearer' ? token : undefined;
} }
private extractSlugFromHeader(request: Request): string | undefined {
const slug = request.headers['X-Slug'] as string;
return slug;
}
} }
@@ -1,6 +1,7 @@
export interface ITokenPayload { export interface ITokenPayload {
userId: string; userId: string;
restId: string; restId: string;
slug: string;
} }
export interface IAdminTokenPayload { export interface IAdminTokenPayload {
+4 -2
View File
@@ -28,9 +28,11 @@ export class AuthService {
) { ) {
this.OTP_EXPIRATION_TIME = this.configService.get<number>('OTP_EXPIRATION_TIME') ?? 240; this.OTP_EXPIRATION_TIME = this.configService.get<number>('OTP_EXPIRATION_TIME') ?? 240;
} }
private userOtpKey(restaurantSlug: string, phone: string) { private userOtpKey(restaurantSlug: string, phone: string) {
return `otp:${restaurantSlug}:${phone}`; return `otp:${restaurantSlug}:${phone}`;
} }
private adminOtpKey(restaurantSlug: string, phone: string) { private adminOtpKey(restaurantSlug: string, phone: string) {
return `otp-admin:${restaurantSlug}:${phone}`; return `otp-admin:${restaurantSlug}:${phone}`;
} }
@@ -64,7 +66,7 @@ export class AuthService {
throw new BadRequestException(RestMessage.NOT_FOUND); throw new BadRequestException(RestMessage.NOT_FOUND);
} }
const tokens = await this.tokensService.generateAccessAndRefreshToken(user.id, rest.id, false); const tokens = await this.tokensService.generateAccessAndRefreshToken(user.id, rest.id, false, slug);
const userResponse = UserLoginTransformer.transform(user, rest); const userResponse = UserLoginTransformer.transform(user, rest);
@@ -93,7 +95,7 @@ export class AuthService {
throw new BadRequestException(RestMessage.NOT_FOUND); throw new BadRequestException(RestMessage.NOT_FOUND);
} }
const tokens = await this.tokensService.generateAccessAndRefreshToken(admin.id, rest.id, true); const tokens = await this.tokensService.generateAccessAndRefreshToken(admin.id, rest.id, true, slug);
const adminResponse = await AdminLoginTransformer.transform(admin, rest); const adminResponse = await AdminLoginTransformer.transform(admin, rest);
+8 -3
View File
@@ -8,6 +8,7 @@ import dayjs from 'dayjs';
import { AuthMessage } from '../../../common/enums/message.enum'; import { AuthMessage } from '../../../common/enums/message.enum';
import { RefreshToken, RefreshTokenType } from '../entities/refresh-token.entity'; import { RefreshToken, RefreshTokenType } from '../entities/refresh-token.entity';
import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload'; import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload';
import { Restaurant } from 'src/modules/restaurants/entities/restaurant.entity';
@Injectable() @Injectable()
export class TokensService { export class TokensService {
@@ -18,13 +19,13 @@ export class TokensService {
private readonly em: EntityManager, private readonly em: EntityManager,
) {} ) {}
async generateAccessAndRefreshToken(ownerId: string, restaurantId: string, isAdmin: boolean) { async generateAccessAndRefreshToken(ownerId: string, restaurantId: string, isAdmin: boolean, slug: string) {
const refreshExpire = this.configService.getOrThrow<number>('REFRESH_TOKEN_EXPIRE'); const refreshExpire = this.configService.getOrThrow<number>('REFRESH_TOKEN_EXPIRE');
const accessExpire = this.configService.getOrThrow<number>('JWT_EXPIRATION_TIME'); const accessExpire = this.configService.getOrThrow<number>('JWT_EXPIRATION_TIME');
const payload: ITokenPayload | IAdminTokenPayload = isAdmin const payload: ITokenPayload | IAdminTokenPayload = isAdmin
? { adminId: ownerId, restId: restaurantId } ? { adminId: ownerId, restId: restaurantId }
: { userId: ownerId, restId: restaurantId }; : { userId: ownerId, restId: restaurantId, slug };
const accessToken = await this.generateAccessToken(payload, accessExpire); const accessToken = await this.generateAccessToken(payload, accessExpire);
const refreshToken = this.generateRefreshToken(); const refreshToken = this.generateRefreshToken();
@@ -78,12 +79,16 @@ export class TokensService {
const ownerId = token.ownerId; const ownerId = token.ownerId;
const restId = token.restId; const restId = token.restId;
const restaurant = await this.em.findOne(Restaurant, { id: restId });
if (!restaurant) {
throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN);
}
// Remove the old token // Remove the old token
this.em.remove(token); this.em.remove(token);
const isAdmin = token.type === RefreshTokenType.ADMIN; const isAdmin = token.type === RefreshTokenType.ADMIN;
try { try {
// Generate new tokens // Generate new tokens
const tokens = await this.generateAccessAndRefreshToken(ownerId, restId, isAdmin); const tokens = await this.generateAccessAndRefreshToken(ownerId, restId, isAdmin, restaurant.slug);
// Commit the transaction // Commit the transaction
await this.em.flush(); await this.em.flush();