ClauseGuard / web /app /api /api-keys /route.ts
gaurv007's picture
Build all missing features: PDF/DOCX upload, team system (5 seats, invites, shared dashboard), API keys (generate/revoke/limits), custom clause rules (CRUD + regex)
89ccd89 verified
raw
history blame
2.83 kB
import { NextRequest, NextResponse } from "next/server";
import { createClient } from "@/lib/supabase/server";
import crypto from "crypto";
// GET — list user's API keys
export async function GET() {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
const { data: profile } = await supabase.from("profiles").select("plan, team_id").eq("id", user.id).single();
if (profile?.plan === "free") return NextResponse.json({ error: "API access requires Pro or Team plan" }, { status: 403 });
const { data: keys } = await supabase.from("api_keys")
.select("id, name, key_prefix, calls_this_month, calls_limit, is_active, last_used_at, created_at")
.eq("user_id", user.id)
.order("created_at", { ascending: false });
return NextResponse.json({ keys: keys || [] });
}
// POST — create new API key
export async function POST(req: NextRequest) {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
const { data: profile } = await supabase.from("profiles").select("plan, team_id").eq("id", user.id).single();
if (profile?.plan === "free") return NextResponse.json({ error: "API access requires Pro or Team plan" }, { status: 403 });
const { name } = await req.json();
// Generate key: cg_live_ + 32 random hex chars
const rawKey = "cg_live_" + crypto.randomBytes(24).toString("hex");
const keyHash = crypto.createHash("sha256").update(rawKey).digest("hex");
const keyPrefix = rawKey.substring(0, 16) + "...";
const callsLimit = profile?.plan === "team" ? 10000 : 1000;
const { error } = await supabase.from("api_keys").insert({
user_id: user.id,
team_id: profile?.team_id || null,
name: name || "Default",
key_hash: keyHash,
key_prefix: keyPrefix,
calls_limit: callsLimit,
});
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
// Return the full key ONCE — it's never shown again
return NextResponse.json({ key: rawKey, prefix: keyPrefix, name, calls_limit: callsLimit });
}
// DELETE — revoke an API key
export async function DELETE(req: NextRequest) {
const supabase = await createClient();
const { data: { user } } = await supabase.auth.getUser();
if (!user) return NextResponse.json({ error: "Not authenticated" }, { status: 401 });
const { keyId } = await req.json();
const { error } = await supabase.from("api_keys")
.update({ is_active: false })
.eq("id", keyId)
.eq("user_id", user.id);
if (error) return NextResponse.json({ error: error.message }, { status: 500 });
return NextResponse.json({ success: true });
}