203 lines
5.9 KiB
TypeScript
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')
|
|
}) |