import { Controller, Get, Post, Delete, Body, Param, UseGuards, NotFoundException } from '@nestjs/common'; import { Roles, RolesGuard } from '@it0/common'; import { CredentialRepository } from '../../../infrastructure/repositories/credential.repository'; import { CredentialVaultService } from '../../../infrastructure/crypto/credential-vault.service'; import { Credential } from '../../../domain/entities/credential.entity'; import * as crypto from 'crypto'; @Controller('api/v1/inventory/credentials') export class CredentialController { constructor( private readonly credentialRepository: CredentialRepository, private readonly credentialVaultService: CredentialVaultService, ) {} @Get() async listCredentials() { const credentials = await this.credentialRepository.findAll(); return credentials.map(c => this.toSafeOutput(c)); } @Post() async createCredential( @Body() body: { name: string; type: string; plainValue: string; keyType?: string; expiresAt?: string }, ) { const { encrypted, iv } = this.credentialVaultService.encrypt(body.plainValue); const credential = new Credential(); credential.id = crypto.randomUUID(); credential.name = body.name; credential.type = body.type as Credential['type']; credential.encryptedValue = encrypted; credential.iv = iv; credential.keyType = body.keyType as Credential['keyType']; credential.expiresAt = body.expiresAt ? new Date(body.expiresAt) : undefined; credential.createdAt = new Date(); const saved = await this.credentialRepository.save(credential); return this.toSafeOutput(saved); } @Get(':id') async getCredential(@Param('id') id: string) { const credential = await this.credentialRepository.findById(id); if (!credential) { throw new NotFoundException(`Credential ${id} not found`); } return this.toSafeOutput(credential); } @Delete(':id') async deleteCredential(@Param('id') id: string) { const credential = await this.credentialRepository.findById(id); if (!credential) { throw new NotFoundException(`Credential ${id} not found`); } await this.credentialRepository.remove(credential); return { message: 'Credential deleted', id }; } @Post(':id/decrypt') @UseGuards(RolesGuard) @Roles('admin') async decryptCredential(@Param('id') id: string) { const credential = await this.credentialRepository.findById(id); if (!credential) { throw new NotFoundException(`Credential ${id} not found`); } const plainValue = this.credentialVaultService.decrypt(credential.encryptedValue, credential.iv); return { id: credential.id, name: credential.name, plainValue }; } private toSafeOutput(credential: Credential) { return { id: credential.id, tenantId: credential.tenantId, name: credential.name, type: credential.type, fingerprint: credential.fingerprint, keyType: credential.keyType, createdBy: credential.createdBy, createdAt: credential.createdAt, expiresAt: credential.expiresAt, lastUsedAt: credential.lastUsedAt, }; } }