87 lines
3.1 KiB
TypeScript
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,
|
|
};
|
|
}
|
|
}
|