From acafdd1853eedc14b588587b201f1994e88fc7bc Mon Sep 17 00:00:00 2001 From: Narutama Aurum Date: Tue, 9 Jun 2026 21:57:59 +0800 Subject: [PATCH 1/4] fix: remove leftover console.log(error) in lib/user-data.ts (issue #274) --- lib/user-data.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/user-data.ts b/lib/user-data.ts index 594685b2..ce433323 100644 --- a/lib/user-data.ts +++ b/lib/user-data.ts @@ -9,8 +9,7 @@ export const getUserById = async (id: string) => { } }); return user; - } catch (error) { - console.log(error); + } catch { return null; } }; @@ -21,8 +20,7 @@ export const getUserByEmail = async (email: string) => { where: { email } }); return user; - } catch (error) { - console.log(error); + } catch { return null; } }; @@ -35,8 +33,7 @@ export const getAccountByUserId = async (userId: string) => { } }); return account; - } catch (error) { - console.log(error); + } catch { return null; } }; From 15dcc9c3bfde82b75414b9dd65a54d0e7a3f06ef Mon Sep 17 00:00:00 2001 From: Narutama Aurum Date: Tue, 9 Jun 2026 23:55:37 +0800 Subject: [PATCH 2/4] fix: improve error handling in user-data helpers - Replace bare catch blocks with proper error capture and structured logging - Log errors with function name and query parameters for observability - Rethrow errors so callers can differentiate DB failures from not-found results - Follow existing structured logging pattern from lib/api-utils.ts Addresses CodeRabbit review on PR #488 --- lib/user-data.ts | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/lib/user-data.ts b/lib/user-data.ts index ce433323..c5afd3ac 100644 --- a/lib/user-data.ts +++ b/lib/user-data.ts @@ -1,5 +1,18 @@ import { db } from "@/lib/db"; +const logError = (functionName: string, params: Record, error: unknown) => { + console.error( + JSON.stringify({ + timestamp: new Date().toISOString(), + level: "error", + context: functionName, + params, + error: error instanceof Error ? error.message : "Unknown error", + stack: error instanceof Error ? error.stack : undefined, + }) + ); +}; + export const getUserById = async (id: string) => { try { const user = await db.user.findUnique({ @@ -9,8 +22,9 @@ export const getUserById = async (id: string) => { } }); return user; - } catch { - return null; + } catch (err) { + logError("getUserById", { id }, err); + throw err; } }; @@ -20,8 +34,9 @@ export const getUserByEmail = async (email: string) => { where: { email } }); return user; - } catch { - return null; + } catch (err) { + logError("getUserByEmail", { email }, err); + throw err; } }; @@ -33,7 +48,8 @@ export const getAccountByUserId = async (userId: string) => { } }); return account; - } catch { - return null; + } catch (err) { + logError("getAccountByUserId", { userId }, err); + throw err; } }; From 06f9c16218fb49725068f84d3bf4dcdbd3722178 Mon Sep 17 00:00:00 2001 From: Narutama Aurum Date: Wed, 10 Jun 2026 03:43:08 +0800 Subject: [PATCH 3/4] fix: redact PII in user-data error logging --- lib/user-data.ts | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/lib/user-data.ts b/lib/user-data.ts index c5afd3ac..c7290c41 100644 --- a/lib/user-data.ts +++ b/lib/user-data.ts @@ -1,12 +1,27 @@ import { db } from "@/lib/db"; +const SENSITIVE_KEYS = ["email", "phone", "ssn", "password", "token", "secret", "key", "auth", "credential"]; + +const redactParams = (params: Record): Record => { + const redacted: Record = {}; + for (const [key, value] of Object.entries(params)) { + const lowerKey = key.toLowerCase(); + if (SENSITIVE_KEYS.some((sensitive) => lowerKey.includes(sensitive))) { + redacted[key] = "[REDACTED]"; + } else { + redacted[key] = value; + } + } + return redacted; +}; + const logError = (functionName: string, params: Record, error: unknown) => { console.error( JSON.stringify({ timestamp: new Date().toISOString(), level: "error", context: functionName, - params, + params: redactParams(params), error: error instanceof Error ? error.message : "Unknown error", stack: error instanceof Error ? error.stack : undefined, }) @@ -52,4 +67,4 @@ export const getAccountByUserId = async (userId: string) => { logError("getAccountByUserId", { userId }, err); throw err; } -}; +}; \ No newline at end of file From b04cea79508c81901b3ddfccad489da2f97e0da6 Mon Sep 17 00:00:00 2001 From: Narutama Aurum Date: Wed, 10 Jun 2026 04:43:58 +0800 Subject: [PATCH 4/4] fix: address CodeRabbit review comments on user-data.ts - Narrow SENSITIVE_KEYS: remove overly broad 'key' pattern, add specific patterns (apikey, api_key, secretkey, private_key, access_key) - Make redactParams recursive to handle nested objects and arrays - Change DB helper functions (getUserById, getUserByEmail, getAccountByUserId) to return null on error instead of rethrowing, so auth JWT callback treats DB failures as 'no user' Signed-off-by: Narutama Aurum --- lib/user-data.ts | 50 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/user-data.ts b/lib/user-data.ts index c7290c41..5d2f557b 100644 --- a/lib/user-data.ts +++ b/lib/user-data.ts @@ -1,6 +1,20 @@ import { db } from "@/lib/db"; -const SENSITIVE_KEYS = ["email", "phone", "ssn", "password", "token", "secret", "key", "auth", "credential"]; +const SENSITIVE_KEYS = [ + "email", + "phone", + "ssn", + "password", + "token", + "secret", + "apikey", + "api_key", + "secretkey", + "private_key", + "access_key", + "auth", + "credential", +]; const redactParams = (params: Record): Record => { const redacted: Record = {}; @@ -8,6 +22,16 @@ const redactParams = (params: Record): Record const lowerKey = key.toLowerCase(); if (SENSITIVE_KEYS.some((sensitive) => lowerKey.includes(sensitive))) { redacted[key] = "[REDACTED]"; + } else if (value !== null && typeof value === "object" && !Array.isArray(value)) { + // Recursively redact nested objects + redacted[key] = redactParams(value as Record); + } else if (Array.isArray(value)) { + // Redact array elements that are objects + redacted[key] = value.map((item) => + item !== null && typeof item === "object" + ? redactParams(item as Record) + : item + ); } else { redacted[key] = value; } @@ -15,7 +39,11 @@ const redactParams = (params: Record): Record return redacted; }; -const logError = (functionName: string, params: Record, error: unknown) => { +const logError = ( + functionName: string, + params: Record, + error: unknown +) => { console.error( JSON.stringify({ timestamp: new Date().toISOString(), @@ -33,25 +61,25 @@ export const getUserById = async (id: string) => { const user = await db.user.findUnique({ where: { id }, include: { - accounts: true - } + accounts: true, + }, }); return user; } catch (err) { logError("getUserById", { id }, err); - throw err; + return null; } }; export const getUserByEmail = async (email: string) => { try { const user = await db.user.findUnique({ - where: { email } + where: { email }, }); return user; } catch (err) { logError("getUserByEmail", { email }, err); - throw err; + return null; } }; @@ -59,12 +87,12 @@ export const getAccountByUserId = async (userId: string) => { try { const account = await db.account.findFirst({ where: { - userId - } + userId, + }, }); return account; } catch (err) { logError("getAccountByUserId", { userId }, err); - throw err; + return null; } -}; \ No newline at end of file +};