auth
This commit is contained in:
parent
f25011b10d
commit
63b6adfdbe
7 changed files with 209 additions and 15 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
/node_modules/
|
||||
/.idea/
|
||||
.env
|
||||
./src/uploads
|
||||
|
|
|
@ -13,7 +13,9 @@
|
|||
"license": "ISC",
|
||||
"packageManager": "pnpm@9.12.3+sha512.cce0f9de9c5a7c95bef944169cc5dfe8741abfb145078c0d508b868056848a87c81e626246cb60967cbd7fd29a6c062ef73ff840d96b3c86c40ac92cf4a813ee",
|
||||
"dependencies": {
|
||||
"@fastify/cookie": "^11.0.1",
|
||||
"@fastify/multipart": "^9.0.1",
|
||||
"@fastify/oauth2": "^8.1.0",
|
||||
"@prisma/client": "6.0.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"fastify": "^5.1.0",
|
||||
|
|
121
pnpm-lock.yaml
generated
121
pnpm-lock.yaml
generated
|
@ -8,9 +8,15 @@ importers:
|
|||
|
||||
.:
|
||||
dependencies:
|
||||
'@fastify/cookie':
|
||||
specifier: ^11.0.1
|
||||
version: 11.0.1
|
||||
'@fastify/multipart':
|
||||
specifier: ^9.0.1
|
||||
version: 9.0.1
|
||||
'@fastify/oauth2':
|
||||
specifier: ^8.1.0
|
||||
version: 8.1.0
|
||||
'@prisma/client':
|
||||
specifier: 6.0.0
|
||||
version: 6.0.0(prisma@6.0.0)
|
||||
|
@ -42,6 +48,9 @@ packages:
|
|||
'@fastify/busboy@3.0.0':
|
||||
resolution: {integrity: sha512-83rnH2nCvclWaPQQKvkJ2pdOjG4TZyEVuFDnlOF6KP08lDaaceVyw/W63mDuafQT+MKHCvXIPpE5uYWeM0rT4w==}
|
||||
|
||||
'@fastify/cookie@11.0.1':
|
||||
resolution: {integrity: sha512-n1Ooz4bgQ5LcOlJQboWPfsMNxIrGV0SgU85UkctdpTlCQE0mtA3rlspOPUdqk9ubiiZn053ucnia4DjTquI4/g==}
|
||||
|
||||
'@fastify/deepmerge@2.0.0':
|
||||
resolution: {integrity: sha512-fsaybTGDyQ5KpPsplQqb9yKdCf2x/pbNpMNk8Tvp3rRz7lVcupKysH4b2ELMN2P4Hak1+UqTYdTj/u4FNV2p0g==}
|
||||
|
||||
|
@ -57,6 +66,27 @@ packages:
|
|||
'@fastify/multipart@9.0.1':
|
||||
resolution: {integrity: sha512-vt2gOCw/O4EwpN4KlLVJxth4iQlDf7T5ggw2Db2C+UbO2WJBG7y0jEBvu/HT6JIW/lBYaqrrUy9MmTpCKgXEpw==}
|
||||
|
||||
'@fastify/oauth2@8.1.0':
|
||||
resolution: {integrity: sha512-SMcvStTvhF+UcyH+7uLWvKrxM4g5evZafjtQWRAg02C/dlsOrqLK0s9/1aszhWY6PBklJ6jduFPpl+sB4l2DlQ==}
|
||||
|
||||
'@hapi/boom@10.0.1':
|
||||
resolution: {integrity: sha512-ERcCZaEjdH3OgSJlyjVk8pHIFeus91CjKP3v+MpgBNp5IvGzP2l/bRiD78nqYcKPaZdbKkK5vDBVPd2ohHBlsA==}
|
||||
|
||||
'@hapi/bourne@3.0.0':
|
||||
resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==}
|
||||
|
||||
'@hapi/hoek@11.0.7':
|
||||
resolution: {integrity: sha512-HV5undWkKzcB4RZUusqOpcgxOaq6VOAH7zhhIr2g3G8NF/MlFO75SjOr2NfuSx0Mh40+1FqCkagKLJRykUWoFQ==}
|
||||
|
||||
'@hapi/hoek@9.3.0':
|
||||
resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==}
|
||||
|
||||
'@hapi/topo@5.1.0':
|
||||
resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==}
|
||||
|
||||
'@hapi/wreck@18.1.0':
|
||||
resolution: {integrity: sha512-0z6ZRCmFEfV/MQqkQomJ7sl/hyxvcZM7LtuVqN3vdAO4vM9eBbowl0kaqQj9EJJQab+3Uuh1GxbGIBFy4NfJ4w==}
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2':
|
||||
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
@ -91,6 +121,15 @@ packages:
|
|||
'@prisma/get-platform@6.0.0':
|
||||
resolution: {integrity: sha512-PS6nYyIm9g8C03E4y7LknOfdCw/t2KyEJxntMPQHQZCOUgOpF82Ma60mdlOD08w90I3fjLiZZ0+MadenR3naDQ==}
|
||||
|
||||
'@sideway/address@4.1.5':
|
||||
resolution: {integrity: sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==}
|
||||
|
||||
'@sideway/formula@3.0.1':
|
||||
resolution: {integrity: sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==}
|
||||
|
||||
'@sideway/pinpoint@2.0.0':
|
||||
resolution: {integrity: sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==}
|
||||
|
||||
'@tsconfig/node10@1.0.11':
|
||||
resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
|
||||
|
||||
|
@ -146,6 +185,15 @@ packages:
|
|||
create-require@1.1.1:
|
||||
resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
|
||||
|
||||
debug@4.3.7:
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
diff@4.0.2:
|
||||
resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
|
||||
engines: {node: '>=0.3.1'}
|
||||
|
@ -202,6 +250,9 @@ packages:
|
|||
resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
|
||||
engines: {node: '>= 0.10'}
|
||||
|
||||
joi@17.13.3:
|
||||
resolution: {integrity: sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==}
|
||||
|
||||
json-schema-ref-resolver@1.0.1:
|
||||
resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==}
|
||||
|
||||
|
@ -214,6 +265,9 @@ packages:
|
|||
make-error@1.3.6:
|
||||
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
on-exit-leak-free@2.1.2:
|
||||
resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
|
@ -333,6 +387,9 @@ packages:
|
|||
set-cookie-parser@2.7.1:
|
||||
resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
|
||||
|
||||
simple-oauth2@5.1.0:
|
||||
resolution: {integrity: sha512-gWDa38Ccm4MwlG5U7AlcJxPv3lvr80dU7ARJWrGdgvOKyzSj1gr3GBPN1rABTedAYvC/LsGYoFuFxwDBPtGEbw==}
|
||||
|
||||
sonic-boom@4.2.0:
|
||||
resolution: {integrity: sha512-INb7TM37/mAcsGmc9hyyI6+QR3rR1zVRu36B0NeGXKnOOLiZOfER5SA+N7X7k3yUYRzLWafduTDvJAfDswwEww==}
|
||||
|
||||
|
@ -394,6 +451,11 @@ snapshots:
|
|||
|
||||
'@fastify/busboy@3.0.0': {}
|
||||
|
||||
'@fastify/cookie@11.0.1':
|
||||
dependencies:
|
||||
cookie: 1.0.2
|
||||
fastify-plugin: 5.0.1
|
||||
|
||||
'@fastify/deepmerge@2.0.0': {}
|
||||
|
||||
'@fastify/error@4.0.0': {}
|
||||
|
@ -414,6 +476,34 @@ snapshots:
|
|||
fastify-plugin: 5.0.1
|
||||
secure-json-parse: 3.0.1
|
||||
|
||||
'@fastify/oauth2@8.1.0':
|
||||
dependencies:
|
||||
'@fastify/cookie': 11.0.1
|
||||
fastify-plugin: 5.0.1
|
||||
simple-oauth2: 5.1.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@hapi/boom@10.0.1':
|
||||
dependencies:
|
||||
'@hapi/hoek': 11.0.7
|
||||
|
||||
'@hapi/bourne@3.0.0': {}
|
||||
|
||||
'@hapi/hoek@11.0.7': {}
|
||||
|
||||
'@hapi/hoek@9.3.0': {}
|
||||
|
||||
'@hapi/topo@5.1.0':
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
|
||||
'@hapi/wreck@18.1.0':
|
||||
dependencies:
|
||||
'@hapi/boom': 10.0.1
|
||||
'@hapi/bourne': 3.0.0
|
||||
'@hapi/hoek': 11.0.7
|
||||
|
||||
'@jridgewell/resolve-uri@3.1.2': {}
|
||||
|
||||
'@jridgewell/sourcemap-codec@1.5.0': {}
|
||||
|
@ -448,6 +538,14 @@ snapshots:
|
|||
dependencies:
|
||||
'@prisma/debug': 6.0.0
|
||||
|
||||
'@sideway/address@4.1.5':
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
|
||||
'@sideway/formula@3.0.1': {}
|
||||
|
||||
'@sideway/pinpoint@2.0.0': {}
|
||||
|
||||
'@tsconfig/node10@1.0.11': {}
|
||||
|
||||
'@tsconfig/node12@1.0.11': {}
|
||||
|
@ -492,6 +590,10 @@ snapshots:
|
|||
|
||||
create-require@1.1.1: {}
|
||||
|
||||
debug@4.3.7:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
diff@4.0.2: {}
|
||||
|
||||
dotenv@16.4.5: {}
|
||||
|
@ -557,6 +659,14 @@ snapshots:
|
|||
|
||||
ipaddr.js@1.9.1: {}
|
||||
|
||||
joi@17.13.3:
|
||||
dependencies:
|
||||
'@hapi/hoek': 9.3.0
|
||||
'@hapi/topo': 5.1.0
|
||||
'@sideway/address': 4.1.5
|
||||
'@sideway/formula': 3.0.1
|
||||
'@sideway/pinpoint': 2.0.0
|
||||
|
||||
json-schema-ref-resolver@1.0.1:
|
||||
dependencies:
|
||||
fast-deep-equal: 3.1.3
|
||||
|
@ -571,6 +681,8 @@ snapshots:
|
|||
|
||||
make-error@1.3.6: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
on-exit-leak-free@2.1.2: {}
|
||||
|
||||
pg-cloudflare@1.1.1:
|
||||
|
@ -677,6 +789,15 @@ snapshots:
|
|||
|
||||
set-cookie-parser@2.7.1: {}
|
||||
|
||||
simple-oauth2@5.1.0:
|
||||
dependencies:
|
||||
'@hapi/hoek': 11.0.7
|
||||
'@hapi/wreck': 18.1.0
|
||||
debug: 4.3.7
|
||||
joi: 17.13.3
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
sonic-boom@4.2.0:
|
||||
dependencies:
|
||||
atomic-sleep: 1.0.0
|
||||
|
|
8
prisma/migrations/20241201191003_balls/migration.sql
Normal file
8
prisma/migrations/20241201191003_balls/migration.sql
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- The required column `apiToken` was added to the `User` table with a prisma-level default value. This is not possible if the table is not empty. Please add this column as optional, then populate it before making it required.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "User" ADD COLUMN "apiToken" UUID NOT NULL;
|
|
@ -18,8 +18,9 @@ model WhitelistedUsers {
|
|||
}
|
||||
|
||||
model User {
|
||||
id String @id
|
||||
id String @id
|
||||
discordToken String
|
||||
apiToken String @default(uuid()) @db.Uuid
|
||||
imagePosts FilePost[]
|
||||
}
|
||||
|
||||
|
@ -27,5 +28,5 @@ model FilePost {
|
|||
id String @id @default(uuid()) @db.Uuid
|
||||
fileName String
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import {DiscordUser} from "./types.ts";
|
|||
import {FastifyRequest} from "fastify";
|
||||
|
||||
export function getAdmins(): string[] {
|
||||
return process.env.ADMINS.split(":")
|
||||
return process.env.ADMINS.split(",")
|
||||
}
|
||||
|
||||
export async function isTokenValid(token: string):Promise<boolean> {
|
||||
|
@ -17,6 +17,16 @@ export async function isTokenValid(token: string):Promise<boolean> {
|
|||
});
|
||||
}
|
||||
|
||||
export async function getUser(token: string): Promise<DiscordUser> {
|
||||
const response = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: new Headers({
|
||||
"Authorization": `Bearer ${token}`
|
||||
})
|
||||
});
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
export async function isAdmin(token: string): Promise<boolean> {
|
||||
const response = await fetch("https://discord.com/api/users/@me", {
|
||||
headers: new Headers({
|
||||
|
|
75
src/main.ts
75
src/main.ts
|
@ -1,12 +1,13 @@
|
|||
import Fastify from 'fastify'
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
import {PrismaClient} from '@prisma/client'
|
||||
import fastifyMultipart from "@fastify/multipart";
|
||||
import fastifyOauth2 from "@fastify/oauth2";
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import dotenv from 'dotenv';
|
||||
import { fileURLToPath } from 'url';
|
||||
import {isAdmin, isTokenValid} from "./authHelper.ts";
|
||||
import {fileURLToPath} from 'url';
|
||||
import {checkadmin} from "./middleware.ts";
|
||||
import {getUser} from "./authHelper.ts";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
|
@ -19,17 +20,68 @@ export const __filename = fileURLToPath(import.meta.url);
|
|||
export const __dirname = path.dirname(__filename);
|
||||
|
||||
const prisma = new PrismaClient()
|
||||
const fastify = Fastify({ logger: true })
|
||||
const fastify = Fastify({logger: true})
|
||||
|
||||
// Register fastify-multipart for file uploads
|
||||
fastify.register(fastifyMultipart)
|
||||
fastify.register(fastifyOauth2, {
|
||||
name: 'discordOAuth2',
|
||||
credentials: {
|
||||
client: {
|
||||
id: process.env.DISCORD_CLIENT,
|
||||
secret: process.env.DISCORD_SECRET,
|
||||
},
|
||||
auth: fastifyOauth2.DISCORD_CONFIGURATION
|
||||
},
|
||||
scope: ["identify"],
|
||||
startRedirectPath: '/login',
|
||||
callbackUri: req => `${req.protocol}://${req.host}/login/callback`,
|
||||
})
|
||||
|
||||
|
||||
// Upload directory
|
||||
const uploadDir = path.join(__dirname, 'uploads')
|
||||
if (!fs.existsSync(uploadDir)) {
|
||||
fs.mkdirSync(uploadDir)
|
||||
}
|
||||
|
||||
fastify.get('/login/callback', async function (request, reply) {
|
||||
// @ts-ignore
|
||||
const {token} = await this.discordOAuth2?.getAccessTokenFromAuthorizationCodeFlow(request)
|
||||
//this is funny
|
||||
const discordAccount = await getUser(token.access_token)
|
||||
if (!await prisma.whitelistedUsers.findUnique({
|
||||
where: {
|
||||
discordId: discordAccount.id
|
||||
}
|
||||
})) {
|
||||
return reply.status(401).send("Not Authorized")
|
||||
}
|
||||
// @ts-ignore
|
||||
const existingUser = await prisma.users.findUnique({
|
||||
where: {id: discordAccount.id},
|
||||
});
|
||||
// @ts-ignore
|
||||
const {token: refreshToken} = await this.discordOAuth2?.getNewAccessTokenUsingRefreshToken(token)
|
||||
if (!existingUser) {
|
||||
await prisma.user.create({
|
||||
data: {
|
||||
id: discordAccount.id,
|
||||
discordToken: refreshToken.access_token,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
reply.send({access_token: refreshToken.access_token})
|
||||
reply.setCookie('access_token', refreshToken.access_token)
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
fastify.post('/api/admin/addwhitelist', async (request, reply) => {
|
||||
const test = await checkadmin(request)
|
||||
if (!test) return reply.status(401).send('Not Authorized');
|
||||
|
@ -38,16 +90,15 @@ fastify.post('/api/admin/addwhitelist', async (request, reply) => {
|
|||
reply.status(400).send('Bad Request');
|
||||
}
|
||||
await prisma.whitelistedUsers.create({
|
||||
data: {
|
||||
discordId: id,
|
||||
}
|
||||
data: {
|
||||
discordId: id,
|
||||
}
|
||||
}).then(() => {
|
||||
reply.status(200).send('User added successfully');
|
||||
})
|
||||
})
|
||||
|
||||
fastify.get('/', async (request, reply) => {
|
||||
|
||||
return reply.status(200).send('ok')
|
||||
})
|
||||
|
||||
|
@ -75,11 +126,11 @@ fastify.post('/api/upload', async (request, reply) => {
|
|||
// reply.code(201).send(newImagePost)
|
||||
} catch (error) {
|
||||
fastify.log.error(error)
|
||||
reply.code(500).send({ error: 'Error uploading file or saving record' })
|
||||
reply.code(500).send({error: 'Error uploading file or saving record'})
|
||||
}
|
||||
})
|
||||
|
||||
fastify.listen({ port: 3000 }, (err, address) => {
|
||||
fastify.listen({port: 3000}, (err, address) => {
|
||||
if (err) {
|
||||
fastify.log.error(err)
|
||||
process.exit(1)
|
||||
|
|
Loading…
Add table
Reference in a new issue