|
| 1 | +/* eslint-disable prettier/prettier */ |
| 2 | +import { Injectable, NotFoundException, ForbiddenException } from '@nestjs/common'; |
| 3 | +import { InjectRepository } from '@nestjs/typeorm'; |
| 4 | +import { Repository } from 'typeorm'; |
| 5 | +import { ApiKey } from './entities/api-key.entity'; |
| 6 | +import { CreateApiKeyDto } from './dto/create-api-key.dto'; |
| 7 | +import { RevokeApiKeyDto } from './dto/revoke-api-key.dto'; |
| 8 | +import { randomBytes } from 'crypto'; |
| 9 | +import { Company } from 'src/companies/entities/company.entity'; |
| 10 | + |
| 11 | +@Injectable() |
| 12 | +export class ApiKeysService { |
| 13 | + constructor( |
| 14 | + @InjectRepository(ApiKey) |
| 15 | + private apiKeyRepo: Repository<ApiKey>, |
| 16 | + @InjectRepository(Company) |
| 17 | + private companyRepo: Repository<Company>, |
| 18 | + ) {} |
| 19 | + |
| 20 | + private generateKey(): string { |
| 21 | + return `ASSETSUP_${randomBytes(32).toString('hex')}`; |
| 22 | + } |
| 23 | + |
| 24 | + async createKey(dto: CreateApiKeyDto): Promise<ApiKey> { |
| 25 | + const company = await this.companyRepo.findOne({ where: { id: Number(dto.companyId) } }); |
| 26 | + if (!company) throw new NotFoundException('Company not found'); |
| 27 | + |
| 28 | + const apiKey = this.apiKeyRepo.create({ |
| 29 | + key: this.generateKey(), |
| 30 | + company, |
| 31 | + expiryDate: dto.expiryDate ? new Date(dto.expiryDate) : null, |
| 32 | + }); |
| 33 | + |
| 34 | + return await this.apiKeyRepo.save(apiKey); |
| 35 | + } |
| 36 | + |
| 37 | + async revokeKey(dto: RevokeApiKeyDto): Promise<ApiKey> { |
| 38 | + const key = await this.apiKeyRepo.findOne({ where: { id: dto.apiKeyId } }); |
| 39 | + if (!key) throw new NotFoundException('API key not found'); |
| 40 | + |
| 41 | + key.status = 'revoked'; |
| 42 | + return await this.apiKeyRepo.save(key); |
| 43 | + } |
| 44 | + |
| 45 | + async validateKey(key: string): Promise<Company> { |
| 46 | + const apiKey = await this.apiKeyRepo.findOne({ |
| 47 | + where: { key, status: 'active' }, |
| 48 | + relations: ['company'], |
| 49 | + }); |
| 50 | + |
| 51 | + if (!apiKey) throw new ForbiddenException('Invalid API key'); |
| 52 | + if (apiKey.expiryDate && apiKey.expiryDate < new Date()) { |
| 53 | + throw new ForbiddenException('API key expired'); |
| 54 | + } |
| 55 | + |
| 56 | + return apiKey.company; |
| 57 | + } |
| 58 | + |
| 59 | + async listKeys(companyId: string): Promise<ApiKey[]> { |
| 60 | + return this.apiKeyRepo.find({ |
| 61 | + where: { company: { id: Number(companyId) } }, |
| 62 | + order: { createdAt: 'DESC' }, |
| 63 | + }); |
| 64 | + } |
| 65 | +} |
0 commit comments