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