From b3efd8ca29adac1fdbede1c05ae57aad58f553c4 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:17:38 -0700 Subject: [PATCH 1/9] token-permissions: implement into tokens --- src/server/lib/auth.ts | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index 169a6ef..133ec52 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -3,17 +3,41 @@ import { readFile, writeFile } from "fs/promises" export let AuthTokens: AuthToken[] = [] export let AuthTokenTO:{[key:string]:NodeJS.Timeout} = {} +export const ValidTokenPermissions = [ + "user", // permissions to /auth/me, with email docked + "email", // adds email back to /auth/me + "upload", // allows an app to upload under an account + "manage", // allows an app to manage an account's files + "admin" // only available for accounts with admin + // gives an app access to all admin tools +] as const + +export type TokenType = "User" | "App" +export type TokenPermission = typeof ValidTokenPermissions[number] + export interface AuthToken { account: string, token: string, - expire: number + expire: number, + + type?: TokenType, // if !type, assume User + tokenPermissions?: TokenPermission[] // default to user if type is App, + // give full permissions if type is User } -export function create(id:string,expire:number=(24*60*60*1000)) { +export function create( + id:string, + expire:number=(24*60*60*1000), + type:TokenType="User", + tokenPermissions?:TokenPermission[] +) { let token = { account:id, token:crypto.randomBytes(36).toString('hex'), - expire:Date.now()+expire + expire:Date.now()+expire, + + type, + tokenPermissions } AuthTokens.push(token) From a04cc9a376b380bf807aa214c31650ddbb05bb9f Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:22:18 -0700 Subject: [PATCH 2/9] token-permissions: update middleware --- src/server/lib/auth.ts | 10 ++++++- src/server/lib/middleware.ts | 58 ++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index 133ec52..4495f2f 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -37,7 +37,7 @@ export function create( expire:Date.now()+expire, type, - tokenPermissions + tokenPermissions: type == "App" ? tokenPermissions || ["user"] : undefined } AuthTokens.push(token) @@ -52,6 +52,14 @@ export function validate(token:string) { return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.account } +export function getType(token:string): TokenType | undefined { + return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.type +} + +export function getPermissions(token:string): TokenPermission[] | undefined { + return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.tokenPermissions +} + export function tokenTimer(token:AuthToken) { if (Date.now() >= token.expire) { invalidate(token.token) diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts index 2f0ed0c..2f487b2 100644 --- a/src/server/lib/middleware.ts +++ b/src/server/lib/middleware.ts @@ -1,17 +1,22 @@ import * as Accounts from "./accounts"; import express, { type RequestHandler } from "express" import ServeError from "../lib/errors"; +import * as auth from "./auth"; -export let getAccount: RequestHandler = function(req, res, next) { - res.locals.acc = Accounts.getFromToken(req.cookies.auth || ( +function tokenFor(req: express.Request) { + return req.cookies.auth || ( req.header("authorization")?.startsWith("Bearer ") ? req.header("authorization")?.split(" ")[1] : undefined - )) + ) +} + +export const getAccount: RequestHandler = function(req, res, next) { + res.locals.acc = Accounts.getFromToken(tokenFor(req)) next() } -export let requiresAccount: RequestHandler = function(_req, res, next) { +export const requiresAccount: RequestHandler = function(_req, res, next) { if (!res.locals.acc) { ServeError(res, 401, "not logged in") return @@ -19,10 +24,53 @@ export let requiresAccount: RequestHandler = function(_req, res, next) { next() } -export let requiresAdmin: RequestHandler = function(_req, res, next) { +export const requiresAdmin: RequestHandler = function(_req, res, next) { if (!res.locals.acc.admin) { ServeError(res, 403, "you are not an administrator") return } next() +} + +export namespace apiBlockers { + + /** + * @description Blocks requests based on the permissions which a token has. Does not apply to routes being accessed with a token of type `User` + * @param tokenPermissions Permissions which your route requires. + * @returns Express middleware + */ + + export const requiresPermissions = function(...tokenPermissions: auth.TokenPermission[]): RequestHandler { + return function(req, res, next) { + let token = tokenFor(req) + let type = auth.getType(token) + + if (type == "App") { + let permissions = auth.getPermissions(token) + + if (!permissions) ServeError(res, 403, "insufficient permissions") + else { + + for (let v in tokenPermissions) + if (!permissions.includes(v as auth.TokenPermission)) { + ServeError(res,403,"insufficient permissions") + return + } + + next() + + } + } else next() + } + } + + /** + * @description Blocks requests based on whether or not the token being used to access the route is of type `User`. + */ + + export const noAPIAccess: RequestHandler = function(req, res, next) { + if (auth.getType(tokenFor(req)) == "App") ServeError(res, 403, "apps are not allowed to access this endpoint") + else next() + } + } \ No newline at end of file From fad320d7fbd76b1fd5b1b680498ca6cc3b0b6690 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:27:48 -0700 Subject: [PATCH 3/9] token-permissions: update middleware further --- src/server/lib/middleware.ts | 56 +++++++++++++++++------------------- 1 file changed, 26 insertions(+), 30 deletions(-) diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts index 2f487b2..4f365ca 100644 --- a/src/server/lib/middleware.ts +++ b/src/server/lib/middleware.ts @@ -32,45 +32,41 @@ export const requiresAdmin: RequestHandler = function(_req, res, next) { next() } -export namespace apiBlockers { - - /** +/** * @description Blocks requests based on the permissions which a token has. Does not apply to routes being accessed with a token of type `User` * @param tokenPermissions Permissions which your route requires. * @returns Express middleware */ - export const requiresPermissions = function(...tokenPermissions: auth.TokenPermission[]): RequestHandler { - return function(req, res, next) { - let token = tokenFor(req) - let type = auth.getType(token) +export const requiresPermissions = function(...tokenPermissions: auth.TokenPermission[]): RequestHandler { + return function(req, res, next) { + let token = tokenFor(req) + let type = auth.getType(token) + + if (type == "App") { + let permissions = auth.getPermissions(token) - if (type == "App") { - let permissions = auth.getPermissions(token) + if (!permissions) ServeError(res, 403, "insufficient permissions") + else { + + for (let v in tokenPermissions) + if (!permissions.includes(v as auth.TokenPermission)) { + ServeError(res,403,"insufficient permissions") + return + } - if (!permissions) ServeError(res, 403, "insufficient permissions") - else { + next() - for (let v in tokenPermissions) - if (!permissions.includes(v as auth.TokenPermission)) { - ServeError(res,403,"insufficient permissions") - return - } - - next() - - } - } else next() - } + } + } else next() } +} - /** - * @description Blocks requests based on whether or not the token being used to access the route is of type `User`. - */ - - export const noAPIAccess: RequestHandler = function(req, res, next) { - if (auth.getType(tokenFor(req)) == "App") ServeError(res, 403, "apps are not allowed to access this endpoint") - else next() - } +/** + * @description Blocks requests based on whether or not the token being used to access the route is of type `User`. + */ +export const noAPIAccess: RequestHandler = function(req, res, next) { + if (auth.getType(tokenFor(req)) == "App") ServeError(res, 403, "apps are not allowed to access this endpoint") + else next() } \ No newline at end of file From 2006fa1cca16838bae907d301fd5028d94f7dfa4 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:14:00 -0700 Subject: [PATCH 4/9] token-permissions: update authRoutes --- src/server/lib/auth.ts | 23 ++++++++++++++----- src/server/lib/middleware.ts | 14 +++--------- src/server/routes/authRoutes.ts | 39 +++++++++++++++++++-------------- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index 4495f2f..899c215 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -1,15 +1,18 @@ import crypto from "crypto" +import express from "express" import { readFile, writeFile } from "fs/promises" export let AuthTokens: AuthToken[] = [] export let AuthTokenTO:{[key:string]:NodeJS.Timeout} = {} export const ValidTokenPermissions = [ - "user", // permissions to /auth/me, with email docked - "email", // adds email back to /auth/me - "upload", // allows an app to upload under an account - "manage", // allows an app to manage an account's files - "admin" // only available for accounts with admin - // gives an app access to all admin tools + "user", // permissions to /auth/me, with email docked + "email", // adds email back to /auth/me + "private", // allows app to read private files + "upload", // allows an app to upload under an account + "manage", // allows an app to manage an account's files + "customize", // allows an app to change customization settings + "admin" // only available for accounts with admin + // gives an app access to all admin tools ] as const export type TokenType = "User" | "App" @@ -48,6 +51,14 @@ export function create( return token.token } +export function tokenFor(req: express.Request) { + return req.cookies.auth || ( + req.header("authorization")?.startsWith("Bearer ") + ? req.header("authorization")?.split(" ")[1] + : undefined + ) +} + export function validate(token:string) { return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.account } diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts index 4f365ca..bcb2bc6 100644 --- a/src/server/lib/middleware.ts +++ b/src/server/lib/middleware.ts @@ -3,16 +3,8 @@ import express, { type RequestHandler } from "express" import ServeError from "../lib/errors"; import * as auth from "./auth"; -function tokenFor(req: express.Request) { - return req.cookies.auth || ( - req.header("authorization")?.startsWith("Bearer ") - ? req.header("authorization")?.split(" ")[1] - : undefined - ) -} - export const getAccount: RequestHandler = function(req, res, next) { - res.locals.acc = Accounts.getFromToken(tokenFor(req)) + res.locals.acc = Accounts.getFromToken(auth.tokenFor(req)) next() } @@ -40,7 +32,7 @@ export const requiresAdmin: RequestHandler = function(_req, res, next) { export const requiresPermissions = function(...tokenPermissions: auth.TokenPermission[]): RequestHandler { return function(req, res, next) { - let token = tokenFor(req) + let token = auth.tokenFor(req) let type = auth.getType(token) if (type == "App") { @@ -67,6 +59,6 @@ export const requiresPermissions = function(...tokenPermissions: auth.TokenPermi */ export const noAPIAccess: RequestHandler = function(req, res, next) { - if (auth.getType(tokenFor(req)) == "App") ServeError(res, 403, "apps are not allowed to access this endpoint") + if (auth.getType(auth.tokenFor(req)) == "App") ServeError(res, 403, "apps are not allowed to access this endpoint") else next() } \ No newline at end of file diff --git a/src/server/routes/authRoutes.ts b/src/server/routes/authRoutes.ts index 72b5863..0c5bb19 100644 --- a/src/server/routes/authRoutes.ts +++ b/src/server/routes/authRoutes.ts @@ -3,7 +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 { getAccount, noAPIAccess, requiresAccount, requiresPermissions } from "../lib/middleware" import { accountRatelimit } from "../lib/ratelimit" import ServeError from "../lib/errors"; @@ -123,7 +123,7 @@ authRoutes.post("/logout", (req,res) => { res.send("logged out") }) -authRoutes.post("/dfv", requiresAccount, parser, (req,res) => { +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)) { @@ -136,7 +136,7 @@ authRoutes.post("/dfv", requiresAccount, parser, (req,res) => { } }) -authRoutes.post("/customcss", requiresAccount, parser, (req,res) => { +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; @@ -158,7 +158,7 @@ authRoutes.post("/customcss", requiresAccount, parser, (req,res) => { } }) -authRoutes.post("/embedcolor", requiresAccount, parser, (req,res) => { +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; @@ -181,7 +181,7 @@ authRoutes.post("/embedcolor", requiresAccount, parser, (req,res) => { } }) -authRoutes.post("/embedsize", requiresAccount, parser, (req,res) => { +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; @@ -193,7 +193,7 @@ authRoutes.post("/embedsize", requiresAccount, parser, (req,res) => { res.send(`custom embed image size saved`) }) -authRoutes.post("/delete_account", requiresAccount, parser, async (req,res) => { +authRoutes.post("/delete_account", requiresAccount, noAPIAccess, parser, async (req,res) => { let acc = res.locals.acc as Accounts.Account let accId = acc.id @@ -217,7 +217,7 @@ authRoutes.post("/delete_account", requiresAccount, parser, async (req,res) => { } else cpl() }) -authRoutes.post("/change_username", requiresAccount, parser, (req,res) => { +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) { @@ -253,7 +253,7 @@ authRoutes.post("/change_username", requiresAccount, parser, (req,res) => { let verificationCodes = new Map() -authRoutes.post("/request_email_change", requiresAccount, accountRatelimit({ requests: 4, per: 60*60*1000 }), parser, (req,res) => { +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 @@ -292,7 +292,7 @@ authRoutes.post("/request_email_change", requiresAccount, accountRatelimit({ req }) }) -authRoutes.get("/confirm_email/:code", requiresAccount, (req,res) => { +authRoutes.get("/confirm_email/:code", requiresAccount, noAPIAccess, (req,res) => { let acc = res.locals.acc as Accounts.Account @@ -314,7 +314,7 @@ authRoutes.get("/confirm_email/:code", requiresAccount, (req,res) => { } }) -authRoutes.post("/remove_email", requiresAccount, (req,res) => { +authRoutes.post("/remove_email", requiresAccount, noAPIAccess, (req,res) => { let acc = res.locals.acc as Accounts.Account if (acc.email) { @@ -404,7 +404,7 @@ authRoutes.get("/emergency_login/:code", (req,res) => { } }) -authRoutes.post("/change_password", requiresAccount, parser, (req,res) => { +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) { @@ -429,7 +429,7 @@ authRoutes.post("/change_password", requiresAccount, parser, (req,res) => { res.send("password changed - logged out all sessions") }) -authRoutes.post("/logout_sessions", requiresAccount, (req,res) => { +authRoutes.post("/logout_sessions", requiresAccount, noAPIAccess, (req,res) => { let acc = res.locals.acc as Accounts.Account let accId = acc.id @@ -441,15 +441,20 @@ authRoutes.post("/logout_sessions", requiresAccount, (req,res) => { res.send("logged out all sessions") }) -authRoutes.get("/me", requiresAccount, (req,res) => { +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.account == accId && e.expire > Date.now()).length, - sessionExpires: auth.AuthTokens.find(e => e.token == req.cookies.auth)?.expire, - password: undefined + sessionCount: auth.AuthTokens.filter(e => e.type != "App" && e.account == accId && e.expire > Date.now()).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 }) }) From 6742bf724f25c4a0a499cf44f6be4c8e07d2fdd8 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:18:29 -0700 Subject: [PATCH 5/9] token-permissions: update fileApiRoutes --- src/server/routes/fileApiRoutes.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/routes/fileApiRoutes.ts b/src/server/routes/fileApiRoutes.ts index 8953a84..f64d141 100644 --- a/src/server/routes/fileApiRoutes.ts +++ b/src/server/routes/fileApiRoutes.ts @@ -7,7 +7,7 @@ import {writeFile} from "fs"; import ServeError from "../lib/errors"; import Files from "../lib/files"; -import { getAccount, requiresAccount } from "../lib/middleware"; +import { getAccount, requiresAccount, requiresPermissions } from "../lib/middleware"; let parser = bodyParser.json({ type: ["text/plain","application/json"] @@ -24,7 +24,7 @@ let config = require(`${process.cwd()}/config.json`) fileApiRoutes.use(getAccount); -fileApiRoutes.get("/list", requiresAccount, (req,res) => { +fileApiRoutes.get("/list", requiresAccount, requiresPermissions("user"), (req,res) => { let acc = res.locals.acc as Accounts.Account @@ -44,7 +44,7 @@ fileApiRoutes.get("/list", requiresAccount, (req,res) => { }) -fileApiRoutes.post("/manage", parser, (req,res) => { +fileApiRoutes.post("/manage", parser, requiresPermissions("manage"), (req,res) => { let acc = res.locals.acc as Accounts.Account From af9c3233d8847ef7a87fa6d08bd0c4561b5941f0 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:20:11 -0700 Subject: [PATCH 6/9] token-permissions: update primaryApi --- src/server/routes/primaryApi.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/server/routes/primaryApi.ts b/src/server/routes/primaryApi.ts index 0ff3ed7..33558d8 100644 --- a/src/server/routes/primaryApi.ts +++ b/src/server/routes/primaryApi.ts @@ -8,7 +8,7 @@ import multer, {memoryStorage} from "multer" import ServeError from "../lib/errors"; import Files from "../lib/files"; -import { getAccount } from "../lib/middleware"; +import { getAccount, requiresPermissions } from "../lib/middleware"; let parser = bodyParser.json({ type: ["text/plain","application/json"] @@ -115,7 +115,7 @@ primaryApi.head(["/file/:fileId", "/cpt/:fileId/*", "/:fileId"], (req: express.R // upload handlers -primaryApi.post("/upload",multerSetup.single('file'),async (req,res) => { +primaryApi.post("/upload", requiresPermissions("upload"), multerSetup.single('file'), async (req,res) => { let acc = res.locals.acc as Accounts.Account @@ -149,7 +149,7 @@ primaryApi.post("/upload",multerSetup.single('file'),async (req,res) => { } }) -primaryApi.post("/clone", bodyParser.json({type: ["text/plain","application/json"]}) ,(req,res) => { +primaryApi.post("/clone", requiresPermissions("upload"), bodyParser.json({type: ["text/plain","application/json"]}) ,(req,res) => { let acc = res.locals.acc as Accounts.Account From 8bec8a4360937c96fcfdb1d65c8874c8bcd1f99a Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:20:32 -0700 Subject: [PATCH 7/9] token-permissions: update adminRoutes --- src/server/routes/adminRoutes.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/routes/adminRoutes.ts b/src/server/routes/adminRoutes.ts index cf554a4..510eec2 100644 --- a/src/server/routes/adminRoutes.ts +++ b/src/server/routes/adminRoutes.ts @@ -5,7 +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 { getAccount, requiresAccount, requiresAdmin, requiresPermissions } from "../lib/middleware" import ServeError from "../lib/errors"; import Files from "../lib/files"; @@ -19,6 +19,7 @@ adminRoutes .use(getAccount) .use(requiresAccount) .use(requiresAdmin) + .use(requiresPermissions("admin")) let files:Files export function setFilesObj(newFiles:Files) { From 5e15b20c106fa6a6469e680e837add32021de2a9 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 21:01:53 -0700 Subject: [PATCH 8/9] token-permissions: bugfix --- src/server/lib/auth.ts | 10 +++++++--- src/server/lib/middleware.ts | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index 899c215..365c82b 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -59,16 +59,20 @@ export function tokenFor(req: express.Request) { ) } +function getToken(token:string) { + return AuthTokens.find(e => e.token == token && Date.now() < e.expire) +} + export function validate(token:string) { - return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.account + return getToken(token)?.account } export function getType(token:string): TokenType | undefined { - return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.type + return getToken(token)?.type } export function getPermissions(token:string): TokenPermission[] | undefined { - return AuthTokens.find(e => e.token == token && Date.now() < e.expire)?.tokenPermissions + return getToken(token)?.tokenPermissions } export function tokenTimer(token:AuthToken) { diff --git a/src/server/lib/middleware.ts b/src/server/lib/middleware.ts index bcb2bc6..9a1a542 100644 --- a/src/server/lib/middleware.ts +++ b/src/server/lib/middleware.ts @@ -41,12 +41,12 @@ export const requiresPermissions = function(...tokenPermissions: auth.TokenPermi if (!permissions) ServeError(res, 403, "insufficient permissions") else { - for (let v in tokenPermissions) + for (let v of tokenPermissions) { if (!permissions.includes(v as auth.TokenPermission)) { ServeError(res,403,"insufficient permissions") return } - + } next() } From 0071c17fe5b17e7d41c2b47c729e5e5feaa48222 Mon Sep 17 00:00:00 2001 From: stringsplit <77242831+nbitzz@users.noreply.github.com> Date: Mon, 2 Oct 2023 22:00:21 -0700 Subject: [PATCH 9/9] tokens: ability to set no expiration --- src/server/lib/auth.ts | 5 +++-- src/server/routes/authRoutes.ts | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/server/lib/auth.ts b/src/server/lib/auth.ts index 365c82b..75a4fd8 100644 --- a/src/server/lib/auth.ts +++ b/src/server/lib/auth.ts @@ -37,7 +37,7 @@ export function create( let token = { account:id, token:crypto.randomBytes(36).toString('hex'), - expire:Date.now()+expire, + expire: expire ? Date.now()+expire : 0, type, tokenPermissions: type == "App" ? tokenPermissions || ["user"] : undefined @@ -60,7 +60,7 @@ export function tokenFor(req: express.Request) { } function getToken(token:string) { - return AuthTokens.find(e => e.token == token && Date.now() < e.expire) + return AuthTokens.find(e => e.token == token && (e.expire == 0 || Date.now() < e.expire)) } export function validate(token:string) { @@ -76,6 +76,7 @@ export function getPermissions(token:string): TokenPermission[] | undefined { } export function tokenTimer(token:AuthToken) { + if (!token.expire) return // justincase if (Date.now() >= token.expire) { invalidate(token.token) return diff --git a/src/server/routes/authRoutes.ts b/src/server/routes/authRoutes.ts index 0c5bb19..a8de6ff 100644 --- a/src/server/routes/authRoutes.ts +++ b/src/server/routes/authRoutes.ts @@ -448,7 +448,7 @@ authRoutes.get("/me", requiresAccount, requiresPermissions("user"), (req,res) => let accId = acc.id res.send({ ...acc, - sessionCount: auth.AuthTokens.filter(e => e.type != "App" && e.account == accId && e.expire > Date.now()).length, + 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: