mirror of
https://github.com/tiennm99/llmapikey.git
synced 2026-08-01 14:22:10 +00:00
- Next.js 15 App Router (JS+JSDoc): landing, auth-gated dashboard, docs - GitHub OAuth via Supabase; identity anchored on numeric provider_id - key provisioning: reserve-then-mint-persist-compensate, one key per account - api_keys in unexposed llmapikey schema via direct Postgres; RLS deny-all - live minting gated behind PROVISIONING_ENABLED; Vercel auto-deploy disabled - unit tests (mask, request-body), RLS deny-all test, reconcile script
32 lines
996 B
JavaScript
32 lines
996 B
JavaScript
"use client";
|
|
|
|
import { useState } from "react";
|
|
|
|
import { createBrowserSupabaseClient } from "@/lib/supabase/browser-client";
|
|
|
|
/**
|
|
* GitHub sign-in button. Kicks off Supabase OAuth; minimal scope (read:user).
|
|
*
|
|
* @param {{ next?: string, label?: string }} props
|
|
*/
|
|
export function SignInWithGithubButton({ next = "/dashboard", label = "Sign in with GitHub" }) {
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
async function handleSignIn() {
|
|
setLoading(true);
|
|
const supabase = createBrowserSupabaseClient();
|
|
const redirectTo = `${window.location.origin}/auth/callback?next=${encodeURIComponent(next)}`;
|
|
const { error } = await supabase.auth.signInWithOAuth({
|
|
provider: "github",
|
|
options: { redirectTo, scopes: "read:user" },
|
|
});
|
|
if (error) setLoading(false); // on success the browser navigates away
|
|
}
|
|
|
|
return (
|
|
<button className="btn" onClick={handleSignIn} disabled={loading}>
|
|
{loading ? "Redirecting…" : label}
|
|
</button>
|
|
);
|
|
}
|