it0/packages/services/inventory-service/src/interfaces/rest/controllers/credential.controller.ts

87 lines
3.1 KiB
TypeScript

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,
};
}
}