2025-08-18 19:15:03 -04:00
|
|
|
import { BadRequestException, ForbiddenException, Injectable } from '@nestjs/common';
|
2025-04-08 12:40:03 -04:00
|
|
|
import { ApiKey } from 'src/database';
|
2024-08-16 09:48:43 -04:00
|
|
|
import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto';
|
2024-03-20 23:53:07 +01:00
|
|
|
import { AuthDto } from 'src/dtos/auth.dto';
|
2025-01-21 11:45:59 -05:00
|
|
|
import { Permission } from 'src/enum';
|
2024-10-02 10:54:35 -04:00
|
|
|
import { BaseService } from 'src/services/base.service';
|
2024-08-16 09:48:43 -04:00
|
|
|
import { isGranted } from 'src/utils/access';
|
2023-01-02 15:22:33 -05:00
|
|
|
|
|
|
|
|
@Injectable()
|
2025-03-10 12:04:35 -04:00
|
|
|
export class ApiKeyService extends BaseService {
|
2023-12-09 23:34:12 -05:00
|
|
|
async create(auth: AuthDto, dto: APIKeyCreateDto): Promise<APIKeyCreateResponseDto> {
|
2025-05-15 13:34:33 -05:00
|
|
|
const token = this.cryptoRepository.randomBytesAsText(32);
|
|
|
|
|
const tokenHashed = this.cryptoRepository.hashSha256(token);
|
2024-08-16 09:48:43 -04:00
|
|
|
|
|
|
|
|
if (auth.apiKey && !isGranted({ requested: dto.permissions, current: auth.apiKey.permissions })) {
|
|
|
|
|
throw new BadRequestException('Cannot grant permissions you do not have');
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 11:15:41 -05:00
|
|
|
const entity = await this.apiKeyRepository.create({
|
2025-05-15 13:34:33 -05:00
|
|
|
key: tokenHashed,
|
2023-01-02 15:22:33 -05:00
|
|
|
name: dto.name || 'API Key',
|
2023-12-09 23:34:12 -05:00
|
|
|
userId: auth.user.id,
|
2024-08-16 09:48:43 -04:00
|
|
|
permissions: dto.permissions,
|
2023-01-02 15:22:33 -05:00
|
|
|
});
|
|
|
|
|
|
2025-05-15 13:34:33 -05:00
|
|
|
return { secret: token, apiKey: this.map(entity) };
|
2023-01-02 15:22:33 -05:00
|
|
|
}
|
|
|
|
|
|
2024-08-16 09:48:43 -04:00
|
|
|
async update(auth: AuthDto, id: string, dto: APIKeyUpdateDto): Promise<APIKeyResponseDto> {
|
2025-03-04 11:15:41 -05:00
|
|
|
const exists = await this.apiKeyRepository.getById(auth.user.id, id);
|
2023-01-02 15:22:33 -05:00
|
|
|
if (!exists) {
|
|
|
|
|
throw new BadRequestException('API Key not found');
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-29 02:16:43 +08:00
|
|
|
const key = await this.apiKeyRepository.update(auth.user.id, id, { name: dto.name, permissions: dto.permissions });
|
2023-06-30 21:49:30 -04:00
|
|
|
|
|
|
|
|
return this.map(key);
|
2023-01-02 15:22:33 -05:00
|
|
|
}
|
|
|
|
|
|
2023-12-09 23:34:12 -05:00
|
|
|
async delete(auth: AuthDto, id: string): Promise<void> {
|
2025-03-04 11:15:41 -05:00
|
|
|
const exists = await this.apiKeyRepository.getById(auth.user.id, id);
|
2023-01-02 15:22:33 -05:00
|
|
|
if (!exists) {
|
|
|
|
|
throw new BadRequestException('API Key not found');
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-04 11:15:41 -05:00
|
|
|
await this.apiKeyRepository.delete(auth.user.id, id);
|
2023-01-02 15:22:33 -05:00
|
|
|
}
|
|
|
|
|
|
2025-08-18 19:15:03 -04:00
|
|
|
async getMine(auth: AuthDto): Promise<APIKeyResponseDto> {
|
|
|
|
|
if (!auth.apiKey) {
|
|
|
|
|
throw new ForbiddenException('Not authenticated with an API Key');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const key = await this.apiKeyRepository.getById(auth.user.id, auth.apiKey.id);
|
|
|
|
|
if (!key) {
|
|
|
|
|
throw new BadRequestException('API Key not found');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return this.map(key);
|
|
|
|
|
}
|
|
|
|
|
|
2023-12-09 23:34:12 -05:00
|
|
|
async getById(auth: AuthDto, id: string): Promise<APIKeyResponseDto> {
|
2025-03-04 11:15:41 -05:00
|
|
|
const key = await this.apiKeyRepository.getById(auth.user.id, id);
|
2023-01-02 15:22:33 -05:00
|
|
|
if (!key) {
|
|
|
|
|
throw new BadRequestException('API Key not found');
|
|
|
|
|
}
|
2023-06-30 21:49:30 -04:00
|
|
|
return this.map(key);
|
2023-01-02 15:22:33 -05:00
|
|
|
}
|
|
|
|
|
|
2023-12-09 23:34:12 -05:00
|
|
|
async getAll(auth: AuthDto): Promise<APIKeyResponseDto[]> {
|
2025-03-04 11:15:41 -05:00
|
|
|
const keys = await this.apiKeyRepository.getByUserId(auth.user.id);
|
2023-06-30 21:49:30 -04:00
|
|
|
return keys.map((key) => this.map(key));
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-08 12:40:03 -04:00
|
|
|
private map(entity: ApiKey): APIKeyResponseDto {
|
2023-06-30 21:49:30 -04:00
|
|
|
return {
|
|
|
|
|
id: entity.id,
|
|
|
|
|
name: entity.name,
|
|
|
|
|
createdAt: entity.createdAt,
|
|
|
|
|
updatedAt: entity.updatedAt,
|
2025-01-21 11:45:59 -05:00
|
|
|
permissions: entity.permissions as Permission[],
|
2023-06-30 21:49:30 -04:00
|
|
|
};
|
2023-01-02 15:22:33 -05:00
|
|
|
}
|
|
|
|
|
}
|