import { NextRequest, NextResponse } from "next/server"; import { nanoid } from "nanoid"; import { db } from "@/db"; import { apiKeys } from "@/db/schema"; import { eq, desc } from "drizzle-orm"; import { authenticateWebOrAPIRequest } from "@/app/lib/api-auth"; import { generateAPIKey, maskApiKey } from "@/app/lib/jwt"; import { MAX_API_KEY_NAME_LEN, expiresAtFromDays, getDaysRemaining, getExpiryRemainingLabel, parseExpiresInDaysOptional, } from "@/app/lib/api-key-utils"; /** * GET /api/v1/api-keys — Oturum veya Bearer ile: kendi API anahtarlarını listele (tam key dönmez) */ export async function GET(request: NextRequest) { const auth = await authenticateWebOrAPIRequest(request); if (!auth.authenticated || !auth.userId) { return NextResponse.json({ error: auth.error ?? "Yetkisiz" }, { status: 401 }); } const rows = await db .select({ id: apiKeys.id, name: apiKeys.name, key: apiKeys.key, expiresAt: apiKeys.expiresAt, lastUsedAt: apiKeys.lastUsedAt, isActive: apiKeys.isActive, createdAt: apiKeys.createdAt, }) .from(apiKeys) .where(eq(apiKeys.userId, auth.userId)) .orderBy(desc(apiKeys.createdAt)); return NextResponse.json({ success: true, data: { keys: rows.map((r) => { const exp = r.expiresAt ?? null; return { id: r.id, name: r.name, keyPreview: maskApiKey(r.key), expiresAt: exp?.toISOString() ?? null, daysRemaining: getDaysRemaining(exp), remainingLabel: getExpiryRemainingLabel(exp), lastUsedAt: r.lastUsedAt?.toISOString() ?? null, isActive: r.isActive, createdAt: r.createdAt.toISOString(), }; }), }, }); } /** * POST /api/v1/api-keys — Yeni API anahtarı oluştur (tam key yalnızca bu yanıtta bir kez) * * Body: { "name": string, "expiresInDays"?: number | null } * — expiresInDays yok/null/0: süresiz; 1–3650: bugünden itibaren o kadar gün */ export async function POST(request: NextRequest) { const auth = await authenticateWebOrAPIRequest(request); if (!auth.authenticated || !auth.userId) { return NextResponse.json({ error: auth.error ?? "Yetkisiz" }, { status: 401 }); } let body: { name?: unknown; expiresInDays?: unknown }; try { body = await request.json(); } catch { return NextResponse.json({ error: "Geçersiz JSON" }, { status: 400 }); } const name = typeof body.name === "string" ? body.name.trim() : ""; if (!name || name.length > MAX_API_KEY_NAME_LEN) { return NextResponse.json( { error: `name zorunludur ve en fazla ${MAX_API_KEY_NAME_LEN} karakter olabilir.`, }, { status: 400 } ); } const parsed = parseExpiresInDaysOptional(body.expiresInDays); if (!parsed.ok) { return NextResponse.json({ error: parsed.error }, { status: 400 }); } const expiresAt = parsed.value === null ? null : expiresAtFromDays(parsed.value); const plainKey = generateAPIKey(); const id = nanoid(); await db.insert(apiKeys).values({ id, userId: auth.userId, name, key: plainKey, expiresAt, isActive: true, }); return NextResponse.json({ success: true, message: "API anahtarı oluşturuldu. Tam değeri yalnızca bu yanıtta saklayın; bir daha gösterilmez.", data: { id, name, key: plainKey, expiresAt: expiresAt?.toISOString() ?? null, daysRemaining: getDaysRemaining(expiresAt), remainingLabel: getExpiryRemainingLabel(expiresAt), }, }); }