8 changed files with 146 additions and 59 deletions
@ -0,0 +1,71 @@ |
|||||
|
|
||||
|
export class CacheTable{ |
||||
|
|
||||
|
constructor(threshold){ |
||||
|
this.entries = {}; |
||||
|
this.count = 0; |
||||
|
this.threshold = threshold || 1024; |
||||
|
} |
||||
|
set(key, val){ |
||||
|
if(this.entries[key] === undefined){ |
||||
|
if(this.count < this.threshold){ |
||||
|
this.count++; |
||||
|
}else{ |
||||
|
for(var otherKey in this.entries){ |
||||
|
delete this.entries[otherKey]; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
this.entries[key] = val; |
||||
|
return val; |
||||
|
} |
||||
|
remove(key){ |
||||
|
if(this.entries[key] !== undefined){ |
||||
|
delete this.entries[key]; |
||||
|
this.count--; |
||||
|
} |
||||
|
} |
||||
|
get(key){ return this.entries[key]; } |
||||
|
allEntries(){ return this.entries; } |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export class SpamCache extends CacheTable{ |
||||
|
|
||||
|
constructor(){ |
||||
|
super(1024); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param string key |
||||
|
* @param {[[maxHits: number, durationMs: number]]} constraints |
||||
|
* @returns |
||||
|
*/ |
||||
|
check(key, constraints){ |
||||
|
const now = Date.now(); |
||||
|
let record = this.get(key); |
||||
|
if(record){ |
||||
|
let dingDong = false; |
||||
|
record.forEach(([count, countFrom], index) => { |
||||
|
const [max, duration] = constraints[index]; |
||||
|
if((now - countFrom) > duration){ |
||||
|
//expired
|
||||
|
record[index] = [1, now]; |
||||
|
}else{ |
||||
|
if(count >= max){ |
||||
|
//max attempts within timespan
|
||||
|
dingDong = true; |
||||
|
}else{ |
||||
|
record[index][0]++; |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
return dingDong; |
||||
|
}else{ |
||||
|
record = constraints.map(() => ([1, now])); |
||||
|
this.set(key, record); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
import { CacheTable, SpamCache } from "./cache.js"; |
||||
|
import { requestIp } from "./utils.js"; |
||||
|
|
||||
|
export class UserSession{ |
||||
|
|
||||
|
constructor(user, request){ |
||||
|
this.user = user; |
||||
|
this.createdAt = Date.now(); |
||||
|
this.ip = requestIp(request); |
||||
|
this.spam = new SpamCache(); |
||||
|
userCache.set(user.token, this); |
||||
|
} |
||||
|
kill(){ |
||||
|
this.dead = true; |
||||
|
userCache.remove(this.user.token); |
||||
|
} |
||||
|
|
||||
|
static find(token){ |
||||
|
return userCache.get(token); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const userCache = new CacheTable(8192); |
||||
@ -1,34 +0,0 @@ |
|||||
|
|
||||
export class CacheTable{ |
|
||||
|
|
||||
constructor(threshold){ |
|
||||
this.entries = {}; |
|
||||
this.count = 0; |
|
||||
this.threshold = threshold || 1024; |
|
||||
} |
|
||||
set(key, val){ |
|
||||
if(this.entries[key] === undefined){ |
|
||||
if(this.count < this.threshold){ |
|
||||
this.count++; |
|
||||
}else{ |
|
||||
for(var otherKey in this.entries){ |
|
||||
delete this.entries[otherKey]; |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
this.entries[key] = val; |
|
||||
} |
|
||||
remove(key){ |
|
||||
if(this.entries[key] !== undefined){ |
|
||||
delete this.entries[key]; |
|
||||
this.count--; |
|
||||
} |
|
||||
} |
|
||||
get(key){ return this.entries[key]; } |
|
||||
allEntries(){ return this.entries; } |
|
||||
} |
|
||||
|
|
||||
export class SpamTable{ |
|
||||
} |
|
||||
|
|
||||
Loading…
Reference in new issue