DTP Social Engine
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.
 
 
 
 
 

75 lines
2.0 KiB

// limiter.js
// Copyright (C) 2022 DTP Technologies, LLC
// License: Apache-2.0
'use strict';
const path = require('path');
const { RateLimiterRedis } = require('rate-limiter-flexible');
const expressLimiter = require('express-limiter');
const { SiteService, SiteError } = require('../../lib/site-lib');
class LimiterService extends SiteService {
constructor (dtp) {
super(dtp, module.exports);
this.config = require(path.resolve(dtp.config.root, 'config', 'limiter.js'));
this.limiter = expressLimiter(this.dtp.app, this.dtp.redis);
this.handlers = {
lookup: this.limiterLookup.bind(this),
whitelist: this.limiterWhitelist.bind(this),
};
this.rateLimiters = { };
}
createMiddleware (config) {
const options = {
total: config.total,
expire: config.expire,
lookup: this.handlers.lookup,
whitelist: this.handlers.whitelist,
onRateLimited: async (req, res, next) => {
this.emit('limiter:block', req);
next(new SiteError(config.status || 429, config.message || 'Rate limit exceeded'));
},
};
const middleware = this.limiter(options);
return async (req, res, next) => {
return middleware(req, res, next);
};
}
limiterLookup (req, res, options, next) {
if (req.user) {
options.lookup = 'user._id'; // req.user._id, populated by PassportJS session
} else {
options.lookup = 'ip'; // req.ip, populated by ExpressJS with trust_proxy=1
}
return next();
}
limiterWhitelist (req) {
return req.user && req.user.flags.isAdmin;
}
createRateLimiter (id, config) {
if (this.rateLimiters[id]) {
return this.rateLimiters[id];
}
config = Object.assign({
storeClient: this.dtp.redis,
}, config);
this.rateLimiters[id] = new RateLimiterRedis(config);
return this.rateLimiters[id];
}
}
module.exports = {
slug: 'limiter',
name: 'limiter',
create: (dtp) => { return new LimiterService(dtp); },
};