refactor: removing governor
This commit is contained in:
parent
9fc916622f
commit
d157b3fb86
|
@ -15,7 +15,6 @@
|
|||
- '($1#L$2)'
|
||||
'@flecks/electron:./packages/electron': {}
|
||||
'@flecks/fleck:./packages/fleck': {}
|
||||
'@flecks/governor:./packages/governor': {}
|
||||
'@flecks/passport:./packages/passport': {}
|
||||
'@flecks/passport-local:./packages/passport-local': {}
|
||||
'@flecks/passport-local-react:./packages/passport-local-react': {}
|
||||
|
|
116
packages/governor/.gitignore
vendored
116
packages/governor/.gitignore
vendored
|
@ -1,116 +0,0 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
.env.test
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
|
@ -1,139 +0,0 @@
|
|||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [3.1.3](https://github.com/cha0s/flecks/compare/v3.1.1...v3.1.3) (2024-01-26)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [3.1.1](https://github.com/cha0s/flecks/compare/v3.1.0...v3.1.1) (2024-01-26)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [3.1.0](https://github.com/cha0s/flecks/compare/v1.4.1...v3.1.0) (2024-01-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* lint ([675aaad](https://github.com/cha0s/flecks/commit/675aaadaedd539ebbef9ab0ace9e9ae8832d1e08))
|
||||
* priority ([841c2fa](https://github.com/cha0s/flecks/commit/841c2faaa14a9385fa18a846e36a4770fc025166))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **fleck:** ProcessAssets ([84a30df](https://github.com/cha0s/flecks/commit/84a30df67ab0c8b5c34bb61657f6103775839e82))
|
||||
* webpack 5 ([f039f7b](https://github.com/cha0s/flecks/commit/f039f7b8f69b3c8b9564714890b2fe2d4cd8a22d))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.3](https://github.com/cha0s/flecks/compare/v2.0.2...v2.0.3) (2023-11-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* electron ([81fc978](https://github.com/cha0s/flecks/commit/81fc978da2b8d32e303d165fe7c2f6071ac8e741))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.2](https://github.com/cha0s/flecks/compare/v2.0.1...v2.0.2) (2023-11-22)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [2.0.1](https://github.com/cha0s/flecks/compare/v2.0.0...v2.0.1) (2023-11-22)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [2.0.0](https://github.com/cha0s/flecks/compare/v1.4.1...v2.0.0) (2023-11-22)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* webpack 5 support ([288b368](https://github.com/cha0s/flecks/commit/288b368b9ff96be5ccb58bd811838a4a4bb6c48c))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.4.1](https://github.com/cha0s/flecks/compare/v1.4.0...v1.4.1) (2022-03-19)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.4.0](https://github.com/cha0s/flecks/compare/v1.3.0...v1.4.0) (2022-03-19)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.3.0](https://github.com/cha0s/flecks/compare/v1.2.1...v1.3.0) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.2.1](https://github.com/cha0s/flecks/compare/v1.2.0...v1.2.1) (2022-03-08)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.2.0](https://github.com/cha0s/flecks/compare/v1.1.1...v1.2.0) (2022-03-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* old redis ([0a8c66a](https://github.com/cha0s/flecks/commit/0a8c66ad7d6da5d63563c40c509f5a165146d7be))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.1.1](https://github.com/cha0s/flecks/compare/v1.1.0...v1.1.1) (2022-02-28)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [1.1.0](https://github.com/cha0s/flecks/compare/v1.0.2...v1.1.0) (2022-02-28)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [1.0.2](https://github.com/cha0s/flecks/compare/v1.0.1...v1.0.2) (2022-02-28)
|
||||
|
||||
**Note:** Version bump only for package @flecks/governor
|
|
@ -1,35 +0,0 @@
|
|||
{
|
||||
"name": "@flecks/governor",
|
||||
"version": "3.1.3",
|
||||
"author": "cha0s",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "flecks build",
|
||||
"clean": "flecks clean",
|
||||
"lint": "flecks lint",
|
||||
"postversion": "npm run build",
|
||||
"test": "flecks test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/cha0s/flecks.git",
|
||||
"directory": "packages/governor"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"files": [
|
||||
"client.js",
|
||||
"server.js"
|
||||
],
|
||||
"dependencies": {
|
||||
"@flecks/core": "^3.1.0",
|
||||
"@flecks/db": "^3.1.3",
|
||||
"@flecks/redis": "^3.1.3",
|
||||
"rate-limiter-flexible": "^2.1.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@flecks/build": "^3.1.3",
|
||||
"@flecks/fleck": "^3.1.3"
|
||||
}
|
||||
}
|
|
@ -1,2 +0,0 @@
|
|||
// eslint-disable-next-line import/prefer-default-export
|
||||
export {default as createLimiter} from './limiter';
|
|
@ -1,3 +0,0 @@
|
|||
import RateLimiterMemory from 'rate-limiter-flexible/lib/RateLimiterMemory';
|
||||
|
||||
export default (flecks, options) => new RateLimiterMemory(options);
|
|
@ -1,29 +0,0 @@
|
|||
export default (flecks, [name, Packet]) => {
|
||||
const {ValidationError} = flecks.fleck('@flecks/socket');
|
||||
return class LimitedPacket extends Packet {
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.limit = flecks.governor.packet[name];
|
||||
}
|
||||
|
||||
static async validate(packet, socket) {
|
||||
try {
|
||||
await packet.limit.consume(socket.id);
|
||||
}
|
||||
catch (error) {
|
||||
if (error.msBeforeNext) {
|
||||
throw new ValidationError({
|
||||
code: 429,
|
||||
ttr: Math.round(error.msBeforeNext / 1000) || 1,
|
||||
});
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
if (super.validate) {
|
||||
await super.validate(packet, socket);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
};
|
|
@ -1,13 +0,0 @@
|
|||
import {createClient} from '@flecks/redis/server';
|
||||
import {RateLimiterRedis} from 'rate-limiter-flexible';
|
||||
|
||||
export default async (flecks, options) => {
|
||||
const storeClient = await createClient(flecks);
|
||||
const legacyClient = storeClient.duplicate({legacyMode: true});
|
||||
await legacyClient.connect();
|
||||
return new RateLimiterRedis({
|
||||
...options,
|
||||
// @todo node-redis@4
|
||||
storeClient: legacyClient,
|
||||
});
|
||||
};
|
|
@ -1,72 +0,0 @@
|
|||
export default (flecks) => {
|
||||
const {Model, Op, Types} = flecks.fleck('@flecks/db/server');
|
||||
const {config: {'@flecks/governor/server': {keys}}} = flecks;
|
||||
return class Ban extends Model {
|
||||
|
||||
static get attributes() {
|
||||
return {
|
||||
ttl: {
|
||||
type: Types.INTEGER,
|
||||
defaultValue: 0,
|
||||
},
|
||||
...Object.fromEntries(keys.map((key) => ([key, {type: Types.STRING}]))),
|
||||
};
|
||||
}
|
||||
|
||||
static async check(req) {
|
||||
const ban = this.fromRequest(req, keys);
|
||||
const candidates = Object.entries(ban)
|
||||
.reduce((r, [key, value]) => [...r, {[key]: value}], []);
|
||||
const where = {
|
||||
where: {
|
||||
[Op.or]: candidates,
|
||||
},
|
||||
};
|
||||
const bans = await this.findAll(where);
|
||||
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];
|
||||
}
|
||||
ban.ttl = Math.ceil((expiresAt.getTime() - Date.now()) / 1000);
|
||||
}
|
||||
return [...r, ban];
|
||||
}, [])
|
||||
.filter((ban) => !!ban)
|
||||
.map((ban) => {
|
||||
const {ttl, ...json} = ban.toJSON();
|
||||
return json;
|
||||
});
|
||||
if (0 === pruned.length) {
|
||||
return;
|
||||
}
|
||||
throw new Error(this.format(pruned));
|
||||
}
|
||||
|
||||
static format(bans) {
|
||||
return [
|
||||
'bans = [',
|
||||
bans.map((ban) => {
|
||||
const entries = Object.entries(ban)
|
||||
.filter(([key]) => -1 === ['id', 'createdAt', 'updatedAt'].indexOf(key));
|
||||
return [
|
||||
' {',
|
||||
entries.map(([key, value]) => ` ${key}: ${value},`).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} : {});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
|
@ -1,146 +0,0 @@
|
|||
import {ByType, Flecks} from '@flecks/core';
|
||||
import {RateLimiterRes} from 'rate-limiter-flexible';
|
||||
|
||||
import LimitedPacket from './limited-packet';
|
||||
import createLimiter from './limiter';
|
||||
|
||||
export {default as createLimiter} from './limiter';
|
||||
|
||||
export const hooks = {
|
||||
'@flecks/core.config': () => ({
|
||||
/**
|
||||
* All keys used to determine fingerprint.
|
||||
*/
|
||||
keys: ['ip'],
|
||||
web: {
|
||||
keys: ['ip'],
|
||||
points: 60,
|
||||
duration: 30,
|
||||
ttl: 30,
|
||||
},
|
||||
socket: {
|
||||
keys: ['ip'],
|
||||
points: 60,
|
||||
duration: 30,
|
||||
ttl: 30,
|
||||
},
|
||||
}),
|
||||
'@flecks/db.models': Flecks.provide(require.context('./models', false, /\.js$/)),
|
||||
'@flecks/web/server.request.route': Flecks.priority(
|
||||
(flecks) => {
|
||||
const {web} = flecks.get('@flecks/governor/server');
|
||||
return async (req, res, next) => {
|
||||
const {Ban} = flecks.db.Models;
|
||||
try {
|
||||
await Ban.check(req);
|
||||
}
|
||||
catch (error) {
|
||||
res.status(403).send(`<pre>${error.message}</pre>`);
|
||||
return;
|
||||
}
|
||||
req.ban = async (keys, ttl = 0) => {
|
||||
const ban = Ban.fromRequest(req, keys, ttl);
|
||||
await Ban.create({...ban});
|
||||
res.status(403).send(`<pre>${Ban.format([ban])}</pre>`);
|
||||
};
|
||||
try {
|
||||
await flecks.governor.web.consume(req.ip);
|
||||
next();
|
||||
}
|
||||
catch (error) {
|
||||
if (!(error instanceof RateLimiterRes)) {
|
||||
throw error;
|
||||
}
|
||||
const {ttl, keys} = web;
|
||||
const ban = Ban.fromRequest(req, keys, ttl);
|
||||
await Ban.create({...ban});
|
||||
res.status(429).send(`<pre>${Ban.format([ban])}</pre>`);
|
||||
}
|
||||
};
|
||||
},
|
||||
{after: '@flecks/passport/server'},
|
||||
),
|
||||
'@flecks/server.up': Flecks.priority(
|
||||
async (flecks) => {
|
||||
if (flecks.fleck('@flecks/web/server')) {
|
||||
const {web} = flecks.get('@flecks/governor/server');
|
||||
flecks.governor.web = await createLimiter(
|
||||
flecks,
|
||||
{
|
||||
keyPrefix: '@flecks/governor.web.request.route',
|
||||
...web,
|
||||
},
|
||||
);
|
||||
}
|
||||
if (flecks.fleck('@flecks/socket/server')) {
|
||||
flecks.governor.packet = Object.fromEntries(
|
||||
await Promise.all(
|
||||
Object.entries(flecks.socket.Packets[ByType])
|
||||
.filter(([, Packet]) => Packet.limit)
|
||||
.map(async ([name, Packet]) => (
|
||||
[
|
||||
name,
|
||||
await createLimiter(
|
||||
flecks,
|
||||
{keyPrefix: `@flecks/governor.packet.${name}`, ...Packet.limit},
|
||||
),
|
||||
]
|
||||
)),
|
||||
),
|
||||
);
|
||||
const {socket} = flecks.get('@flecks/governor/server');
|
||||
flecks.governor.socket = await createLimiter(
|
||||
flecks,
|
||||
{
|
||||
keyPrefix: '@flecks/governor.socket.request.socket',
|
||||
...socket,
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
{before: '@flecks/web/server', after: '@flecks/redis/server'},
|
||||
),
|
||||
'@flecks/socket/server.request.socket': (flecks) => (
|
||||
async (socket, next) => {
|
||||
const {handshake: req} = socket;
|
||||
const {Ban} = flecks.db.Models;
|
||||
try {
|
||||
await Ban.check(req);
|
||||
}
|
||||
catch (error) {
|
||||
next(error);
|
||||
return;
|
||||
}
|
||||
req.ban = async (keys, ttl) => {
|
||||
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
||||
socket.disconnect();
|
||||
};
|
||||
try {
|
||||
await flecks.governor.socket.consume(req.ip);
|
||||
next();
|
||||
}
|
||||
catch (error) {
|
||||
if (!(error instanceof RateLimiterRes)) {
|
||||
throw error;
|
||||
}
|
||||
const {ttl, keys} = socket;
|
||||
await Ban.create(Ban.fromRequest(req, keys, ttl));
|
||||
next(error);
|
||||
}
|
||||
}
|
||||
),
|
||||
'@flecks/socket.packets.decorate': (Packets, flecks) => (
|
||||
Object.fromEntries(
|
||||
Object.entries(Packets).map(([keyPrefix, Packet]) => [
|
||||
keyPrefix,
|
||||
!Packet.limit ? Packet : LimitedPacket(flecks, [keyPrefix, Packet]),
|
||||
]),
|
||||
)
|
||||
),
|
||||
};
|
||||
|
||||
export const mixin = (Flecks) => class FlecksWithGovernor extends Flecks {
|
||||
|
||||
governor = {};
|
||||
|
||||
};
|
|
@ -82,7 +82,7 @@ export const hooks = {
|
|||
});
|
||||
});
|
||||
},
|
||||
{after: '@flecks/session/server', before: '@flecks/governor/server'},
|
||||
{after: '@flecks/session/server'},
|
||||
),
|
||||
'@flecks/web.routes': (flecks) => {
|
||||
const {
|
||||
|
|
Loading…
Reference in New Issue
Block a user