Unfinished

This commit is contained in:
Aron Malcher 2024-02-18 22:02:52 +01:00
parent 18c6535d1c
commit 6b388729d9
Signed by: aronmal
GPG key ID: 816B7707426FC612
25 changed files with 1598 additions and 2352 deletions

View file

@ -1,4 +0,0 @@
import { SolidAuth } from "@auth/solid-start"
import { authOptions } from "~/server/auth"
export const { GET, POST } = SolidAuth(authOptions)

View file

@ -0,0 +1,132 @@
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<Response> {
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<paths>({
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,
});
}
}

View file

@ -0,0 +1,24 @@
import { APIEvent } from "@solidjs/start/server/types";
import { generateState } from "arctic";
import { setCookie } from "vinxi/http";
import { discord } from "~/lib/auth";
export async function GET(event: APIEvent) {
const state = generateState();
const url = await discord.createAuthorizationURL(state, {
scopes: ["identify", "guilds", "guilds.members.read"],
});
setCookie(event, "discord_oauth_state", state, {
path: "/",
secure: import.meta.env.PROD,
httpOnly: true,
maxAge: 60 * 10,
sameSite: "lax",
});
return new Response(null, {
status: 302,
headers: { Location: url.toString() },
});
}

View file

@ -0,0 +1,19 @@
import { APIEvent } from "@solidjs/start/server/types";
import { appendHeader } from "vinxi/http";
import { lucia } from "~/lib/auth";
export const GET = async (event: APIEvent) => {
if (!event.nativeEvent.context.session) {
return new Error("Unauthorized");
}
await lucia.invalidateSession(event.nativeEvent.context.session.id);
appendHeader(
event,
"Set-Cookie",
lucia.createBlankSessionCookie().serialize(),
);
return new Response(null, {
status: 302,
headers: { Location: "/" },
});
};

View file

@ -4,6 +4,19 @@ import db from "~/drizzle";
import { guilds } from "~/drizzle/schema";
export const GET = async ({ params }: APIEvent) => {
if (params.guildId === "boot") {
const guilds = await db.query.guilds
.findMany({
with: {
timePlanning: { with: { messages: true } },
matches: true,
},
})
.execute();
return { guilds };
}
const guild = await db.query.guilds
.findFirst({
where: eq(guilds.id, params.guildId),