Automatically migrated from Gitolite
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

71 lines
1.9 KiB

# 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}:")
.filter (key) => key.match(@_keyMatcher)
.forEach (key) =>
@_createExpiryTimer key, @persist.getItem(key).expiry
_createExpiryTimer: (key, expiry) ->
ttl = expiry -
if ttl < 0
setTimeout @_createRemover(key), ttl
_removeExpiryTimer: (key) ->
if @_timers[key]?
clearTimeout @_timers[key]
delete @_timers[key]
_createRemover: (key) ->
return =>
prefixedKey = "#{@prefix}:#{key}"
# TODO: Error handling?
@persist.removeItem prefixedKey
set: (key, value, lifetime, callback) ->
prefixedKey = "#{@prefix}:#{key}"
expiry = ( + lifetime)
@_createExpiryTimer key, expiry
@persist.setItem prefixedKey, {value: value, expiry: expiry}, callback
process.nextTick ->
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...
process.nextTick ->