add: onboarding

This commit is contained in:
Théo LAGACHE
2026-06-22 10:52:42 +02:00
parent 68cd89fbe1
commit 1b3f972bc8
47 changed files with 2164 additions and 1546 deletions
+22 -20
View File
@@ -5,31 +5,33 @@ import { headers } from "next/headers";
const authHandler = toNextJsHandler(auth.handler);
async function blockApiKeyCreateForRestrictedUsers(req: NextRequest): Promise<NextResponse | null> {
const url = req.nextUrl;
if (req.method !== "POST" || !url.pathname.endsWith("/api-key/create")) {
return null;
}
const session = await auth.api.getSession({ headers: await headers() });
if (!session?.user) {
return null;
}
// @ts-ignore
if (session.user.banned || (session.user.role as string) === "pending") {
return NextResponse.json(
{ error: "Account not eligible to create API keys" },
{ status: 403 }
);
}
async function blockApiKeyCreateForRestrictedUsers(
req: NextRequest,
): Promise<NextResponse | null> {
const url = req.nextUrl;
if (req.method !== "POST" || !url.pathname.endsWith("/api-key/create")) {
return null;
}
const session = await auth.api.getSession({ headers: await headers() });
if (!session?.user) {
return null;
}
// @ts-ignore
if (session.user.banned || (session.user.role as string) === "pending") {
return NextResponse.json(
{ error: "Account not eligible to create API keys" },
{ status: 403 },
);
}
return null;
}
export async function GET(req: NextRequest) {
return authHandler.GET(req);
return authHandler.GET(req);
}
export async function POST(req: NextRequest) {
const guard = await blockApiKeyCreateForRestrictedUsers(req);
if (guard) return guard;
return authHandler.POST(req);
const guard = await blockApiKeyCreateForRestrictedUsers(req);
if (guard) return guard;
return authHandler.POST(req);
}
+34 -34
View File
@@ -4,42 +4,42 @@ import { NextRequest } from "next/server";
export const runtime = "edge";
const AVATAR_COLORS = [
"#4f46e5", // indigo
"#7c3aed", // violet
"#e11d48", // rose
"#ea580c", // orange
"#d97706", // amber
"#059669", // emerald
"#0891b2", // cyan
"#52525b", // zinc
"#4f46e5",
"#7c3aed",
"#e11d48",
"#ea580c",
"#d97706",
"#059669",
"#0891b2",
"#52525b",
];
export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url);
const initials = (searchParams.get("initials") ?? "?").slice(0, 2).toUpperCase();
const color = searchParams.get("color") ?? AVATAR_COLORS[0];
const { searchParams } = new URL(request.url);
const initials = (searchParams.get("initials") ?? "?")
.slice(0, 2)
.toUpperCase();
const color = searchParams.get("color") ?? AVATAR_COLORS[0];
return new ImageResponse(
(
<div
style={{
width: 80,
height: 80,
borderRadius: "50%",
backgroundColor: color,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "white",
fontSize: 28,
fontWeight: 700,
fontFamily: "sans-serif",
letterSpacing: "-0.5px",
}}
>
{initials}
</div>
),
{ width: 80, height: 80 }
);
return new ImageResponse(
<div
style={{
width: 80,
height: 80,
borderRadius: "50%",
backgroundColor: color,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "white",
fontSize: 28,
fontWeight: 700,
fontFamily: "sans-serif",
letterSpacing: "-0.5px",
}}
>
{initials}
</div>,
{ width: 80, height: 80 },
);
}