UNPKG

rate-limiter-flexible

Version:

Node.js rate limiter by key and protection from DDoS and Brute-Force attacks in process Memory, Redis, MongoDb, Memcached, MySQL, PostgreSQL, Cluster or PM

196 lines (158 loc) 4.32 kB
const RateLimiterRes = require('./RateLimiterRes'); module.exports = class RLWrapperBlackAndWhite { constructor(opts = {}) { this.limiter = opts.limiter; this.blackList = opts.blackList; this.whiteList = opts.whiteList; this.isBlackListed = opts.isBlackListed; this.isWhiteListed = opts.isWhiteListed; this.runActionAnyway = opts.runActionAnyway; } get limiter() { return this._limiter; } set limiter(value) { if (typeof value === 'undefined') { throw new Error('limiter is not set'); } this._limiter = value; } get runActionAnyway() { return this._runActionAnyway; } set runActionAnyway(value) { this._runActionAnyway = typeof value === 'undefined' ? false : value; } get blackList() { return this._blackList; } set blackList(value) { this._blackList = Array.isArray(value) ? value : []; } get isBlackListed() { return this._isBlackListed; } set isBlackListed(func) { if (typeof func === 'undefined') { func = () => false; } if (typeof func !== 'function') { throw new Error('isBlackListed must be function'); } this._isBlackListed = func; } get whiteList() { return this._whiteList; } set whiteList(value) { this._whiteList = Array.isArray(value) ? value : []; } get isWhiteListed() { return this._isWhiteListed; } set isWhiteListed(func) { if (typeof func === 'undefined') { func = () => false; } if (typeof func !== 'function') { throw new Error('isWhiteListed must be function'); } this._isWhiteListed = func; } isBlackListedSomewhere(key) { return this.blackList.indexOf(key) >= 0 || this.isBlackListed(key); } isWhiteListedSomewhere(key) { return this.whiteList.indexOf(key) >= 0 || this.isWhiteListed(key); } getBlackRes() { return new RateLimiterRes(0, Number.MAX_SAFE_INTEGER, 0, false); } getWhiteRes() { return new RateLimiterRes(Number.MAX_SAFE_INTEGER, 0, 0, false); } rejectBlack() { return Promise.reject(this.getBlackRes()); } resolveBlack() { return Promise.resolve(this.getBlackRes()); } resolveWhite() { return Promise.resolve(this.getWhiteRes()); } consume(key, pointsToConsume = 1) { let res; if (this.isWhiteListedSomewhere(key)) { res = this.resolveWhite(); } else if (this.isBlackListedSomewhere(key)) { res = this.rejectBlack(); } if (typeof res === 'undefined') { return this.limiter.consume(key, pointsToConsume); } if (this.runActionAnyway) { this.limiter.consume(key, pointsToConsume).catch(() => {}); } return res; } block(key, secDuration) { let res; if (this.isWhiteListedSomewhere(key)) { res = this.resolveWhite(); } else if (this.isBlackListedSomewhere(key)) { res = this.resolveBlack(); } if (typeof res === 'undefined') { return this.limiter.block(key, secDuration); } if (this.runActionAnyway) { this.limiter.block(key, secDuration).catch(() => {}); } return res; } penalty(key, points) { let res; if (this.isWhiteListedSomewhere(key)) { res = this.resolveWhite(); } else if (this.isBlackListedSomewhere(key)) { res = this.resolveBlack(); } if (typeof res === 'undefined') { return this.limiter.penalty(key, points); } if (this.runActionAnyway) { this.limiter.penalty(key, points).catch(() => {}); } return res; } reward(key, points) { let res; if (this.isWhiteListedSomewhere(key)) { res = this.resolveWhite(); } else if (this.isBlackListedSomewhere(key)) { res = this.resolveBlack(); } if (typeof res === 'undefined') { return this.limiter.reward(key, points); } if (this.runActionAnyway) { this.limiter.reward(key, points).catch(() => {}); } return res; } get(key) { let res; if (this.isWhiteListedSomewhere(key)) { res = this.resolveWhite(); } else if (this.isBlackListedSomewhere(key)) { res = this.resolveBlack(); } if (typeof res === 'undefined' || this.runActionAnyway) { return this.limiter.get(key); } return res; } delete(key) { return this.limiter.delete(key); } };