From b5bf3ed8c0fcd4e4b8b2295c43f4a866b9a1d1d2 Mon Sep 17 00:00:00 2001 From: Schalli Date: Tue, 30 Jun 2026 09:58:59 +0200 Subject: [PATCH] fix(dkv): return username in GET /dkv/config response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit loadConfig used CONFIG_SAFE_SELECT which excludes encryptedInboxCreds entirely, so username was never returned to the frontend — form always showed empty username. Added getConfigForApi() which loads the safe config + decrypts encryptedInboxCreds to extract username (never password) and adds hasPassword boolean. Controller getConfig now calls getConfigForApi instead of loadConfig. Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/dkv/dkv.controller.ts | 4 ++-- apps/api/src/dkv/dkv.service.ts | 22 ++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/apps/api/src/dkv/dkv.controller.ts b/apps/api/src/dkv/dkv.controller.ts index 391fe2d..6ecc90d 100644 --- a/apps/api/src/dkv/dkv.controller.ts +++ b/apps/api/src/dkv/dkv.controller.ts @@ -55,12 +55,12 @@ export class DkvController { // ─── Config ──────────────────────────────────────────────────────────────── - /** GET /dkv/config — returns module config without encrypted credentials. 404 when not yet configured. */ + /** GET /dkv/config — returns module config with username + hasPassword. 404 when not yet configured. */ @Get('config') @Roles(Role.ADMIN, Role.SUPER_ADMIN) async getConfig(@Req() req: any) { const tenantId = this._requireTenant(req); - const config = await this.dkvService.loadConfig(tenantId); + const config = await this.dkvService.getConfigForApi(tenantId); if (!config) { throw new NotFoundException('DKV module not yet configured'); } diff --git a/apps/api/src/dkv/dkv.service.ts b/apps/api/src/dkv/dkv.service.ts index 302b1a3..61a352c 100644 --- a/apps/api/src/dkv/dkv.service.ts +++ b/apps/api/src/dkv/dkv.service.ts @@ -102,6 +102,28 @@ export class DkvService { }); } + /** + * Load config for API response: safe fields + decrypted username + hasPassword flag. + * T-07-12: password is NEVER returned — only hasPassword boolean. + */ + async getConfigForApi(tenantId: string) { + const safe = await this.loadConfig(tenantId); + if (!safe) return null; + + let username: string | null = null; + let hasPassword = false; + try { + const raw = await this.prisma.dkvModuleConfig.findUnique({ where: { tenantId } }); + if (raw?.encryptedInboxCreds) { + const creds = JSON.parse(this.crypto.decrypt(raw.encryptedInboxCreds)) as { username?: string; password?: string }; + username = creds.username ?? null; + hasPassword = Boolean(creds.password); + } + } catch { /* ignore decrypt errors — return empty username */ } + + return { ...safe, username, hasPassword }; + } + /** * Upsert DKV module config for a tenant. *