From ead3155ad822079c6c573a84792995140ca06560 Mon Sep 17 00:00:00 2001 From: lendry Date: Fri, 26 Jun 2026 10:20:29 +0300 Subject: [PATCH] fix document 500 error --- apps/sso-core/src/domain/documents.service.ts | 44 ++++++++++++++++--- apps/sso-core/src/infra/encryption.service.ts | 26 +++++++++++ 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/apps/sso-core/src/domain/documents.service.ts b/apps/sso-core/src/domain/documents.service.ts index e3e2183..7ecfd06 100644 --- a/apps/sso-core/src/domain/documents.service.ts +++ b/apps/sso-core/src/domain/documents.service.ts @@ -124,17 +124,47 @@ export class DocumentsService { } private toResponse(document: Awaited>) { - const metadata = document.metadata as { encryptedPayload?: string } | null; return { id: document.id, userId: document.userId, type: document.type, - number: this.encryption.decrypt(document.number), - issuedAt: document.issuedAt?.toISOString(), - expiresAt: document.expiresAt?.toISOString(), - metadataJson: metadata?.encryptedPayload ? this.encryption.decrypt(metadata.encryptedPayload) : undefined, - createdAt: document.createdAt.toISOString(), - updatedAt: document.updatedAt.toISOString() + number: this.encryption.decryptIfNeeded(document.number), + issuedAt: this.formatOptionalDate(document.issuedAt), + expiresAt: this.formatOptionalDate(document.expiresAt), + metadataJson: this.resolveMetadataJson(document.metadata), + createdAt: this.formatRequiredDate(document.createdAt), + updatedAt: this.formatRequiredDate(document.updatedAt) }; } + + private resolveMetadataJson(metadata: Prisma.JsonValue | null): string | undefined { + if (!metadata || typeof metadata !== 'object' || Array.isArray(metadata)) { + return undefined; + } + + const record = metadata as Record; + if (typeof record.encryptedPayload === 'string') { + return this.encryption.decryptIfNeeded(record.encryptedPayload); + } + + if (Object.keys(record).length === 0) { + return undefined; + } + + return JSON.stringify(record); + } + + private formatOptionalDate(value: Date | null | undefined): string | undefined { + if (!value || Number.isNaN(value.getTime())) { + return undefined; + } + return value.toISOString(); + } + + private formatRequiredDate(value: Date): string { + if (Number.isNaN(value.getTime())) { + return new Date(0).toISOString(); + } + return value.toISOString(); + } } diff --git a/apps/sso-core/src/infra/encryption.service.ts b/apps/sso-core/src/infra/encryption.service.ts index d1733c6..585e859 100644 --- a/apps/sso-core/src/infra/encryption.service.ts +++ b/apps/sso-core/src/infra/encryption.service.ts @@ -15,6 +15,21 @@ export class EncryptionService { return `${iv.toString('base64url')}.${authTag.toString('base64url')}.${encrypted.toString('base64url')}`; } + looksEncrypted(value: string): boolean { + const parts = value.split('.'); + if (parts.length !== 3) return false; + const [ivRaw, authTagRaw, encryptedRaw] = parts; + if (!ivRaw || !authTagRaw || !encryptedRaw) return false; + try { + Buffer.from(ivRaw, 'base64url'); + Buffer.from(authTagRaw, 'base64url'); + Buffer.from(encryptedRaw, 'base64url'); + return true; + } catch { + return false; + } + } + decrypt(value: string): string { const [ivRaw, authTagRaw, encryptedRaw] = value.split('.'); if (!ivRaw || !authTagRaw || !encryptedRaw) { @@ -25,4 +40,15 @@ export class EncryptionService { const decrypted = Buffer.concat([decipher.update(Buffer.from(encryptedRaw, 'base64url')), decipher.final()]); return decrypted.toString('utf8'); } + + decryptIfNeeded(value: string): string { + if (!this.looksEncrypted(value)) { + return value; + } + try { + return this.decrypt(value); + } catch { + return value; + } + } }