From de795b6c88b57c696932fa6b70ecd2caf93ab89e Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Thu, 3 Aug 2023 11:59:25 +0000 Subject: [PATCH] DRY up code --- src/server/index.ts | 4 +- src/server/lib/middleware.ts | 24 +++++++ src/server/routes/adminRoutes.ts | 53 ++++---------- src/server/routes/authRoutes.ts | 111 +++++++++-------------------- src/server/routes/fileApiRoutes.ts | 4 +- 5 files changed, 75 insertions(+), 121 deletions(-) create mode 100644 src/server/lib/middleware.ts diff --git a/src/server/index.ts b/src/server/index.ts index 7fc9f93..561d4e0 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -206,10 +206,11 @@ app.get("/server",(req,res) => { })) }) -app.get(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"],async (req:express.Request,res:express.Response) => { +app.get(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], async (req:express.Request,res:express.Response) => { let file = files.getFilePointer(req.params.fileId) res.setHeader("Access-Control-Allow-Origin", "*") + res.setHeader("Content-Security-Policy","sandbox allow-scripts") if (req.query.attachment == "1") res.setHeader("Content-Disposition", "attachment") if (file) { @@ -273,6 +274,7 @@ app.get(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"],async (req:express.Reque app.head(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], (req: express.Request, res:express.Response) => { let file = files.getFilePointer(req.params.fileId) res.setHeader("Access-Control-Allow-Origin", "*") + res.setHeader("Content-Security-Policy","sandbox allow-scripts") if (req.query.attachment == "1") res.setHeader("Content-Disposition", "attachment") if (!file) { res.status(404) diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts new file mode 100644 index 0000000..a56ba95 --- /dev/null +++ b/src/server/lib/middleware.ts @@ -0,0 +1,24 @@ +import * as Accounts from "./accounts"; +import express, { type RequestHandler } from "express" +import ServeError from "../lib/errors"; + +export let getAccount: RequestHandler = function(req, res, next) { + res.locals.acc = Accounts.getFromToken(req.cookies.auth) + next() +} + +export let requiresAccount: RequestHandler = function(_req, res, next) { + if (!res.locals.acc) { + ServeError(res, 401, "not logged in") + return + } + next() +} + +export let requiresAdmin: RequestHandler = function(_req, res, next) { + if (!res.locals.acc.admin) { + ServeError(res, 403, "you are not an administrator") + return + } + next() +} \ No newline at end of file diff --git a/src/server/routes/adminRoutes.ts b/src/server/routes/adminRoutes.ts index 78cfcf2..85e7c61 100644 --- a/src/server/routes/adminRoutes.ts +++ b/src/server/routes/adminRoutes.ts @@ -5,6 +5,7 @@ import * as auth from "../lib/auth"; import bytes from "bytes" import {writeFile} from "fs"; import { sendMail } from "../lib/mail"; +import { getAccount, requiresAccount, requiresAdmin } from "../lib/middleware" import ServeError from "../lib/errors"; import Files from "../lib/files"; @@ -14,6 +15,10 @@ let parser = bodyParser.json({ }) export let adminRoutes = Router(); +adminRoutes + .use(getAccount) + .use(requiresAccount) + .use(requiresAdmin) let files:Files export function admin_setFilesObj(newFiles:Files) { @@ -21,7 +26,7 @@ export function admin_setFilesObj(newFiles:Files) { } let config = require(`${process.cwd()}/config.json`) - +/* adminRoutes.post("/manage", parser, (req,res) => { if (!auth.validate(req.cookies.auth)) { @@ -35,18 +40,11 @@ adminRoutes.post("/manage", parser, (req,res) => { if (!acc.admin) return }) - +*/ adminRoutes.post("/reset", parser, (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } - - let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account + let acc = res.locals.acc as Accounts.Account - if (!acc) return - if (!acc.admin) return if (typeof req.body.target !== "string" || typeof req.body.password !== "string") { res.status(404) res.send() @@ -70,15 +68,8 @@ adminRoutes.post("/reset", parser, (req,res) => { adminRoutes.post("/elevate", parser, (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } + let acc = res.locals.acc as Accounts.Account - let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account - - if (!acc) return - if (!acc.admin) return if (typeof req.body.target !== "string") { res.status(404) res.send() @@ -100,15 +91,8 @@ adminRoutes.post("/elevate", parser, (req,res) => { adminRoutes.post("/delete", parser, (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } - - let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account + let acc = res.locals.acc as Accounts.Account - if (!acc) return - if (!acc.admin) return if (typeof req.body.target !== "string") { res.status(404) res.send() @@ -132,15 +116,9 @@ adminRoutes.post("/delete", parser, (req,res) => { }) adminRoutes.post("/delete_account", parser, async (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } - let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account + let acc = res.locals.acc as Accounts.Account - if (!acc) return - if (!acc.admin) return if (typeof req.body.target !== "string") { res.status(404) res.send() @@ -182,15 +160,8 @@ adminRoutes.post("/delete_account", parser, async (req,res) => { adminRoutes.post("/transfer", parser, (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } - - let acc = Accounts.getFromToken(req.cookies.auth) as Accounts.Account + let acc = res.locals.acc as Accounts.Account - if (!acc) return - if (!acc.admin) return if (typeof req.body.target !== "string" || typeof req.body.owner !== "string") { res.status(404) res.send() diff --git a/src/server/routes/authRoutes.ts b/src/server/routes/authRoutes.ts index 96084e0..8c156b5 100644 --- a/src/server/routes/authRoutes.ts +++ b/src/server/routes/authRoutes.ts @@ -3,6 +3,7 @@ import { Router } from "express"; import * as Accounts from "../lib/accounts"; import * as auth from "../lib/auth"; import { sendMail } from "../lib/mail"; +import { getAccount, requiresAccount } from "../lib/middleware" import ServeError from "../lib/errors"; import Files, { FileVisibility, generateFileId, id_check_regex } from "../lib/files"; @@ -14,6 +15,7 @@ let parser = bodyParser.json({ }) export let authRoutes = Router(); +authRoutes.use(getAccount) let config = require(`${process.cwd()}/config.json`) @@ -120,12 +122,8 @@ authRoutes.post("/logout", (req,res) => { res.send("logged out") }) -authRoutes.post("/dfv", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/dfv", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account if (['public','private','anonymous'].includes(req.body.defaultFileVisibility)) { acc.defaultFileVisibility = req.body.defaultFileVisibility @@ -137,12 +135,8 @@ authRoutes.post("/dfv", parser, (req,res) => { } }) -authRoutes.post("/customcss", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/customcss", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account if (typeof req.body.fileId != "string") req.body.fileId = undefined; @@ -163,12 +157,8 @@ authRoutes.post("/customcss", parser, (req,res) => { } }) -authRoutes.post("/embedcolor", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/embedcolor", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account if (typeof req.body.color != "string") req.body.color = undefined; @@ -190,12 +180,8 @@ authRoutes.post("/embedcolor", parser, (req,res) => { } }) -authRoutes.post("/embedsize", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/embedsize", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account if (typeof req.body.largeImage != "boolean") req.body.color = false; @@ -206,12 +192,9 @@ authRoutes.post("/embedsize", parser, (req,res) => { res.send(`custom embed image size saved`) }) -authRoutes.post("/delete_account", parser, async (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/delete_account", requiresAccount, parser, async (req,res) => { + let acc = res.locals.acc as Accounts.Account + let accId = acc.id auth.AuthTokens.filter(e => e.account == accId).forEach((v) => { @@ -233,12 +216,8 @@ authRoutes.post("/delete_account", parser, async (req,res) => { } else cpl() }) -authRoutes.post("/change_username", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/change_username", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account if (typeof req.body.username != "string" || req.body.username.length < 3 || req.body.username.length > 20) { ServeError(res,400,"username must be between 3 and 20 characters in length") @@ -267,12 +246,9 @@ authRoutes.post("/change_username", parser, (req,res) => { let verificationCodes = new Map() -authRoutes.post("/request_email_change", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/request_email_change", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account + if (typeof req.body.email != "string" || !req.body.email) { ServeError(res,400, "supply an email") @@ -315,12 +291,9 @@ authRoutes.post("/request_email_change", parser, (req,res) => { }) }) -authRoutes.get("/confirm_email/:code", (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.get("/confirm_email/:code", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account + let vcode = verificationCodes.get(acc.id) @@ -419,13 +392,9 @@ authRoutes.get("/emergency_login/:code", (req,res) => { } }) -authRoutes.post("/change_password", parser, (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } - +authRoutes.post("/change_password", requiresAccount, parser, (req,res) => { + let acc = res.locals.acc as Accounts.Account + if (typeof req.body.password != "string" || req.body.password.length < 8) { ServeError(res,400,"password must be 8 characters or longer") return @@ -442,12 +411,8 @@ authRoutes.post("/change_password", parser, (req,res) => { res.send("password changed - logged out all sessions") }) -authRoutes.post("/logout_sessions", (req,res) => { - let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) { - ServeError(res, 401, "not logged in") - return - } +authRoutes.post("/logout_sessions", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account let accId = acc.id @@ -458,23 +423,15 @@ authRoutes.post("/logout_sessions", (req,res) => { res.send("logged out all sessions") }) -authRoutes.get("/me", (req,res) => { - if (!auth.validate(req.cookies.auth)) { - ServeError(res, 401, "not logged in") - return - } - - // lazy rn so +authRoutes.get("/me", requiresAccount, (req,res) => { + let acc = res.locals.acc as Accounts.Account - let acc = Accounts.getFromToken(req.cookies.auth) - if (acc) { - let accId = acc.id - res.send({ - ...acc, - sessionCount: auth.AuthTokens.filter(e => e.account == accId && e.expire > Date.now()).length, - sessionExpires: auth.AuthTokens.find(e => e.token == req.cookies.auth)?.expire - }) - } + let accId = acc.id + res.send({ + ...acc, + sessionCount: auth.AuthTokens.filter(e => e.account == accId && e.expire > Date.now()).length, + sessionExpires: auth.AuthTokens.find(e => e.token == req.cookies.auth)?.expire + }) }) authRoutes.get("/customCSS", (req,res) => { diff --git a/src/server/routes/fileApiRoutes.ts b/src/server/routes/fileApiRoutes.ts index 1d54c9a..be461c9 100644 --- a/src/server/routes/fileApiRoutes.ts +++ b/src/server/routes/fileApiRoutes.ts @@ -30,11 +30,11 @@ fileApiRoutes.get("/list", (req,res) => { let acc = Accounts.getFromToken(req.cookies.auth) - if (!acc) return + if (!acc) return let accId = acc.id res.send(acc.files.map((e) => { - let fp = files.getFilePointer(e) + let fp = files.getFilePointer(e) if (!fp) { Accounts.files.deindex(accId, e); return null } return { ...fp,