All checks were successful
Dev CI / Backend — Lint (push) Successful in 10m23s
Dev CI / Backend — Unit Tests (push) Successful in 10m17s
Dev CI / Frontend — Lint & Type-check (push) Successful in 11m3s
Dev CI / Frontend — Unit Tests (push) Successful in 10m33s
Dev CI / Notify Failure (push) Has been skipped
76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Delete,
|
|
Get,
|
|
HttpCode,
|
|
HttpStatus,
|
|
Param,
|
|
ParseUUIDPipe,
|
|
Post,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { ApiBearerAuth, ApiOperation, ApiResponse, ApiSecurity, ApiTags } from '@nestjs/swagger';
|
|
|
|
import { CurrentUser } from '../decorators/current-user.decorator';
|
|
import { RequiresFeature } from '../decorators/requires-feature.decorator';
|
|
import { FeatureFlagGuard } from '../guards/feature-flag.guard';
|
|
|
|
import { ApiKeysService } from './api-keys.service';
|
|
import { CreateApiKeyDto, ApiKeyDto, CreateApiKeyResultDto } from '../dto/api-key.dto';
|
|
|
|
@ApiTags('API Keys')
|
|
@ApiBearerAuth()
|
|
@ApiSecurity('x-api-key')
|
|
@UseGuards(FeatureFlagGuard)
|
|
@RequiresFeature('api_access')
|
|
@Controller('api-keys')
|
|
export class ApiKeysController {
|
|
constructor(private readonly apiKeysService: ApiKeysService) {}
|
|
|
|
@Post()
|
|
@ApiOperation({
|
|
summary: 'Générer une nouvelle clé API',
|
|
description:
|
|
'Crée une clé API pour accès programmatique. La clé complète est retournée **une seule fois** — conservez-la immédiatement. Réservé aux abonnements Gold et Platinium.',
|
|
})
|
|
@ApiResponse({
|
|
status: 201,
|
|
description: 'Clé créée avec succès. La clé complète est dans le champ `fullKey`.',
|
|
type: CreateApiKeyResultDto,
|
|
})
|
|
@ApiResponse({ status: 403, description: 'Abonnement Gold ou Platinium requis' })
|
|
async create(
|
|
@CurrentUser() user: { id: string; organizationId: string },
|
|
@Body() dto: CreateApiKeyDto
|
|
): Promise<CreateApiKeyResultDto> {
|
|
return this.apiKeysService.generateApiKey(user.id, user.organizationId, dto);
|
|
}
|
|
|
|
@Get()
|
|
@ApiOperation({
|
|
summary: 'Lister les clés API',
|
|
description:
|
|
"Retourne toutes les clés API de l'organisation. Les clés complètes ne sont jamais exposées — uniquement le préfixe.",
|
|
})
|
|
@ApiResponse({ status: 200, type: [ApiKeyDto] })
|
|
async list(@CurrentUser() user: { organizationId: string }): Promise<ApiKeyDto[]> {
|
|
return this.apiKeysService.listApiKeys(user.organizationId);
|
|
}
|
|
|
|
@Delete(':id')
|
|
@HttpCode(HttpStatus.NO_CONTENT)
|
|
@ApiOperation({
|
|
summary: 'Révoquer une clé API',
|
|
description: 'Désactive immédiatement la clé API. Cette action est irréversible.',
|
|
})
|
|
@ApiResponse({ status: 204, description: 'Clé révoquée' })
|
|
@ApiResponse({ status: 404, description: 'Clé introuvable' })
|
|
async revoke(
|
|
@CurrentUser() user: { organizationId: string },
|
|
@Param('id', ParseUUIDPipe) keyId: string
|
|
): Promise<void> {
|
|
return this.apiKeysService.revokeApiKey(keyId, user.organizationId);
|
|
}
|
|
}
|