debug: add comprehensive logging to api-keys POST endpoint

- Log each step: auth, body parsing, schema validation, encryption, db upsert
- Check for API_KEY_ENCRYPTION_SECRET presence before encrypt
- Log timing, error details with stack traces
- Return specific error messages for each failure point
This commit is contained in:
Ajax Davis 2026-01-03 13:49:23 +10:00
parent 1b1c4f6474
commit cc3a991661

View file

@ -46,58 +46,138 @@ export async function GET(): Promise<NextResponse> {
* Add or update an API key for a provider
*/
export async function POST(request: NextRequest): Promise<NextResponse> {
const startTime = Date.now();
console.log('[api-keys] POST request received');
try {
// Step 1: Auth check
console.log('[api-keys] Checking session...');
const session = await auth.api.getSession({ headers: await headers() });
if (!session?.user?.id) {
console.log('[api-keys] Unauthorized - no session or user id');
return NextResponse.json({ success: false, error: 'Unauthorized' }, { status: 401 });
}
console.log('[api-keys] Session valid for user:', session.user.id);
const body = await request.json();
// Step 2: Parse request body
console.log('[api-keys] Parsing request body...');
let body: unknown;
try {
body = await request.json();
console.log('[api-keys] Body parsed, provider:', (body as { provider?: string })?.provider);
} catch (parseError) {
console.error('[api-keys] Failed to parse JSON body:', parseError);
return NextResponse.json(
{ success: false, error: 'Invalid JSON body' },
{ status: 400 }
);
}
// Step 3: Validate schema
console.log('[api-keys] Validating schema...');
const parsed = AddApiKeySchema.safeParse(body);
if (!parsed.success) {
console.error('[api-keys] Schema validation failed:', parsed.error.flatten());
return NextResponse.json(
{ success: false, error: 'Invalid request', details: parsed.error.flatten() },
{ status: 400 }
);
}
console.log('[api-keys] Schema valid, provider:', parsed.data.provider);
const { provider, apiKey } = parsed.data;
const { encrypted, iv } = encryptApiKey(apiKey);
const keyHint = getKeyHint(apiKey);
console.log('[api-keys] API key length:', apiKey.length, 'chars');
const result = await prisma.userApiKey.upsert({
where: {
userId_provider: {
// Step 4: Encrypt the key
console.log('[api-keys] Encrypting API key...');
let encrypted: string;
let iv: string;
try {
const hasEncryptionSecret = !!process.env.API_KEY_ENCRYPTION_SECRET;
console.log('[api-keys] API_KEY_ENCRYPTION_SECRET present:', hasEncryptionSecret);
if (!hasEncryptionSecret) {
console.error('[api-keys] CRITICAL: API_KEY_ENCRYPTION_SECRET is not set!');
return NextResponse.json(
{ success: false, error: 'Server configuration error: encryption not configured' },
{ status: 500 }
);
}
const result = encryptApiKey(apiKey);
encrypted = result.encrypted;
iv = result.iv;
console.log('[api-keys] Encryption successful, encrypted length:', encrypted.length);
} catch (encryptError) {
console.error('[api-keys] Encryption failed:', encryptError);
return NextResponse.json(
{ success: false, error: 'Failed to encrypt API key' },
{ status: 500 }
);
}
const keyHint = getKeyHint(apiKey);
console.log('[api-keys] Key hint:', keyHint);
// Step 5: Upsert to database
console.log('[api-keys] Upserting to database...');
console.log('[api-keys] Where clause: userId_provider =', { userId: session.user.id, provider });
let result;
try {
result = await prisma.userApiKey.upsert({
where: {
userId_provider: {
userId: session.user.id,
provider,
},
},
create: {
userId: session.user.id,
provider,
encryptedKey: encrypted,
keyIv: iv,
keyHint,
},
},
create: {
userId: session.user.id,
provider,
encryptedKey: encrypted,
keyIv: iv,
keyHint,
},
update: {
encryptedKey: encrypted,
keyIv: iv,
keyHint,
},
select: {
provider: true,
keyHint: true,
createdAt: true,
updatedAt: true,
},
});
update: {
encryptedKey: encrypted,
keyIv: iv,
keyHint,
},
select: {
provider: true,
keyHint: true,
createdAt: true,
updatedAt: true,
},
});
console.log('[api-keys] Upsert successful:', result.provider, 'updated at', result.updatedAt);
} catch (dbError) {
console.error('[api-keys] Database upsert failed:', dbError);
console.error('[api-keys] Database error details:', {
name: (dbError as Error).name,
message: (dbError as Error).message,
stack: (dbError as Error).stack?.slice(0, 500),
});
return NextResponse.json(
{ success: false, error: 'Failed to save API key to database' },
{ status: 500 }
);
}
const duration = Date.now() - startTime;
console.log(`[api-keys] POST completed successfully in ${duration}ms`);
return NextResponse.json({
success: true,
data: result,
});
} catch (error) {
console.error('Failed to save API key:', error);
const duration = Date.now() - startTime;
console.error(`[api-keys] Unexpected error after ${duration}ms:`, error);
console.error('[api-keys] Error details:', {
name: (error as Error).name,
message: (error as Error).message,
stack: (error as Error).stack?.slice(0, 500),
});
return NextResponse.json({ success: false, error: 'Failed to save API key' }, { status: 500 });
}
}