chore: compelet refresh token mechanism

This commit is contained in:
mahyargdz
2025-03-06 12:47:05 +03:30
parent 144bfb2ac1
commit 1391deecf0
3 changed files with 22 additions and 14 deletions
-1
View File
@@ -84,7 +84,6 @@ export class AuthController {
return this.authService.changePassword(userId, changePasswordDto); return this.authService.changePassword(userId, changePasswordDto);
} }
@AuthGuards()
@ApiOperation({ summary: "refresh the user access token / refresh token" }) @ApiOperation({ summary: "refresh the user access token / refresh token" })
@HttpCode(HttpStatus.OK) @HttpCode(HttpStatus.OK)
@Post("refresh") @Post("refresh")
+21 -12
View File
@@ -5,7 +5,6 @@ import dayjs from "dayjs";
import { AuthMessage } from "../../../common/enums/message.enum"; import { AuthMessage } from "../../../common/enums/message.enum";
import { User } from "../../users/entities/user.entity"; import { User } from "../../users/entities/user.entity";
import { UsersService } from "../../users/providers/users.service";
import { RefreshTokensRepository } from "../../users/repositories/refresh-token.repository"; import { RefreshTokensRepository } from "../../users/repositories/refresh-token.repository";
import { ITokenPayload } from "../interfaces/IToken-payload"; import { ITokenPayload } from "../interfaces/IToken-payload";
@@ -15,7 +14,6 @@ export class TokensService {
private readonly configService: ConfigService, private readonly configService: ConfigService,
private readonly jwtService: JwtService, private readonly jwtService: JwtService,
private readonly refreshTokensRepository: RefreshTokensRepository, private readonly refreshTokensRepository: RefreshTokensRepository,
private readonly usersService: UsersService,
) {} ) {}
// ----------- generate token ----------------- // ----------- generate token -----------------
@@ -33,7 +31,7 @@ export class TokensService {
const accessExpire = this.configService.getOrThrow<number>("ACCESS_TOKEN_EXPIRE"); const accessExpire = this.configService.getOrThrow<number>("ACCESS_TOKEN_EXPIRE");
const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE"); const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
const accessToken = this.jwtService.sign(payload, { expiresIn: `${accessExpire}h` }); const accessToken = this.jwtService.sign(payload, { expiresIn: `${accessExpire}m` });
const refreshToken = this.jwtService.sign(payload, { expiresIn: `${refreshExpire}d` }); const refreshToken = this.jwtService.sign(payload, { expiresIn: `${refreshExpire}d` });
@@ -48,30 +46,41 @@ export class TokensService {
//**************************************************************** */ //**************************************************************** */
async storeRefreshToken(userId: string, refreshToken: string) { async storeRefreshToken(userId: string, refreshToken: string) {
const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE"); const refreshExpire = this.configService.getOrThrow<number>("REFRESH_TOKEN_EXPIRE");
const expiresAt = dayjs().add(refreshExpire, "day").toDate(); const expiresAt = dayjs().add(refreshExpire, "day").toDate();
const token = this.refreshTokensRepository.create({ const existingToken = await this.refreshTokensRepository.findOne({
token: refreshToken, where: { user: { id: userId } },
user: { id: userId },
expiresAt,
}); });
await this.refreshTokensRepository.save(token); if (existingToken) {
existingToken.token = refreshToken;
existingToken.expiresAt = expiresAt;
await this.refreshTokensRepository.save(existingToken);
} else {
const token = this.refreshTokensRepository.create({
token: refreshToken,
user: { id: userId },
expiresAt,
});
await this.refreshTokensRepository.save(token);
}
} }
/************************************************************ */ /************************************************************ */
async refreshToken(oldRefreshToken: string) { async refreshToken(oldRefreshToken: string) {
const token = await this.refreshTokensRepository.findOne({ where: { token: oldRefreshToken }, relations: { user: true } }); const token = await this.refreshTokensRepository.findOne({
where: { token: oldRefreshToken },
relations: { user: { roles: { permissions: true } } },
});
if (!token) throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN); if (!token) throw new UnauthorizedException(AuthMessage.INVALID_REFRESH_TOKEN);
if (dayjs(token.expiresAt).isBefore(dayjs())) throw new UnauthorizedException(AuthMessage.REFRESH_TOKEN_EXPIRED); if (dayjs(token.expiresAt).isBefore(dayjs())) throw new UnauthorizedException(AuthMessage.REFRESH_TOKEN_EXPIRED);
const { user } = await this.usersService.findOneById(token.user.id);
await this.refreshTokensRepository.delete({ id: token.id }); await this.refreshTokensRepository.delete({ id: token.id });
return await this.generateTokens(user); return await this.generateTokens(token.user);
} }
/************************************************************ */ /************************************************************ */
@@ -70,7 +70,7 @@ export class DanakServicesRepository extends Repository<DanakService> {
.leftJoinAndSelect("service.category", "category") .leftJoinAndSelect("service.category", "category")
.where("service.isActive = :isActive", { isActive: true }) .where("service.isActive = :isActive", { isActive: true })
.andWhere("service.deletedAt IS NULL") .andWhere("service.deletedAt IS NULL")
.andWhere("service.isDanakSuggest = :isDanakSuggest", { isDanakSuggest: true }) // .andWhere("service.isDanakSuggest = :isDanakSuggest", { isDanakSuggest: true })
.orderBy("service.createdAt", "DESC") .orderBy("service.createdAt", "DESC")
.skip(skip) .skip(skip)
.take(limit); .take(limit);