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.
64 lines
1.8 KiB
64 lines
1.8 KiB
// limiter.js
|
|
// Copyright (C) 2024 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
'use strict';
|
|
|
|
import path from 'node:path';
|
|
import expressLimiter from 'express-limiter';
|
|
|
|
import { SiteService, SiteError } from '../../lib/site-lib.js';
|
|
|
|
export default class LimiterService extends SiteService {
|
|
|
|
static get slug ( ) { return 'limiter'; }
|
|
static get name ( ) { return 'LimiterService'; }
|
|
|
|
constructor (dtp) {
|
|
super(dtp, LimiterService);
|
|
|
|
this.handlers = {
|
|
lookup: this.limiterLookup.bind(this),
|
|
whitelist: this.limiterWhitelist.bind(this),
|
|
};
|
|
}
|
|
|
|
async start ( ) {
|
|
this.config = (await import(path.resolve(this.dtp.config.root, 'config', 'limiter.js'))).default;
|
|
this.limiter = expressLimiter(this.dtp.app, this.dtp.redis);
|
|
}
|
|
|
|
create (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'));
|
|
},
|
|
};
|
|
// this.log.debug('creating rate limiter', { options });
|
|
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) {
|
|
if ((process.env.NODE_ENV === 'local') && (process.env.DTP_RATE_LIMITER === 'disabled')) {
|
|
return true;
|
|
}
|
|
return req.user && req.user.flags.isAdmin;
|
|
}
|
|
}
|