Unfinished
This commit is contained in:
parent
18c6535d1c
commit
6b388729d9
25 changed files with 1598 additions and 2352 deletions
|
@ -1,4 +0,0 @@
|
|||
import { SolidAuth } from "@auth/solid-start"
|
||||
import { authOptions } from "~/server/auth"
|
||||
|
||||
export const { GET, POST } = SolidAuth(authOptions)
|
132
src/routes/api/auth/callback/discord.ts
Normal file
132
src/routes/api/auth/callback/discord.ts
Normal 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,
|
||||
});
|
||||
}
|
||||
}
|
24
src/routes/api/auth/login.ts
Normal file
24
src/routes/api/auth/login.ts
Normal 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() },
|
||||
});
|
||||
}
|
19
src/routes/api/auth/logout.ts
Normal file
19
src/routes/api/auth/logout.ts
Normal 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: "/" },
|
||||
});
|
||||
};
|
|
@ -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),
|
Loading…
Add table
Add a link
Reference in a new issue