import { Body, Controller, Delete, Get, Header, Param, Post, UseGuards } from '@nestjs/common'; import { ApiBearerAuth, ApiTags } from '@nestjs/swagger'; import { JwtAuthGuard } from '../auth/guards/auth.guard'; import { OrgRolesGuard } from '../auth/guards/org-roles.guard'; import { Roles } from '../auth/decorators/roles.decorator'; import { CertificatesService } from './certificates.service'; import { ProvisionMqttCertDto } from './dto/certificates.dto'; import { RequireAnyOrgAdminGuard } from './guards/require-any-org-admin.guard'; // Global broker/CA management — not org-nested, since the CA is broker-wide // (mirrors serialNumber already being globally unique across orgs). JWT-only, // same precedent as api-keys: credential-minting endpoints never accept an // API key. @ApiTags('certificates') @ApiBearerAuth('jwt') @Controller('certificates') @UseGuards(JwtAuthGuard, RequireAnyOrgAdminGuard) export class CertificatesController { constructor(private readonly certificatesService: CertificatesService) {} @Get('ca') caStatus() { return this.certificatesService.getCaStatus(); } @Post('ca/init') initCa() { return this.certificatesService.initCa(); } @Post('mqtt/provision') provisionMqttCert(@Body() dto: ProvisionMqttCertDto) { return this.certificatesService.provisionMqttCert(dto); } @Get('ca/download') @Header('Content-Type', 'application/x-pem-file') @Header('Content-Disposition', 'attachment; filename="ca.crt"') downloadCa() { return this.certificatesService.downloadCaCert(); } } // Per-device certificate issuance, nested under the org's devices like the // rest of the domain. Same guard stack as devices create/disable. @ApiTags('certificates') @ApiBearerAuth('jwt') @Controller('orgs/:orgId/devices/:deviceId/certificate') @UseGuards(JwtAuthGuard, OrgRolesGuard) @Roles('ORG_ADMIN') export class DeviceCertificatesController { constructor(private readonly certificatesService: CertificatesService) {} @Post() issue(@Param('orgId') orgId: string, @Param('deviceId') deviceId: string) { return this.certificatesService.issueDeviceCertificate(orgId, deviceId); } @Get() get(@Param('orgId') orgId: string, @Param('deviceId') deviceId: string) { return this.certificatesService.getDeviceCertificate(orgId, deviceId); } @Get('cert') @Header('Content-Type', 'application/x-pem-file') @Header('Content-Disposition', 'attachment; filename="device.crt"') downloadCert(@Param('orgId') orgId: string, @Param('deviceId') deviceId: string) { return this.certificatesService.downloadDeviceCert(orgId, deviceId); } @Get('key') @Header('Content-Type', 'application/x-pem-file') @Header('Content-Disposition', 'attachment; filename="device.key"') downloadKey(@Param('orgId') orgId: string, @Param('deviceId') deviceId: string) { return this.certificatesService.downloadDeviceKey(orgId, deviceId); } @Delete() revoke(@Param('orgId') orgId: string, @Param('deviceId') deviceId: string) { return this.certificatesService.revokeDeviceCertificate(orgId, deviceId); } }