Files
Momento/memento-note/app/api/user/api-keys/[provider]/route.ts
Antigravity a623454347
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m32s
CI / Deploy production (on server) (push) Has been skipped
perf: memo GridCard, fuse save fns, fix slash tab active color
2026-06-14 14:06:05 +00:00

78 lines
2.4 KiB
TypeScript

import { NextRequest, NextResponse } from 'next/server';
import { auth } from '@/auth';
import { prisma } from '@/lib/prisma';
import { encryptApiKey, hashApiKey } from '@/lib/crypto';
import { VALID_PROVIDERS } from '@/lib/ai/router';
type RouteContext = { params: Promise<{ provider: string }> };
export async function PATCH(req: NextRequest, context: RouteContext) {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { provider } = await context.params;
if (!VALID_PROVIDERS.has(provider)) {
return NextResponse.json({ error: 'Unknown provider' }, { status: 400 });
}
const body = (await req.json().catch(() => ({}))) as {
isActive?: boolean;
model?: string;
alias?: string;
baseUrl?: string;
apiKey?: string; // optional — only when rotating the key
};
const data: Record<string, unknown> = {};
if (typeof body.isActive === 'boolean') data.isActive = body.isActive;
if (body.model !== undefined) data.model = body.model || null;
if (body.alias !== undefined) data.alias = body.alias || '';
if (body.baseUrl !== undefined) data.baseUrl = body.baseUrl || null;
// Key rotation: only when new key explicitly provided
if (body.apiKey && body.apiKey.length >= 8) {
data.encryptedKey = await encryptApiKey(body.apiKey);
data.keyHash = hashApiKey(body.apiKey);
}
if (Object.keys(data).length === 0) {
return NextResponse.json({ error: 'No fields to update' }, { status: 400 });
}
const updated = await prisma.userAPIKey.updateMany({
where: { userId: session.user.id, provider },
data,
});
if (updated.count === 0) {
return NextResponse.json({ error: 'Not found' }, { status: 404 });
}
return NextResponse.json({ ok: true });
}
export async function DELETE(_req: NextRequest, context: RouteContext) {
const session = await auth();
if (!session?.user?.id) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
const { provider } = await context.params;
if (!VALID_PROVIDERS.has(provider)) {
return NextResponse.json({ error: 'Unknown provider' }, { status: 400 });
}
const deleted = await prisma.userAPIKey.deleteMany({
where: { userId: session.user.id, provider },
});
if (deleted.count === 0) {
return NextResponse.json({ error: 'Not found' }, { status: 404 });
}
return NextResponse.json({ ok: true });
}