You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
72 lines
1.9 KiB
CoffeeScript
72 lines
1.9 KiB
CoffeeScript
# NOTE: This module does not currently ensure correct writes. Callbacks are called immediately (but asynchronously).
|
|
|
|
AbstractClientStore = require "express-brute/lib/AbstractClientStore"
|
|
|
|
module.exports = class PersistBruteStore extends AbstractClientStore
|
|
constructor: (options) ->
|
|
@persist = options.persist
|
|
@prefix = options.prefix ? "brute"
|
|
|
|
@_timers = {}
|
|
@_keyMatcher = new RegExp("^#{@prefix}:")
|
|
|
|
@persist.keys()
|
|
.filter (key) => key.match(@_keyMatcher)
|
|
.forEach (key) =>
|
|
@_createExpiryTimer key, @persist.getItem(key).expiry
|
|
|
|
_createExpiryTimer: (key, expiry) ->
|
|
@_removeExpiryTimer(key)
|
|
|
|
ttl = expiry - Date.now()
|
|
|
|
if ttl < 0
|
|
@_createRemover(key)()
|
|
else
|
|
setTimeout @_createRemover(key), ttl
|
|
|
|
_removeExpiryTimer: (key) ->
|
|
if @_timers[key]?
|
|
clearTimeout @_timers[key]
|
|
delete @_timers[key]
|
|
|
|
_createRemover: (key) ->
|
|
return =>
|
|
@_removeExpiryTimer(key)
|
|
|
|
prefixedKey = "#{@prefix}:#{key}"
|
|
|
|
# TODO: Error handling?
|
|
@persist.removeItem prefixedKey
|
|
|
|
set: (key, value, lifetime, callback) ->
|
|
prefixedKey = "#{@prefix}:#{key}"
|
|
expiry = (Date.now() + lifetime)
|
|
|
|
@_createExpiryTimer key, expiry
|
|
@persist.setItem prefixedKey, {value: value, expiry: expiry}, callback
|
|
|
|
process.nextTick ->
|
|
callback(null)
|
|
|
|
get: (key, callback) ->
|
|
prefixedKey = "#{@prefix}:#{key}"
|
|
result = @persist.getItem(prefixedKey)
|
|
value = result?.value
|
|
|
|
# Normalize to dates if we're reading from disk-persisted data... on disk, they're saved as strings.
|
|
if value?.firstRequest? and value?.firstRequest not instanceof Date
|
|
value.firstRequest = new Date(value.firstRequest)
|
|
|
|
if value?.lastRequest? and value?.lastRequest not instanceof Date
|
|
value.lastRequest = new Date(value.lastRequest)
|
|
|
|
process.nextTick ->
|
|
callback(null, value)
|
|
|
|
reset: (key, callback) ->
|
|
# I don't really understand why this is called 'reset'. It's quite clearly a 'remove' function...
|
|
@_createRemover(key)()
|
|
process.nextTick ->
|
|
callback(null)
|