This commit is contained in:
split / May 2023-08-04 04:05:52 +00:00
parent 42062eaf86
commit 7f694f1a4a
3 changed files with 65 additions and 10 deletions

View file

@ -0,0 +1,45 @@
import { RequestHandler } from "express"
import { type Account } from "./accounts"
import ServeError from "./errors"
interface ratelimitSettings {
requests: number
per: number
}
export function accountRatelimit( settings: ratelimitSettings ): RequestHandler {
let activeLimits: {
[ key: string ]: {
requests: number,
expirationHold: NodeJS.Timeout
}
} = {}
return (req, res, next) => {
if (res.locals.acc) {
let accId = res.locals.acc.id
let aL = activeLimits[accId]
if (!aL) {
activeLimits[accId] = {
requests: 0,
expirationHold: setTimeout(() => delete activeLimits[accId], settings.per)
}
aL = activeLimits[accId]
}
if (aL.requests < settings.requests) {
res.locals.undoCount = () => {
if (activeLimits[accId]) {
activeLimits[accId].requests--
}
}
next()
} else {
ServeError(res, 429, "too many requests")
}
}
}
}

View file

@ -48,6 +48,13 @@ adminRoutes.post("/reset", parser, (req,res) => {
auth.AuthTokens.filter(e => e.account == targetAccount?.id).forEach((v) => { auth.AuthTokens.filter(e => e.account == targetAccount?.id).forEach((v) => {
auth.invalidate(v.token) auth.invalidate(v.token)
}) })
sendMail(req.body.email, `Your login details have been updated`, `<b>Hello there!</b> This email is to notify you of a password change that an administrator, <span username>${acc.username}</span>, has initiated. You have been logged out of your devices. Thank you for using monofile.`).then(() => {
res.send("OK")
}).catch((err) => {})
res.send() res.send()
}) })

View file

@ -4,6 +4,7 @@ import * as Accounts from "../lib/accounts";
import * as auth from "../lib/auth"; import * as auth from "../lib/auth";
import { sendMail } from "../lib/mail"; import { sendMail } from "../lib/mail";
import { getAccount, requiresAccount } from "../lib/middleware" import { getAccount, requiresAccount } from "../lib/middleware"
import { accountRatelimit } from "../lib/ratelimit"
import ServeError from "../lib/errors"; import ServeError from "../lib/errors";
import Files, { FileVisibility, generateFileId, id_check_regex } from "../lib/files"; import Files, { FileVisibility, generateFileId, id_check_regex } from "../lib/files";
@ -239,14 +240,18 @@ authRoutes.post("/change_username", requiresAccount, parser, (req,res) => {
acc.username = req.body.username acc.username = req.body.username
Accounts.save() Accounts.save()
sendMail(req.body.email, `Your login details have been updated`, `<b>Hello there!</b> Your username has been updated to <span username>${req.body.username}</span>. Please update your devices accordingly. Thank you for using monofile.`).then(() => {
res.send("OK")
}).catch((err) => {})
res.send("username changed") res.send("username changed")
}) })
// shit way to do this but... // shit way to do this but...
let verificationCodes = new Map<string, {code: string, email: string, expiry: NodeJS.Timeout, requestedAt:number}>() let verificationCodes = new Map<string, {code: string, email: string, expiry: NodeJS.Timeout}>()
authRoutes.post("/request_email_change", requiresAccount, parser, (req,res) => { authRoutes.post("/request_email_change", requiresAccount, accountRatelimit({ requests: 4, per: 60*60*1000 }), parser, (req,res) => {
let acc = res.locals.acc as Accounts.Account let acc = res.locals.acc as Accounts.Account
@ -257,12 +262,6 @@ authRoutes.post("/request_email_change", requiresAccount, parser, (req,res) => {
let vcode = verificationCodes.get(acc.id) let vcode = verificationCodes.get(acc.id)
if (vcode && vcode.requestedAt+(15*60*1000) > Date.now()) {
ServeError(res, 429, `Please wait a few moments to request another email change.`)
return
}
// delete previous if any // delete previous if any
let e = vcode?.expiry let e = vcode?.expiry
if (e) clearTimeout(e) if (e) clearTimeout(e)
@ -275,8 +274,7 @@ authRoutes.post("/request_email_change", requiresAccount, parser, (req,res) => {
verificationCodes.set(acc.id, { verificationCodes.set(acc.id, {
code, code,
email: req.body.email, email: req.body.email,
expiry: setTimeout( () => verificationCodes.delete(acc?.id||""), 15*60*1000), expiry: setTimeout( () => verificationCodes.delete(acc?.id||""), 15*60*1000)
requestedAt: Date.now()
}) })
// this is a mess but it's fine // this is a mess but it's fine
@ -287,6 +285,7 @@ authRoutes.post("/request_email_change", requiresAccount, parser, (req,res) => {
let e = verificationCodes.get(acc?.id||"")?.expiry let e = verificationCodes.get(acc?.id||"")?.expiry
if (e) clearTimeout(e) if (e) clearTimeout(e)
verificationCodes.delete(acc?.id||"") verificationCodes.delete(acc?.id||"")
res.locals.undoCount();
ServeError(res, 500, err?.toString()) ServeError(res, 500, err?.toString())
}) })
}) })
@ -408,6 +407,10 @@ authRoutes.post("/change_password", requiresAccount, parser, (req,res) => {
auth.invalidate(v.token) auth.invalidate(v.token)
}) })
sendMail(req.body.email, `Your login details have been updated`, `<b>Hello there!</b> 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") res.send("password changed - logged out all sessions")
}) })