var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; import { createHash, randomBytes } from "node:crypto"; import { BadRequestException, Injectable, UnauthorizedException } from "@nestjs/common"; import { JwtService } from "@nestjs/jwt"; import { hash, verify } from "@node-rs/argon2"; import { env } from "../config/env.js"; import { AuditService } from "../common/common.module.js"; import { PrismaService } from "../prisma/prisma.service.js"; export const hashPassword = (password) => hash(password); const sha256 = (v) => createHash("sha256").update(v).digest("hex"); export const toUserDto = (u) => ({ id: u.id, phone: u.phone, name: u.name, role: u.role, isActive: u.isActive, lastLoginAt: u.lastLoginAt?.toISOString() ?? null, createdAt: u.createdAt.toISOString(), }); const INVALID_LOGIN = "شماره موبایل یا رمز عبور اشتباه است"; const DUMMY_HASH = hashPassword(randomBytes(16).toString("hex")); let AuthService = class AuthService { prisma; jwt; audit; constructor(prisma, jwt, audit) { this.prisma = prisma; this.jwt = jwt; this.audit = audit; } async login(input, userAgent) { const user = await this.prisma.adminUser.findUnique({ where: { phone: input.phone } }); const ok = await verify(user?.passwordHash ?? (await DUMMY_HASH), input.password).catch(() => false); if (!user || !ok || !user.isActive) throw new UnauthorizedException(INVALID_LOGIN); const updated = await this.prisma.adminUser.update({ where: { id: user.id }, data: { lastLoginAt: new Date() }, }); this.audit.log(user.id, "login", "user", user.id, user.phone); return this.issue(updated, userAgent); } async refresh(token, userAgent) { if (!token) throw new UnauthorizedException("نشست شما منقضی شده است"); const stored = await this.prisma.refreshToken.findUnique({ where: { tokenHash: sha256(token) }, include: { user: true }, }); if (!stored) throw new UnauthorizedException("نشست شما منقضی شده است"); if (stored.revokedAt) { await this.revokeAll(stored.userId); throw new UnauthorizedException("نشست شما منقضی شده است"); } if (stored.expiresAt < new Date() || !stored.user.isActive) { throw new UnauthorizedException("نشست شما منقضی شده است"); } await this.prisma.refreshToken.update({ where: { id: stored.id }, data: { revokedAt: new Date() }, }); return this.issue(stored.user, userAgent); } async logout(token) { if (!token) return; await this.prisma.refreshToken.updateMany({ where: { tokenHash: sha256(token), revokedAt: null }, data: { revokedAt: new Date() }, }); } async changePassword(userId, input) { const user = await this.prisma.adminUser.findUniqueOrThrow({ where: { id: userId } }); if (!(await verify(user.passwordHash, input.currentPassword).catch(() => false))) { throw new BadRequestException("رمز عبور فعلی اشتباه است"); } await this.prisma.adminUser.update({ where: { id: userId }, data: { passwordHash: await hashPassword(input.newPassword) }, }); this.audit.log(userId, "change-password", "user", userId, user.phone); } async me(userId) { return toUserDto(await this.prisma.adminUser.findUniqueOrThrow({ where: { id: userId } })); } revokeAll(userId) { return this.prisma.refreshToken.updateMany({ where: { userId, revokedAt: null }, data: { revokedAt: new Date() }, }); } async issue(user, userAgent) { const payload = { sub: user.id, role: user.role }; const accessToken = await this.jwt.signAsync(payload); const refreshToken = randomBytes(48).toString("base64url"); const refreshExpiresAt = new Date(Date.now() + env.REFRESH_TTL_DAYS * 86_400_000); await this.prisma.refreshToken.create({ data: { userId: user.id, tokenHash: sha256(refreshToken), expiresAt: refreshExpiresAt, userAgent: userAgent.slice(0, 300), }, }); void this.prisma.refreshToken .deleteMany({ where: { expiresAt: { lt: new Date(Date.now() - 86_400_000) } } }) .catch(() => undefined); return { accessToken, refreshToken, refreshExpiresAt, user: toUserDto(user) }; } }; AuthService = __decorate([ Injectable(), __metadata("design:paramtypes", [PrismaService, JwtService, AuditService]) ], AuthService); export { AuthService }; //# sourceMappingURL=auth.service.js.map