import { createId } from "@paralleldrive/cuid2"; import { APIEvent } from "@solidjs/start/server/types"; import { OAuth2RequestError } from "arctic"; import { eq } from "drizzle-orm"; import createClient from "openapi-fetch"; import { getCookie, setCookie } from "vinxi/http"; import db from "~/drizzle"; import { discordTokens, users } from "~/drizzle/schema"; import { discord, lucia } from "~/lib/auth"; import { paths } from "~/types/discord"; export async function GET(event: APIEvent): Promise { const code = new URL(event.request.url).searchParams.get("code"); const state = new URL(event.request.url).searchParams.get("state"); const error = new URL(event.request.url).searchParams.get("error"); const error_description = new URL(event.request.url).searchParams.get( "error_description", ); if (error) switch (error) { case "access_denied": return new Response(null, { status: 302, headers: { Location: "/" }, }); default: console.log("Discord oauth error:", error_description); return new Response(decodeURI(error_description ?? ""), { status: 400, }); } const storedState = getCookie("discord_oauth_state") ?? null; if (!code || !state || !storedState || state !== storedState) { return new Response(null, { status: 400, }); } try { const tokens = await discord.validateAuthorizationCode(code); const { GET } = createClient({ baseUrl: "https://discord.com/api/v10", }); const discordUserResponse = await GET("/users/@me", { headers: { Authorization: `Bearer ${tokens.accessToken}` }, }); if (discordUserResponse.error) throw discordUserResponse.error; const discordUser = discordUserResponse.data; const existingUser = await db.query.users .findFirst({ where: eq(users.discord_id, discordUser.id), }) .execute(); if (existingUser) { const session = await lucia.createSession( existingUser.id, {}, { sessionId: createId() }, ); const sessionCookie = lucia.createSessionCookie(session.id); console.log(sessionCookie); setCookie( sessionCookie.name, sessionCookie.value, sessionCookie.attributes, ); await db .update(users) .set({ name: discordUser.global_name, image: discordUser.avatar, }) .where(eq(users.discord_id, discordUser.id)) .returning() .execute(); return new Response(null, { status: 302, headers: { Location: "/config" }, }); } const userId = createId(); await db.insert(users).values({ id: userId, discord_id: discordUser.id, name: discordUser.global_name, image: discordUser.avatar, }); await db .insert(discordTokens) .values({ userId, accessToken: tokens.accessToken, expiresAt: tokens.accessTokenExpiresAt, refreshToken: tokens.refreshToken, }) .returning() .execute(); console.log(createId(), createId(), { warst: createId() }); const session = await lucia.createSession( userId, {}, { sessionId: createId() }, ); const sessionCookie = lucia.createSessionCookie(session.id); setCookie( sessionCookie.name, sessionCookie.value, sessionCookie.attributes, ); return new Response(null, { status: 302, headers: { Location: "/config" }, }); } catch (e) { // the specific error message depends on the provider if (e instanceof OAuth2RequestError) { // invalid code return new Response(null, { status: 400, }); } console.error("Unknown error on callback."); console.error(e); return new Response(null, { status: 500, }); } }