feat: Added brute force prevention. Closes #3

This commit is contained in:
2025-05-16 00:39:55 +02:00
parent 9efeba0010
commit b708fe8c18
3 changed files with 101 additions and 6 deletions

53
src/helpers/security.ts Normal file
View File

@@ -0,0 +1,53 @@
import { Job, scheduleJob } from "node-schedule";
import usettings from "./usettings";
import { Types } from "mongoose";
interface IAccTimeout {
firstAttempt: Date;
expire: Job;
attempts: number;
}
class SecurityHelper {
private timeouts = new Map<string, IAccTimeout>();
private onTimeout = new Map<string, Job>(); // key: user id, value: unlock date
constructor () { }
addAttempt (userId: Types.ObjectId) {
var uid = userId.toString()
if (this.timeouts.has(uid)) {
var t = this.timeouts.get(uid)
t.attempts += 1
if (t.attempts > usettings.settings.security.loginTimeout.attempts) {
this.onTimeout.set(uid, scheduleJob(new Date(Date.now() + usettings.settings.security.loginTimeout.lockout * 1000), () => {
this.onTimeout.get(uid).cancel()
this.onTimeout.delete(uid)
}))
} else {
this.timeouts.set(uid, t)
}
} else {
this.timeouts.set(uid, {
attempts: 1,
firstAttempt: new Date(),
expire: scheduleJob(new Date(Date.now() + usettings.settings.security.loginTimeout.time * 1000), () => {
this.timeouts.get(uid).expire.cancel()
this.timeouts.delete(uid)
})
})
}
}
check(userId: Types.ObjectId) {
var timeout = this.onTimeout.get(userId.toString())
if (timeout) {
// @ts-ignore
return timeout.nextInvocation().toDate().valueOf() - Date.now().valueOf()
} else {
return false
}
}
}
export default new SecurityHelper()