friends-best/server/routes/auth/v1/callback.ts
Louis Hollingworth e6a00bc260
DB now writing!
Signed-off-by: Louis Hollingworth <louis@hollingworth.ch>
2023-05-17 17:38:30 +01:00

203 lines
5.9 KiB
TypeScript

import { runtimeConfig, prisma } from '~/server/index'
import * as jose from 'jose'
import { z } from 'zod';
const PartialUserGuildSchema = z.object({
id: z.string(),
name: z.string(),
icon: z.string().nullable(),
owner: z.boolean(),
permissions: z.number(),
features: z.array(z.string()),
});
const UserGuildSchema = z.object({
avatar: z.string().nullable(),
communication_disabled_until: z.string().nullable(),
flags: z.number(),
joined_at: z.string(),
nick: z.string().nullable(),
pending: z.boolean(),
premium_since: z.string().nullable(),
roles: z.array(z.string()),
user: z.object({
id: z.string(),
username: z.string(),
global_name: z.string().nullable(),
avatar: z.string().nullable(),
discriminator: z.string(),
public_flags: z.number(),
avatar_decoration: z.string().nullable(),
}),
mute: z.boolean(),
deaf: z.boolean(),
});
var userToWrite: {
discord_id: string,
name: string,
is_admin: boolean,
is_staff: boolean,
is_member: boolean,
}
export default defineEventHandler(async (event) => {
const { code } = getQuery(event)
let create_user = false
if (!code) {
return sendRedirect(event, '/')
}
const response = await fetch("https://discord.com/api/oauth2/token", {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/x-www-form-urlencoded'
},
body: new URLSearchParams({
client_id: '1105533416377688174',
client_secret: '7FdJcfSNvhXpsR_46N-ZnbNoyjV3bl1o',
grant_type: 'authorization_code',
code: (code as string),
redirect_uri: 'http://localhost:3000/auth/v1/callback'
})
});
const data: {
access_token: string,
expires_in: number,
refresh_token: string,
scope: string,
token_type: string
} = await response.json();
const userReq = await fetch("https://discord.com/api/users/@me", {
headers: {
Authorization: `${data.token_type} ${data.access_token}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/x-www-form-urlencoded'
}
});
const user: {
id: string,
username: string,
discriminator: string,
} = await userReq.json();
const dbUser = await prisma.user.findUnique({
where: {
discord_id: user.id
}
})
create_user = dbUser === null
const guilds = await fetch("https://discord.com/api/users/@me/guilds", {
headers: {
Authorization: `${data.token_type} ${data.access_token}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/x-www-form-urlencoded'
}
}).then(async (res) => PartialUserGuildSchema.array().parse(await res.json()));
const guild = guilds.find((g) => g.id === runtimeConfig.discordGuildId);
if (guild) {
prisma.user.update({
where: {
discord_id: user.id
},
data: {
is_member: true
}
})
const member = await fetch(`https://discord.com/api/users/@me/guilds/${guild.id}/member`, {
headers: {
Authorization: `${data.token_type} ${data.access_token}`,
'Content-Type': 'application/x-www-form-urlencoded',
'Accept-Encoding': 'application/x-www-form-urlencoded'
}
}).then((res) => res.json()).then((res) => UserGuildSchema.parse(res))
if (member.roles.find((r) => r === runtimeConfig.discordAdminRoleId)) {
console.log('admin')
userToWrite = {
discord_id: user.id,
name: user.username + '#' + user.discriminator,
is_admin: true,
is_staff: true,
is_member: true
}
} else if (member.roles.find((r) => r === runtimeConfig.discordStaffRoleId)) {
console.log('staff')
userToWrite = {
discord_id: user.id,
name: user.username + '#' + user.discriminator,
is_admin: false,
is_staff: true,
is_member: true
}
} else {
console.log('member')
userToWrite = {
discord_id: user.id,
name: user.username + '#' + user.discriminator,
is_admin: false,
is_staff: false,
is_member: true
}
}
} else {
console.log('not member')
userToWrite = {
discord_id: user.id,
name: user.username + '#' + user.discriminator,
is_admin: false,
is_staff: false,
is_member: false
}
}
if (create_user) {
await prisma.user.create({
data: userToWrite
})
} else {
const transformedUser: typeof userToWrite = {
discord_id: user.id,
name: user.username + '#' + user.discriminator,
is_admin: userToWrite.is_admin,
is_staff: userToWrite.is_staff,
is_member: userToWrite.is_member
}
if (userToWrite !== transformedUser) {
await prisma.user.update({
where: {
discord_id: user.id
},
data: userToWrite
})
}
}
const secret = new TextEncoder().encode(runtimeConfig.jwtSecret)
const token = await new jose.SignJWT({ sub: user.id })
.setProtectedHeader({ alg: 'HS512' })
.setIssuedAt()
.setIssuer('https://vannerba.st')
.setAudience('https://vannerba.st')
.setExpirationTime('5h')
.sign(secret)
setCookie(event, 'token', token)
return sendRedirect(event, '/dash')
})