refactor: bans
This commit is contained in:
parent
3d7db1a001
commit
7f66434cda
|
@ -1,6 +1,6 @@
|
||||||
/* eslint-disable import/no-extraneous-dependencies */
|
/* eslint-disable import/no-extraneous-dependencies */
|
||||||
import {
|
import {
|
||||||
Model, Types,
|
Model, Op, Types,
|
||||||
} from '@latus/db';
|
} from '@latus/db';
|
||||||
|
|
||||||
export default (latus) => {
|
export default (latus) => {
|
||||||
|
@ -18,51 +18,57 @@ export default (latus) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async check(req) {
|
static async check(req) {
|
||||||
const entries = keys.map((key) => [key, req[key]]);
|
const ban = this.fromRequest(req, keys);
|
||||||
const promises = entries.map(([key, value]) => this.findOne({where: {[key]: value}}));
|
const candidates = Object.entries(ban)
|
||||||
const bans = await Promise.all(promises);
|
.reduce((r, [key, value]) => [...r, {[key]: value}], []);
|
||||||
const pruned = bans.reduce((r, ban) => {
|
const where = {
|
||||||
if (ban && ban.ttl > 0) {
|
where: {
|
||||||
const expiresAt = new Date(ban.createdAt);
|
[Op.or]: candidates,
|
||||||
expiresAt.setSeconds(expiresAt.getSeconds() + ban.ttl);
|
},
|
||||||
if (Date.now() >= expiresAt.getTime()) {
|
};
|
||||||
this.destroy({where: {id: ban.id}});
|
const bans = await this.findAll(where);
|
||||||
return [...r, null];
|
const pruned = bans
|
||||||
|
.reduce((r, ban) => {
|
||||||
|
if (ban && ban.ttl > 0) {
|
||||||
|
const expiresAt = new Date(ban.createdAt);
|
||||||
|
expiresAt.setSeconds(expiresAt.getSeconds() + ban.ttl);
|
||||||
|
if (Date.now() >= expiresAt.getTime()) {
|
||||||
|
this.destroy({where: {id: ban.id}});
|
||||||
|
return [...r, null];
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
ban.ttl = Math.ceil((expiresAt.getTime() - Date.now()) / 1000);
|
||||||
}
|
}
|
||||||
}
|
return [...r, ban];
|
||||||
return [...r, ban];
|
}, [])
|
||||||
}, []);
|
.filter((ban) => !!ban)
|
||||||
const prunedEntries = pruned
|
.map((ban) => ban.toJSON());
|
||||||
.reduce((r, ban, i) => ([
|
if (0 === pruned.length) {
|
||||||
...r,
|
|
||||||
...(
|
|
||||||
ban
|
|
||||||
? [[
|
|
||||||
entries[i][0],
|
|
||||||
[ban.ttl, entries[i][1]],
|
|
||||||
]]
|
|
||||||
: []),
|
|
||||||
]), []);
|
|
||||||
if (0 === prunedEntries.length) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error(this.format(prunedEntries));
|
throw new Error(this.format(pruned));
|
||||||
}
|
|
||||||
|
|
||||||
static async create(req, keys, ttl) {
|
|
||||||
return Promise.all(keys.map((key) => super.create({[key]: req[key], ttl})));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static format(bans) {
|
static format(bans) {
|
||||||
return [
|
return [
|
||||||
'ban = {',
|
'bans = [',
|
||||||
bans.map(
|
bans.map((ban) => {
|
||||||
([key, [ttl, value]]) => ` ${key}: ${value},${ttl ? ` // ttl: ${ttl}` : ''}`,
|
const entries = Object.entries(ban)
|
||||||
).join('\n'),
|
.filter(([key]) => -1 === ['id', 'createdAt', 'updatedAt'].indexOf(key));
|
||||||
'};',
|
return [
|
||||||
|
' {',
|
||||||
|
entries.map(([key, value]) => ` ${key}: ${value},`).join('\n'),
|
||||||
|
' },',
|
||||||
|
].join('\n');
|
||||||
|
}).join('\n'),
|
||||||
|
'];',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromRequest(req, keys, ttl = 0) {
|
||||||
|
return keys.reduce((r, key) => ({...r, [key]: req[key]}), ttl ? {ttl} : {});
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,10 +6,6 @@ import createLimiter from './limiter';
|
||||||
|
|
||||||
export {createLimiter};
|
export {createLimiter};
|
||||||
|
|
||||||
const {
|
|
||||||
NODE_ENV,
|
|
||||||
} = process.env;
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
hooks: {
|
hooks: {
|
||||||
'@latus/core/config': () => ({
|
'@latus/core/config': () => ({
|
||||||
|
@ -46,8 +42,9 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req.ban = async (keys, ttl = 0) => {
|
req.ban = async (keys, ttl = 0) => {
|
||||||
await Ban.create(req, keys, ttl);
|
const ban = Ban.fromRequest(req, keys, ttl);
|
||||||
res.status(403).send(`<pre>${Ban.format(keys.map((key) => [key, [ttl, req[key]]]))}</pre>`);
|
await Ban.create({...ban});
|
||||||
|
res.status(403).send(`<pre>${Ban.format([ban])}</pre>`);
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
await limiter.consume(req.ip);
|
await limiter.consume(req.ip);
|
||||||
|
@ -55,8 +52,9 @@ export default {
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
const {ttl, keys} = http;
|
const {ttl, keys} = http;
|
||||||
await Ban.create(req, keys, ttl);
|
const ban = Ban.fromRequest(req, keys, ttl);
|
||||||
res.status(429).send(`<pre>${Ban.format(keys.map((key) => [key, [ttl, req[key]]]))}</pre>`);
|
await Ban.create({...ban});
|
||||||
|
res.status(429).send(`<pre>${Ban.format([ban])}</pre>`);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
@ -77,7 +75,7 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
req.ban = async (keys, ttl) => {
|
req.ban = async (keys, ttl) => {
|
||||||
await Ban.create(req, keys, ttl);
|
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
||||||
socket.disconnect();
|
socket.disconnect();
|
||||||
};
|
};
|
||||||
try {
|
try {
|
||||||
|
@ -86,7 +84,7 @@ export default {
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
const {ttl, keys} = socket;
|
const {ttl, keys} = socket;
|
||||||
await Ban.create(req, keys, ttl);
|
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue
Block a user