initial commit: fork

This commit is contained in:
2023-10-27 10:31:20 +02:00
commit a52dbbc103
195 changed files with 17484 additions and 0 deletions

28
packages/auth/env.mjs Normal file
View File

@@ -0,0 +1,28 @@
import { createEnv } from '@t3-oss/env-nextjs';
import { z } from 'zod';
export const env = createEnv({
server: {
DISCORD_CLIENT_ID: z.string().min(1),
DISCORD_CLIENT_SECRET: z.string().min(1),
NEXTAUTH_SECRET:
process.env.NODE_ENV === 'production'
? z.string().min(1)
: z.string().min(1).optional(),
NEXTAUTH_URL: z.preprocess(
// This makes Vercel deployments not fail if you don't set NEXTAUTH_URL
// Since NextAuth.js automatically uses the VERCEL_URL if present.
str => process.env.VERCEL_URL ?? str,
// VERCEL_URL doesn't include `https` so it cant be validated as a URL
process.env.VERCEL ? z.string() : z.string().url()
)
},
client: {},
runtimeEnv: {
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
NEXTAUTH_URL: process.env.NEXTAUTH_URL,
DISCORD_CLIENT_ID: process.env.DISCORD_CLIENT_ID,
DISCORD_CLIENT_SECRET: process.env.DISCORD_CLIENT_SECRET
},
skipValidation: !!process.env.CI || !!process.env.SKIP_ENV_VALIDATION
});

134
packages/auth/index.ts Normal file
View File

@@ -0,0 +1,134 @@
// @ts-nocheck
import Discord, { type DiscordProfile } from '@auth/core/providers/discord';
import type { DefaultSession as DefaultSessionType } from '@auth/core/types';
import { PrismaAdapter } from '@auth/prisma-adapter';
import { prisma } from '@master-bot/db';
import NextAuth from 'next-auth';
import { env } from './env.mjs';
export type { Session } from 'next-auth';
// Update this whenever adding new providers so that the client can
export const providers = ['discord'] as const;
export type OAuthProviders = (typeof providers)[number];
declare module 'next-auth' {
interface Session {
user: {
id: string;
discordId: string;
} & DefaultSessionType['user'];
}
}
const scope = ['identify', 'guilds', 'email'].join(' ');
export const {
handlers: { GET, POST },
auth,
CSRF_experimental
} = NextAuth({
adapter: {
...PrismaAdapter(prisma),
createUser: async data => {
return await prisma.user.upsert({
where: { discordId: data.discordId },
update: data,
create: data
});
}
},
providers: [
Discord({
clientId: env.DISCORD_CLIENT_ID,
clientSecret: env.DISCORD_CLIENT_SECRET,
authorization: {
params: {
scope
}
},
profile(profile: DiscordProfile) {
return {
id: profile.id,
name: profile.username,
email: profile.email,
image: profile.avatar,
discordId: profile.id
};
}
})
],
callbacks: {
session: async ({ session, user }) => {
const account = await prisma.account.findUnique({
where: {
userId: user.id
}
});
if (account?.expires_at * 1000 < Date.now()) {
// refresh token
try {
const response = await fetch(
'https://discord.com/api/v10/oauth2/token',
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
method: 'POST',
body: new URLSearchParams({
grant_type: 'refresh_token',
client_id: env.DISCORD_CLIENT_ID,
client_secret: env.DISCORD_CLIENT_SECRET,
refresh_token: account.refresh_token
})
}
);
if (!response.ok) {
throw new Error('Failed to refresh token');
}
const data = await response.json();
await prisma.account.update({
where: {
userId: user.id
},
data: {
access_token: data.access_token,
refresh_token: data.refresh_token,
expires_at: data.expires_in
}
});
} catch (error) {
console.log(error);
}
}
return {
...session,
user: {
...session.user,
id: user.id,
discordId: user.discordId
}
};
}
// @TODO - if you wanna have auth on the edge
// jwt: ({ token, profile }) => {
// if (profile?.id) {
// token.id = profile.id;
// token.image = profile.picture;
// }
// return token;
// },
// @TODO
// authorized({ request, auth }) {
// return !!auth?.user
// }
}
});

View File

@@ -0,0 +1,35 @@
{
"name": "@master-bot/auth",
"version": "0.1.0",
"main": "./index.ts",
"types": "./index.ts",
"license": "ISC",
"scripts": {
"clean": "rm -rf .turbo node_modules",
"lint": "eslint .",
"lint:fix": "pnpm lint --fix",
"type-check": "tsc --noEmit"
},
"dependencies": {
"@auth/core": "^0.10.0",
"@auth/prisma-adapter": "^1.0.1",
"@master-bot/db": "^0.1.0",
"@t3-oss/env-nextjs": "^0.6.0",
"next": "^13.4.12",
"next-auth": "^0.0.0-manual.b53ca00b",
"react": "18.2.0",
"react-dom": "18.2.0",
"zod": "^3.21.4"
},
"devDependencies": {
"@master-bot/eslint-config": "^0.2.0",
"eslint": "^8.46.0",
"typescript": "^5.1.6"
},
"eslintConfig": {
"root": true,
"extends": [
"@master-bot/eslint-config/base"
]
}
}

View File

@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["src", "*.ts", "env.mjs"]
}