import { randomBytes } from "node:crypto"; import { Injectable, Logger } from "@nestjs/common"; import { HashingService } from "../crypto/services/hashing.service"; import { ApiKeysRepository } from "./repositories/api-keys.repository"; @Injectable() export class ApiKeysService { private readonly logger = new Logger(ApiKeysService.name); constructor( private readonly apiKeysRepository: ApiKeysRepository, private readonly hashingService: HashingService, ) {} async create(userId: string, name: string, expiresAt?: Date) { this.logger.log(`Creating API key for user ${userId}: ${name}`); const prefix = "mg_live_"; const randomPart = randomBytes(24).toString("hex"); const key = `${prefix}${randomPart}`; const keyHash = await this.hashingService.hashSha256(key); await this.apiKeysRepository.create({ userId, name, prefix: prefix.substring(0, 8), keyHash, expiresAt, }); return { name, key, // Retourné une seule fois à la création expiresAt, }; } async findAll(userId: string) { return await this.apiKeysRepository.findAll(userId); } async revoke(userId: string, keyId: string) { this.logger.log(`Revoking API key ${keyId} for user ${userId}`); return await this.apiKeysRepository.revoke(userId, keyId); } async validateKey(key: string) { const keyHash = await this.hashingService.hashSha256(key); const apiKey = await this.apiKeysRepository.findActiveByKeyHash(keyHash); if (!apiKey) return null; if (apiKey.expiresAt && apiKey.expiresAt < new Date()) { return null; } // Update last used at await this.apiKeysRepository.updateLastUsed(apiKey.id); return apiKey; } }