diff --git a/config.json b/config.json
index 985642f..f2e8469 100644
--- a/config.json
+++ b/config.json
@@ -27,5 +27,5 @@
},
"trustProxy": true,
- "forceSSL": true
+ "forceSSL": false
}
\ No newline at end of file
diff --git a/src/server/index.ts b/src/server/index.ts
index 68819e6..6baf6c6 100644
--- a/src/server/index.ts
+++ b/src/server/index.ts
@@ -8,13 +8,10 @@ import ServeError from "./lib/errors"
import Files from "./lib/files"
import * as auth from "./lib/auth"
import * as Accounts from "./lib/accounts"
-
-import * as authRoutes from "./routes/authRoutes";
-import * as fileApiRoutes from "./routes/fileApiRoutes";
-import * as adminRoutes from "./routes/adminRoutes";
-import * as primaryApi from "./routes/primaryApi";
import { getAccount } from "./lib/middleware";
+import APIRouter from "./routes/api"
+
require("dotenv").config()
let pkg = require(`${process.cwd()}/package.json`)
@@ -46,19 +43,12 @@ app.get("/server",(req,res) => {
}))
})
-app
- .use("/auth",authRoutes.authRoutes)
- .use("/admin",adminRoutes.adminRoutes)
- .use("/files", fileApiRoutes.fileApiRoutes)
- .use(primaryApi.primaryApi)
// funcs
// init data
if (!fs.existsSync(__dirname+"/../.data/")) fs.mkdirSync(__dirname+"/../.data/")
-
-
// discord
let client = new Client({intents:[
@@ -68,12 +58,11 @@ let client = new Client({intents:[
let files = new Files(client,config)
-authRoutes.setFilesObj(files)
-adminRoutes.setFilesObj(files)
-fileApiRoutes.setFilesObj(files)
-primaryApi.setFilesObj(files)
-
-// routes (could probably make these use routers)
+let apiRouter = new APIRouter(files)
+apiRouter.loadAPIMethods().then(() => {
+ app.use(apiRouter.root)
+ console.log("API OK!")
+})
// index, clone
diff --git a/src/server/routes/adminRoutes.ts b/src/server/routes/adminRoutes.ts
deleted file mode 100644
index 510eec2..0000000
--- a/src/server/routes/adminRoutes.ts
+++ /dev/null
@@ -1,235 +0,0 @@
-import bodyParser from "body-parser";
-import { Router } from "express";
-import * as Accounts from "../lib/accounts";
-import * as auth from "../lib/auth";
-import bytes from "bytes"
-import {writeFile} from "fs";
-import { sendMail } from "../lib/mail";
-import { getAccount, requiresAccount, requiresAdmin, requiresPermissions } from "../lib/middleware"
-
-import ServeError from "../lib/errors";
-import Files from "../lib/files";
-
-let parser = bodyParser.json({
- type: ["text/plain","application/json"]
-})
-
-export let adminRoutes = Router();
-adminRoutes
- .use(getAccount)
- .use(requiresAccount)
- .use(requiresAdmin)
- .use(requiresPermissions("admin"))
-let files:Files
-
-export function setFilesObj(newFiles:Files) {
- files = newFiles
-}
-
-let config = require(`${process.cwd()}/config.json`)
-
-adminRoutes.post("/reset", parser, (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.target !== "string" || typeof req.body.password !== "string") {
- res.status(404)
- res.send()
- return
- }
-
- let targetAccount = Accounts.getFromUsername(req.body.target)
- if (!targetAccount) {
- res.status(404)
- res.send()
- return
- }
-
- Accounts.password.set ( targetAccount.id, req.body.password )
- auth.AuthTokens.filter(e => e.account == targetAccount?.id).forEach((v) => {
- auth.invalidate(v.token)
- })
-
- if (targetAccount.email) {
- sendMail(targetAccount.email, `Your login details have been updated`, `Hello there! This email is to notify you of a password change that an administrator, ${acc.username}, has initiated. You have been logged out of your devices. Thank you for using monofile.`).then(() => {
- res.send("OK")
- }).catch((err) => {})
- }
-
-
- res.send()
-
-})
-
-adminRoutes.post("/elevate", parser, (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.target !== "string") {
- res.status(404)
- res.send()
- return
- }
-
- let targetAccount = Accounts.getFromUsername(req.body.target)
- if (!targetAccount) {
- res.status(404)
- res.send()
- return
- }
-
- targetAccount.admin = true;
- Accounts.save()
- res.send()
-
-})
-
-adminRoutes.post("/delete", parser, (req,res) => {
-
- if (typeof req.body.target !== "string") {
- res.status(404)
- res.send()
- return
- }
-
- let targetFile = files.getFilePointer(req.body.target)
-
- if (!targetFile) {
- res.status(404)
- res.send()
- return
- }
-
- files.unlink(req.body.target).then(() => {
- res.status(200)
- }).catch(() => {
- res.status(500)
- }).finally(() => res.send())
-
-})
-
-adminRoutes.post("/delete_account", parser, async (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.target !== "string") {
- res.status(404)
- res.send()
- return
- }
-
- let targetAccount = Accounts.getFromUsername(req.body.target)
- if (!targetAccount) {
- res.status(404)
- res.send()
- return
- }
-
- let accId = targetAccount.id
-
- auth.AuthTokens.filter(e => e.account == accId).forEach((v) => {
- auth.invalidate(v.token)
- })
-
- let cpl = () => Accounts.deleteAccount(accId).then(_ => {
- if (targetAccount?.email) {
- sendMail(targetAccount.email, "Notice of account deletion", `Your account, ${targetAccount.username}, has been deleted by ${acc.username} for the following reason:
${req.body.reason || "(no reason specified)"}
Your files ${req.body.deleteFiles ? "have been deleted" : "have not been modified"}. Thank you for using monofile.`)
- }
- res.send("account deleted")
- })
-
- if (req.body.deleteFiles) {
- let f = targetAccount.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die
- for (let v of f) {
- files.unlink(v,true).catch(err => console.error(err))
- }
-
- writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => {
- if (err) console.log(err)
- cpl()
- })
- } else cpl()
-})
-
-adminRoutes.post("/transfer", parser, (req,res) => {
-
- if (typeof req.body.target !== "string" || typeof req.body.owner !== "string") {
- res.status(404)
- res.send()
- return
- }
-
- let targetFile = files.getFilePointer(req.body.target)
- if (!targetFile) {
- res.status(404)
- res.send()
- return
- }
-
- let newOwner = Accounts.getFromUsername(req.body.owner || "")
-
- // clear old owner
-
- if (targetFile.owner) {
- let oldOwner = Accounts.getFromId(targetFile.owner)
- if (oldOwner) {
- Accounts.files.deindex(oldOwner.id, req.body.target)
- }
- }
-
- if (newOwner) {
- Accounts.files.index(newOwner.id, req.body.target)
- }
- targetFile.owner = newOwner ? newOwner.id : undefined;
-
- files.writeFile(req.body.target, targetFile).then(() => {
- res.send()
- }).catch(() => {
- res.status(500)
- res.send()
- }) // wasting a reassignment but whatee
-
-})
-
-adminRoutes.post("/idchange", parser, (req,res) => {
-
- if (typeof req.body.target !== "string" || typeof req.body.new !== "string") {
- res.status(400)
- res.send()
- return
- }
-
- let targetFile = files.getFilePointer(req.body.target)
- if (!targetFile) {
- res.status(404)
- res.send()
- return
- }
-
- if (files.getFilePointer(req.body.new)) {
- res.status(400)
- res.send()
- return
- }
-
- if (targetFile.owner) {
- Accounts.files.deindex(targetFile.owner, req.body.target)
- Accounts.files.index(targetFile.owner, req.body.new)
- }
- delete files.files[req.body.target]
-
- files.writeFile(req.body.new, targetFile).then(() => {
- res.send()
- }).catch(() => {
- files.files[req.body.target] = req.body.new
-
- if (targetFile.owner) {
- Accounts.files.deindex(targetFile.owner, req.body.new)
- Accounts.files.index(targetFile.owner, req.body.target)
- }
-
- res.status(500)
- res.send()
- })
-
-})
\ No newline at end of file
diff --git a/src/server/routes/api/v1/account.ts b/src/server/routes/api/v1/account.ts
index e69de29..242a9f1 100644
--- a/src/server/routes/api/v1/account.ts
+++ b/src/server/routes/api/v1/account.ts
@@ -0,0 +1,13 @@
+import { Router } from "express";
+import Files from "../../../lib/files";
+
+let router = Router()
+
+module.exports = function(files: Files) {
+
+ router.get("/", function(req,res) {
+ res.send("hello world!")
+ })
+
+ return router
+}
\ No newline at end of file
diff --git a/src/server/routes/api/v1/admin.ts b/src/server/routes/api/v1/admin.ts
index e69de29..8c8168d 100644
--- a/src/server/routes/api/v1/admin.ts
+++ b/src/server/routes/api/v1/admin.ts
@@ -0,0 +1,8 @@
+import { Router } from "express";
+import Files from "../../../lib/files";
+
+let router = Router()
+
+module.exports = function(files: Files) {
+ return router
+}
\ No newline at end of file
diff --git a/src/server/routes/api/v1/file.ts b/src/server/routes/api/v1/file.ts
index e69de29..8c8168d 100644
--- a/src/server/routes/api/v1/file.ts
+++ b/src/server/routes/api/v1/file.ts
@@ -0,0 +1,8 @@
+import { Router } from "express";
+import Files from "../../../lib/files";
+
+let router = Router()
+
+module.exports = function(files: Files) {
+ return router
+}
\ No newline at end of file
diff --git a/src/server/routes/api/v1/public.ts b/src/server/routes/api/v1/public.ts
index e69de29..8c8168d 100644
--- a/src/server/routes/api/v1/public.ts
+++ b/src/server/routes/api/v1/public.ts
@@ -0,0 +1,8 @@
+import { Router } from "express";
+import Files from "../../../lib/files";
+
+let router = Router()
+
+module.exports = function(files: Files) {
+ return router
+}
\ No newline at end of file
diff --git a/src/server/routes/authRoutes.ts b/src/server/routes/authRoutes.ts
deleted file mode 100644
index a8de6ff..0000000
--- a/src/server/routes/authRoutes.ts
+++ /dev/null
@@ -1,465 +0,0 @@
-import bodyParser from "body-parser";
-import { Router } from "express";
-import * as Accounts from "../lib/accounts";
-import * as auth from "../lib/auth";
-import { sendMail } from "../lib/mail";
-import { getAccount, noAPIAccess, requiresAccount, requiresPermissions } from "../lib/middleware"
-import { accountRatelimit } from "../lib/ratelimit"
-
-import ServeError from "../lib/errors";
-import Files, { FileVisibility, generateFileId, id_check_regex } from "../lib/files";
-
-import { writeFile } from "fs";
-
-let parser = bodyParser.json({
- type: ["text/plain","application/json"]
-})
-
-export let authRoutes = Router();
-authRoutes.use(getAccount)
-
-let config = require(`${process.cwd()}/config.json`)
-
-let files:Files
-
-export function setFilesObj(newFiles:Files) {
- files = newFiles
-}
-
-authRoutes.post("/login", parser, (req,res) => {
- if (typeof req.body.username != "string" || typeof req.body.password != "string") {
- ServeError(res,400,"please provide a username or password")
- return
- }
-
- if (auth.validate(req.cookies.auth)) return
-
- /*
- check if account exists
- */
-
- let acc = Accounts.getFromUsername(req.body.username)
-
- if (!acc) {
- ServeError(res,401,"username or password incorrect")
- return
- }
-
- if (!Accounts.password.check(acc.id,req.body.password)) {
- ServeError(res,401,"username or password incorrect")
- return
- }
-
- /*
- assign token
- */
-
- res.cookie("auth",auth.create(acc.id,(3*24*60*60*1000)))
- res.status(200)
- res.end()
-})
-
-authRoutes.post("/create", parser, (req,res) => {
- if (!config.accounts.registrationEnabled) {
- ServeError(res,403,"account registration disabled")
- return
- }
-
- if (auth.validate(req.cookies.auth)) return
-
- if (typeof req.body.username != "string" || typeof req.body.password != "string") {
- ServeError(res,400,"please provide a username or password")
- return
- }
-
- /*
- check if account exists
- */
-
- let acc = Accounts.getFromUsername(req.body.username)
-
- if (acc) {
- ServeError(res,400,"account with this username already exists")
- return
- }
-
- if (req.body.username.length < 3 || req.body.username.length > 20) {
- ServeError(res,400,"username must be over or equal to 3 characters or under or equal to 20 characters in length")
- return
- }
-
- if ((req.body.username.match(/[A-Za-z0-9_\-\.]+/) || [])[0] != req.body.username) {
- ServeError(res,400,"username contains invalid characters")
- return
- }
-
- if (req.body.password.length < 8) {
- ServeError(res,400,"password must be 8 characters or longer")
- return
- }
-
- Accounts.create(req.body.username,req.body.password)
- .then((newAcc) => {
- /*
- assign token
- */
-
- res.cookie("auth",auth.create(newAcc,(3*24*60*60*1000)))
- res.status(200)
- res.end()
- })
- .catch(() => {
- ServeError(res,500,"internal server error")
- })
-})
-
-authRoutes.post("/logout", (req,res) => {
- if (!auth.validate(req.cookies.auth)) {
- ServeError(res, 401, "not logged in")
- return
- }
-
- auth.invalidate(req.cookies.auth)
- res.send("logged out")
-})
-
-authRoutes.post("/dfv", requiresAccount, requiresPermissions("manage"), parser, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- if (['public','private','anonymous'].includes(req.body.defaultFileVisibility)) {
- acc.defaultFileVisibility = req.body.defaultFileVisibility
- Accounts.save()
- res.send(`dfv has been set to ${acc.defaultFileVisibility}`)
- } else {
- res.status(400)
- res.send("invalid dfv")
- }
-})
-
-authRoutes.post("/customcss", requiresAccount, requiresPermissions("customize"), parser, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.fileId != "string") req.body.fileId = undefined;
-
- if (
-
- !req.body.fileId
- || (req.body.fileId.match(id_check_regex) == req.body.fileId
- && req.body.fileId.length <= config.maxUploadIdLength)
-
- ) {
- acc.customCSS = req.body.fileId || undefined
- if (!req.body.fileId) delete acc.customCSS
- Accounts.save()
- res.send(`custom css saved`)
- } else {
- res.status(400)
- res.send("invalid fileid")
- }
-})
-
-authRoutes.post("/embedcolor", requiresAccount, requiresPermissions("customize"), parser, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.color != "string") req.body.color = undefined;
-
- if (
-
- !req.body.color
- || (req.body.color.toLowerCase().match(/[a-f0-9]+/) == req.body.color.toLowerCase())
- && req.body.color.length == 6
-
- ) {
- if (!acc.embed) acc.embed = {}
- acc.embed.color = req.body.color || undefined
- if (!req.body.color) delete acc.embed.color
- Accounts.save()
- res.send(`custom embed color saved`)
- } else {
- res.status(400)
- res.send("invalid hex code")
- }
-})
-
-authRoutes.post("/embedsize", requiresAccount, requiresPermissions("customize"), parser, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- if (typeof req.body.largeImage != "boolean") req.body.color = false;
-
- if (!acc.embed) acc.embed = {}
- acc.embed.largeImage = req.body.largeImage
- if (!req.body.largeImage) delete acc.embed.largeImage
- Accounts.save()
- res.send(`custom embed image size saved`)
-})
-
-authRoutes.post("/delete_account", requiresAccount, noAPIAccess, 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) => {
- auth.invalidate(v.token)
- })
-
- let cpl = () => Accounts.deleteAccount(accId).then(_ => res.send("account deleted"))
-
- if (req.body.deleteFiles) {
- let f = acc.files.map(e=>e) // make shallow copy so that iterating over it doesnt Die
- for (let v of f) {
- files.unlink(v,true).catch(err => console.error(err))
- }
-
- writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => {
- if (err) console.log(err)
- cpl()
- })
- } else cpl()
-})
-
-authRoutes.post("/change_username", requiresAccount, noAPIAccess, 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")
- return
- }
-
- let _acc = Accounts.getFromUsername(req.body.username)
-
- if (_acc) {
- ServeError(res,400,"account with this username already exists")
- return
- }
-
- if ((req.body.username.match(/[A-Za-z0-9_\-\.]+/) || [])[0] != req.body.username) {
- ServeError(res,400,"username contains invalid characters")
- return
- }
-
- acc.username = req.body.username
- Accounts.save()
-
- if (acc.email) {
- sendMail(acc.email, `Your login details have been updated`, `Hello there! Your username has been updated to ${req.body.username}. Please update your devices accordingly. Thank you for using monofile.`).then(() => {
- res.send("OK")
- }).catch((err) => {})
- }
-
- res.send("username changed")
-})
-
-// shit way to do this but...
-
-let verificationCodes = new Map()
-
-authRoutes.post("/request_email_change", requiresAccount, noAPIAccess, accountRatelimit({ requests: 4, per: 60*60*1000 }), parser, (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")
- return
- }
-
- let vcode = verificationCodes.get(acc.id)
-
- // delete previous if any
- let e = vcode?.expiry
- if (e) clearTimeout(e)
- verificationCodes.delete(acc?.id||"")
-
- let code = generateFileId(12).toUpperCase()
-
- // set
-
- verificationCodes.set(acc.id, {
- code,
- email: req.body.email,
- expiry: setTimeout( () => verificationCodes.delete(acc?.id||""), 15*60*1000)
- })
-
- // this is a mess but it's fine
-
- sendMail(req.body.email, `Hey there, ${acc.username} - let's connect your email`, `Hello there! You are recieving this message because you decided to link your email, ${req.body.email.split("@")[0]}@${req.body.email.split("@")[1]}, to your account, ${acc.username}. If you would like to continue, please click here, or go to https://${req.header("Host")}/auth/confirm_email/${code}.`).then(() => {
- res.send("OK")
- }).catch((err) => {
- let e = verificationCodes.get(acc?.id||"")?.expiry
- if (e) clearTimeout(e)
- verificationCodes.delete(acc?.id||"")
- res.locals.undoCount();
- ServeError(res, 500, err?.toString())
- })
-})
-
-authRoutes.get("/confirm_email/:code", requiresAccount, noAPIAccess, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
-
- let vcode = verificationCodes.get(acc.id)
-
- if (!vcode) { ServeError(res, 400, "nothing to confirm"); return }
-
- if (typeof req.params.code == "string" && req.params.code.toUpperCase() == vcode.code) {
- acc.email = vcode.email
- Accounts.save();
-
- let e = verificationCodes.get(acc?.id||"")?.expiry
- if (e) clearTimeout(e)
- verificationCodes.delete(acc?.id||"")
-
- res.redirect("/")
- } else {
- ServeError(res, 400, "invalid code")
- }
-})
-
-authRoutes.post("/remove_email", requiresAccount, noAPIAccess, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- if (acc.email) {
- delete acc.email;
- Accounts.save()
- res.send("email detached")
- }
- else ServeError(res, 400, "email not attached")
-})
-
-let pwReset = new Map()
-let prcIdx = new Map()
-
-authRoutes.post("/request_emergency_login", parser, (req,res) => {
- if (auth.validate(req.cookies.auth || "")) return
-
- if (typeof req.body.account != "string" || !req.body.account) {
- ServeError(res,400, "supply a username")
- return
- }
-
- let acc = Accounts.getFromUsername(req.body.account)
- if (!acc || !acc.email) {
- ServeError(res, 400, "this account either does not exist or does not have an email attached; please contact the server's admin for a reset if you would still like to access it")
- return
- }
-
- let pResetCode = pwReset.get(acc.id)
-
- if (pResetCode && pResetCode.requestedAt+(15*60*1000) > Date.now()) {
- ServeError(res, 429, `Please wait a few moments to request another emergency login.`)
- return
- }
-
-
- // delete previous if any
- let e = pResetCode?.expiry
- if (e) clearTimeout(e)
- pwReset.delete(acc?.id||"")
- prcIdx.delete(pResetCode?.code||"")
-
- let code = generateFileId(12).toUpperCase()
-
- // set
-
- pwReset.set(acc.id, {
- code,
- expiry: setTimeout( () => { pwReset.delete(acc?.id||""); prcIdx.delete(pResetCode?.code||"") }, 15*60*1000),
- requestedAt: Date.now()
- })
-
- prcIdx.set(code, acc.id)
-
- // this is a mess but it's fine
-
- sendMail(acc.email, `Emergency login requested for ${acc.username}`, `Hello there! You are recieving this message because you forgot your password to your monofile account, ${acc.username}. To log in, please click here, or go to https://${req.header("Host")}/auth/emergency_login/${code}. If it doesn't appear that you are logged in after visiting this link, please try refreshing. Once you have successfully logged in, you may reset your password.`).then(() => {
- res.send("OK")
- }).catch((err) => {
- let e = pwReset.get(acc?.id||"")?.expiry
- if (e) clearTimeout(e)
- pwReset.delete(acc?.id||"")
- prcIdx.delete(code||"")
- ServeError(res, 500, err?.toString())
- })
-})
-
-authRoutes.get("/emergency_login/:code", (req,res) => {
- if (auth.validate(req.cookies.auth || "")) {
- ServeError(res, 403, "already logged in")
- return
- }
-
- let vcode = prcIdx.get(req.params.code)
-
- if (!vcode) { ServeError(res, 400, "invalid emergency login code"); return }
-
- if (typeof req.params.code == "string" && vcode) {
- res.cookie("auth",auth.create(vcode,(3*24*60*60*1000)))
- res.redirect("/")
-
- let e = pwReset.get(vcode)?.expiry
- if (e) clearTimeout(e)
- pwReset.delete(vcode)
- prcIdx.delete(req.params.code)
- } else {
- ServeError(res, 400, "invalid code")
- }
-})
-
-authRoutes.post("/change_password", requiresAccount, noAPIAccess, 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
- }
-
- let accId = acc.id
-
- Accounts.password.set(accId,req.body.password)
-
- auth.AuthTokens.filter(e => e.account == accId).forEach((v) => {
- auth.invalidate(v.token)
- })
-
- if (acc.email) {
- sendMail(acc.email, `Your login details have been updated`, `Hello there! This email is to notify you of a password change that you have initiated. You have been logged out of your devices. Thank you for using monofile.`).then(() => {
- res.send("OK")
- }).catch((err) => {})
- }
-
- res.send("password changed - logged out all sessions")
-})
-
-authRoutes.post("/logout_sessions", requiresAccount, noAPIAccess, (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- let accId = acc.id
-
- auth.AuthTokens.filter(e => e.account == accId).forEach((v) => {
- auth.invalidate(v.token)
- })
-
- res.send("logged out all sessions")
-})
-
-authRoutes.get("/me", requiresAccount, requiresPermissions("user"), (req,res) => {
- let acc = res.locals.acc as Accounts.Account
-
- let sessionToken = auth.tokenFor(req)
- let accId = acc.id
- res.send({
- ...acc,
- sessionCount: auth.AuthTokens.filter(e => e.type != "App" && e.account == accId && (e.expire > Date.now() || !e.expire)).length,
- sessionExpires: auth.AuthTokens.find(e => e.token == sessionToken)?.expire,
- password: undefined,
- email:
- auth.getType(sessionToken) == "User" || auth.getPermissions(sessionToken)?.includes("email")
- ? acc.email
- : undefined
- })
-})
-
-authRoutes.get("/customCSS", (req,res) => {
- let acc = res.locals.acc
- if (acc?.customCSS) res.redirect(`/file/${acc.customCSS}`)
- else res.send("")
-})
diff --git a/src/server/routes/fileApiRoutes.ts b/src/server/routes/fileApiRoutes.ts
deleted file mode 100644
index f64d141..0000000
--- a/src/server/routes/fileApiRoutes.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import bodyParser from "body-parser";
-import { Router } from "express";
-import * as Accounts from "../lib/accounts";
-import * as auth from "../lib/auth";
-import bytes from "bytes"
-import {writeFile} from "fs";
-
-import ServeError from "../lib/errors";
-import Files from "../lib/files";
-import { getAccount, requiresAccount, requiresPermissions } from "../lib/middleware";
-
-let parser = bodyParser.json({
- type: ["text/plain","application/json"]
-})
-
-export let fileApiRoutes = Router();
-let files:Files
-
-export function setFilesObj(newFiles:Files) {
- files = newFiles
-}
-
-let config = require(`${process.cwd()}/config.json`)
-
-fileApiRoutes.use(getAccount);
-
-fileApiRoutes.get("/list", requiresAccount, requiresPermissions("user"), (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (!acc) return
- let accId = acc.id
-
- res.send(acc.files.map((e) => {
- let fp = files.getFilePointer(e)
- if (!fp) { Accounts.files.deindex(accId, e); return null }
- return {
- ...fp,
- messageids: null,
- owner: null,
- id:e
- }
- }).filter(e=>e))
-
-})
-
-fileApiRoutes.post("/manage", parser, requiresPermissions("manage"), (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (!acc) return
- if (!req.body.target || !(typeof req.body.target == "object") || req.body.target.length < 1) return
-
- let modified = 0
-
- req.body.target.forEach((e:string) => {
- if (!acc.files.includes(e)) return
-
- let fp = files.getFilePointer(e)
-
- if (fp.reserved) {
- return
- }
-
- switch( req.body.action ) {
- case "delete":
- files.unlink(e, true)
- modified++;
- break;
-
- case "changeFileVisibility":
- if (!["public","anonymous","private"].includes(req.body.value)) return;
- files.files[e].visibility = req.body.value;
- modified++;
- break;
-
- case "setTag":
- if (!req.body.value) delete files.files[e].tag
- else {
- if (req.body.value.toString().length > 30) return
- files.files[e].tag = req.body.value.toString().toLowerCase()
- }
- modified++;
- break;
- }
- })
-
- Accounts.save().then(() => {
- writeFile(process.cwd()+"/.data/files.json",JSON.stringify(files.files), (err) => {
- if (err) console.log(err)
- res.contentType("text/plain")
- res.send(`modified ${modified} files`)
- })
- }).catch((err) => console.error(err))
-
-
-})
\ No newline at end of file
diff --git a/src/server/routes/primaryApi.ts b/src/server/routes/primaryApi.ts
deleted file mode 100644
index 33558d8..0000000
--- a/src/server/routes/primaryApi.ts
+++ /dev/null
@@ -1,181 +0,0 @@
-import bodyParser from "body-parser";
-import express, { Router } from "express";
-import * as Accounts from "../lib/accounts";
-import * as auth from "../lib/auth";
-import axios, { AxiosResponse } from "axios"
-import { type Range } from "range-parser";
-import multer, {memoryStorage} from "multer"
-
-import ServeError from "../lib/errors";
-import Files from "../lib/files";
-import { getAccount, requiresPermissions } from "../lib/middleware";
-
-let parser = bodyParser.json({
- type: ["text/plain","application/json"]
-})
-
-export let primaryApi = Router();
-let files:Files
-
-export function setFilesObj(newFiles:Files) {
- files = newFiles
-}
-
-const multerSetup = multer({storage:memoryStorage()})
-
-let config = require(`${process.cwd()}/config.json`)
-
-primaryApi.use(getAccount);
-
-primaryApi.get(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], async (req:express.Request,res:express.Response) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- 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) {
-
- if (file.visibility == "private" && acc?.id != file.owner) {
- ServeError(res,403,"you do not own this file")
- return
- }
-
- let range: Range | undefined
-
- res.setHeader("Content-Type",file.mime)
- if (file.sizeInBytes) {
- res.setHeader("Content-Length",file.sizeInBytes)
-
- if (file.chunkSize) {
- let rng = req.range(file.sizeInBytes)
- if (rng) {
-
- // error handling
- if (typeof rng == "number") {
- res.status(rng == -1 ? 416 : 400).send()
- return
- }
- if (rng.type != "bytes") {
- res.status(400).send();
- return
- }
-
- // set ranges var
- let rngs = Array.from(rng)
- if (rngs.length != 1) { res.status(400).send(); return }
- range = rngs[0]
-
- }
- }
- }
-
- // supports ranges
-
-
- files.readFileStream(req.params.fileId, range).then(async stream => {
-
- if (range) {
- res.status(206)
- res.header("Content-Length", (range.end-range.start + 1).toString())
- res.header("Content-Range", `bytes ${range.start}-${range.end}/${file.sizeInBytes}`)
- }
- stream.pipe(res)
-
- }).catch((err) => {
- ServeError(res,err.status,err.message)
- })
-
- } else {
- ServeError(res, 404, "file not found")
- }
-
-})
-
-primaryApi.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)
- res.send()
- } else {
- res.setHeader("Content-Type",file.mime)
- if (file.sizeInBytes) {
- res.setHeader("Content-Length",file.sizeInBytes)
- }
- if (file.chunkSize) {
- res.setHeader("Accept-Ranges", "bytes")
- }
- }
-})
-
-// upload handlers
-
-primaryApi.post("/upload", requiresPermissions("upload"), multerSetup.single('file'), async (req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- if (req.file) {
- try {
- let prm = req.header("monofile-params")
- let params:{[key:string]:any} = {}
- if (prm) {
- params = JSON.parse(prm)
- }
-
- files.uploadFile({
- owner: acc?.id,
-
- uploadId:params.uploadId,
- name:req.file.originalname,
- mime:req.file.mimetype
- },req.file.buffer)
- .then((uID) => res.send(uID))
- .catch((stat) => {
- res.status(stat.status);
- res.send(`[err] ${stat.message}`)
- })
- } catch {
- res.status(400)
- res.send("[err] bad request")
- }
- } else {
- res.status(400)
- res.send("[err] bad request")
- }
-})
-
-primaryApi.post("/clone", requiresPermissions("upload"), bodyParser.json({type: ["text/plain","application/json"]}) ,(req,res) => {
-
- let acc = res.locals.acc as Accounts.Account
-
- try {
- axios.get(req.body.url,{responseType:"arraybuffer"}).then((data:AxiosResponse) => {
-
- files.uploadFile({
- owner: acc?.id,
-
- name:req.body.url.split("/")[req.body.url.split("/").length-1] || "generic",
- mime:data.headers["content-type"],
- uploadId:req.body.uploadId
- },Buffer.from(data.data))
- .then((uID) => res.send(uID))
- .catch((stat) => {
- res.status(stat.status);
- res.send(`[err] ${stat.message}`)
- })
-
- }).catch((err) => {
- console.log(err)
- res.status(400)
- res.send(`[err] failed to fetch data`)
- })
- } catch {
- res.status(500)
- res.send("[err] an error occured")
- }
-})
\ No newline at end of file