@universis/janitor 1.6.1 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"file":"RedisClientStore.js","names":["_common","require","_rateLimitRedis","_interopRequireDefault","_ioredis","obj","__esModule","default","_defineProperty","key","value","_toPropertyKey","Object","defineProperty","enumerable","configurable","writable","arg","_toPrimitive","String","input","hint","prim","Symbol","toPrimitive","undefined","res","call","TypeError","Number","superLoadIncrementScript","superLoadGetScript","noLoadGetScript","noLoadIncrementScript","RedisStore","prototype","loadIncrementScript","name","loadGetScript","RedisClientStore","constructor","service","options","sendCommand","args","Array","from","arguments","command","splice","self","connectOptions","getApplication","getConfiguration","getSourceAt","host","port","client","Redis","catch","error","message","TraceUtils","warn","JSON","stringify","Promise","reject","finally","isOpen","disconnect","errDisconnect","incrementScriptSha","postInit","resolve","then","init","debug","err","getScriptSha","sequence","exports"],"sources":["../src/RedisClientStore.js"],"sourcesContent":["import { TraceUtils } from '@themost/common';\nimport RedisStore from 'rate-limit-redis';\nimport { Redis } from 'ioredis';\nimport '@themost/promise-sequence';\n\nlet superLoadIncrementScript;\nlet superLoadGetScript;\n\nfunction noLoadGetScript() {\n //\n}\n\nfunction noLoadIncrementScript() {\n //\n}\n\nif (RedisStore.prototype.loadIncrementScript.name === 'loadIncrementScript') {\n // get super method for future use\n superLoadIncrementScript = RedisStore.prototype.loadIncrementScript;\n RedisStore.prototype.loadIncrementScript = noLoadIncrementScript;\n}\n\nif (RedisStore.prototype.loadGetScript.name === 'loadGetScript') {\n // get super method\n superLoadGetScript = RedisStore.prototype.loadGetScript;\n RedisStore.prototype.loadGetScript = noLoadGetScript;\n}\n\nclass RedisClientStore extends RedisStore {\n\n /**\n * @type {import('redis').RedisClientType}\n */\n client;\n\n /**\n * \n * @param {import('@themost/common').ApplicationService} service\n * @param {{windowMs: number}} options\n */\n constructor(service, options) {\n super({\n /**\n * @param {...string} args\n * @returns {Promise<*>}\n */\n sendCommand: function () {\n const args = Array.from(arguments);\n const [command] = args.splice(0, 1);\n const self = this;\n if (command === 'SCRIPT') {\n const connectOptions = service.getApplication().getConfiguration().getSourceAt('settings/redis/options') || {\n host: '127.0.0.1',\n port: 6379\n };\n const client = new Redis(connectOptions);\n return client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n }).finally(() => {\n if (client.isOpen) {\n client.disconnect().catch((errDisconnect) => {\n TraceUtils.error(errDisconnect);\n });\n }\n });\n }\n if (self.client == null) {\n const connectOptions = service.getApplication().getConfiguration().getSourceAt('settings/redis/options') || {\n host: '127.0.0.1',\n port: 6379\n };\n self.client = new Redis(connectOptions);\n }\n if (self.client.isOpen) {\n return self.client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n });\n }\n // send load script commands once\n return (() => {\n if (self.incrementScriptSha == null) {\n return this.postInit();\n }\n return Promise.resolve();\n })().then(() => {\n // send command \n args[0] = self.incrementScriptSha;\n return self.client.call(command, args).catch((error) => {\n if (error instanceof TypeError && error.message === 'Invalid argument type') {\n TraceUtils.warn('RedisClientStore: Invalid argument type: ' + JSON.stringify(args));\n }\n return Promise.reject(error);\n });\n });\n }\n });\n this.init(options);\n TraceUtils.debug('RedisClientStore: Starting up and loading increment and get scripts.');\n void this.postInit().then(() => {\n TraceUtils.debug('RedisClientStore: Successfully loaded increment and get scripts.');\n }).catch((err) => {\n TraceUtils.error('RedisClientStore: Failed to load increment and get scripts.');\n TraceUtils.error(err);\n });\n }\n async postInit() {\n const [incrementScriptSha, getScriptSha] = await Promise.sequence([\n () => superLoadIncrementScript.call(this),\n () => superLoadGetScript.call(this)\n ]);\n this.incrementScriptSha = incrementScriptSha;\n this.getScriptSha = getScriptSha;\n }\n\n}\n\nexport {\n RedisClientStore\n}"],"mappings":"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"}
@@ -1,10 +0,0 @@
1
- import { ApplicationService } from '@themost/common';
2
- import { Request } from 'express';
3
-
4
- export declare class RemoteAddressValidator extends ApplicationService {
5
-
6
- constructor(app: ApplicationService);
7
- validateRemoteAddress(request: Request): Promise<boolean>;
8
- getRemoteAddress(request: Request): string;
9
-
10
- }
@@ -1,89 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.RemoteAddressValidator = exports.HttpRemoteAddrForbiddenError = void 0;var _common = require("@themost/common");
2
- var _express = _interopRequireDefault(require("express"));
3
- var _jsonwebtoken = _interopRequireDefault(require("jsonwebtoken"));function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
4
-
5
- class HttpRemoteAddrForbiddenError extends _common.HttpForbiddenError {
6
- constructor() {
7
- super('Access is denied due to remote address conflict. The client network has been changed or cannot be determined.');
8
- this.statusCode = 403.6;
9
- }
10
-
11
- }exports.HttpRemoteAddrForbiddenError = HttpRemoteAddrForbiddenError;
12
-
13
- class RemoteAddressValidator extends _common.ApplicationService {
14
- constructor(app) {
15
- super(app);
16
-
17
- // get proxy address forwarding option
18
- let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');
19
- if (typeof proxyAddressForwarding !== 'boolean') {
20
- proxyAddressForwarding = false;
21
- }
22
- this.proxyAddressForwarding = proxyAddressForwarding;
23
- // get token claim name
24
- this.claim = app.getConfiguration().getSourceAt('settings/universis/janitor/remoteAddress/claim') || 'remoteAddress';
25
-
26
- app.serviceRouter.subscribe((serviceRouter) => {
27
- if (serviceRouter == null) {
28
- return;
29
- }
30
- const addRouter = _express.default.Router();
31
- addRouter.use((req, res, next) => {
32
- void this.validateRemoteAddress(req).then((value) => {
33
- if (value === false) {
34
- return next(new HttpRemoteAddrForbiddenError());
35
- }
36
- return next();
37
- }).catch((err) => {
38
- return next(err);
39
- });
40
- });
41
- // insert router at the beginning of serviceRouter.stack
42
- serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);
43
- });
44
- }
45
-
46
- /**
47
- * Gets remote address from request
48
- * @param {import('express').Request} req
49
- * @returns
50
- */
51
- getRemoteAddress(req) {
52
- let remoteAddress;
53
- if (this.proxyAddressForwarding) {
54
- // get proxy headers or remote address
55
- remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);
56
- } else {
57
- remoteAddress = req.connection ? req.connection.remoteAddress : req.socket.remoteAddress;
58
- }
59
- return remoteAddress;
60
- }
61
-
62
- /**
63
- * Validates token remote address with request remote address
64
- * @param {import('express').Request} req
65
- * @returns {Promise<boolean>}
66
- */
67
- async validateRemoteAddress(req) {var _req$context, _req$context$user;
68
- const authenticationToken = (_req$context = req.context) === null || _req$context === void 0 ? void 0 : (_req$context$user = _req$context.user) === null || _req$context$user === void 0 ? void 0 : _req$context$user.authenticationToken;
69
- if (authenticationToken != null) {
70
- const access_token = _jsonwebtoken.default.decode(authenticationToken);
71
- const remoteAddress = access_token[this.claim];
72
- if (remoteAddress == null) {
73
- _common.TraceUtils.warn(`Remote address validation failed. Expected a valid remote address claimed by using "${this.claim}" attribute but got none.`);
74
- return false;
75
- }
76
- // get context remote address
77
- const requestRemoteAddress = this.getRemoteAddress(req);
78
- if (remoteAddress !== requestRemoteAddress) {
79
- _common.TraceUtils.warn(`Remote address validation failed. Expected remote address is ${remoteAddress || 'Uknown'} but request remote address is ${requestRemoteAddress}`);
80
- return false;
81
- }
82
- return true;
83
- }
84
- _common.TraceUtils.warn('Remote address validation cannot be completed because authentication token is not available.');
85
- return false;
86
- }
87
-
88
- }exports.RemoteAddressValidator = RemoteAddressValidator;
89
- //# sourceMappingURL=RemoteAddressValidator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"RemoteAddressValidator.js","names":["_common","require","_express","_interopRequireDefault","_jsonwebtoken","obj","__esModule","default","HttpRemoteAddrForbiddenError","HttpForbiddenError","constructor","statusCode","exports","RemoteAddressValidator","ApplicationService","app","proxyAddressForwarding","getConfiguration","getSourceAt","claim","serviceRouter","subscribe","addRouter","express","Router","use","req","res","next","validateRemoteAddress","then","value","catch","err","stack","unshift","apply","getRemoteAddress","remoteAddress","headers","connection","socket","_req$context","_req$context$user","authenticationToken","context","user","access_token","jwt","decode","TraceUtils","warn","requestRemoteAddress"],"sources":["../src/RemoteAddressValidator.js"],"sourcesContent":["import { ApplicationService, HttpForbiddenError, TraceUtils } from '@themost/common';\nimport express from 'express';\nimport jwt from 'jsonwebtoken';\n\nclass HttpRemoteAddrForbiddenError extends HttpForbiddenError {\n constructor() {\n super('Access is denied due to remote address conflict. The client network has been changed or cannot be determined.');\n this.statusCode = 403.6;\n }\n \n}\n\nclass RemoteAddressValidator extends ApplicationService {\n constructor(app) {\n super(app);\n\n // get proxy address forwarding option\n let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');\n if (typeof proxyAddressForwarding !== 'boolean') {\n proxyAddressForwarding = false;\n }\n this.proxyAddressForwarding = proxyAddressForwarding;\n // get token claim name\n this.claim = app.getConfiguration().getSourceAt('settings/universis/janitor/remoteAddress/claim') || 'remoteAddress';\n\n app.serviceRouter.subscribe((serviceRouter) => {\n if (serviceRouter == null) {\n return;\n }\n const addRouter = express.Router();\n addRouter.use((req, res, next) => {\n void this.validateRemoteAddress(req).then((value) => {\n if (value === false) {\n return next(new HttpRemoteAddrForbiddenError());\n }\n return next();\n }).catch((err) => {\n return next(err);\n });\n });\n // insert router at the beginning of serviceRouter.stack\n serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);\n });\n }\n\n /**\n * Gets remote address from request\n * @param {import('express').Request} req \n * @returns \n */\n getRemoteAddress(req) {\n let remoteAddress;\n if (this.proxyAddressForwarding) {\n // get proxy headers or remote address\n remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n } else {\n remoteAddress = req.connection ? req.connection.remoteAddress : req.socket.remoteAddress;\n }\n return remoteAddress;\n }\n\n /**\n * Validates token remote address with request remote address\n * @param {import('express').Request} req \n * @returns {Promise<boolean>}\n */\n async validateRemoteAddress(req) {\n const authenticationToken = req.context?.user?.authenticationToken;\n if (authenticationToken != null) {\n const access_token = jwt.decode(authenticationToken);\n const remoteAddress = access_token[this.claim];\n if (remoteAddress == null) {\n TraceUtils.warn(`Remote address validation failed. Expected a valid remote address claimed by using \"${this.claim}\" attribute but got none.`);\n return false;\n }\n // get context remote address\n const requestRemoteAddress = this.getRemoteAddress(req);\n if (remoteAddress !== requestRemoteAddress) {\n TraceUtils.warn(`Remote address validation failed. Expected remote address is ${remoteAddress || 'Uknown'} but request remote address is ${requestRemoteAddress}`);\n return false;\n }\n return true;\n }\n TraceUtils.warn('Remote address validation cannot be completed because authentication token is not available.');\n return false;\n }\n\n}\n\nexport {\n HttpRemoteAddrForbiddenError,\n RemoteAddressValidator\n}\n"],"mappings":"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"}
@@ -1,65 +0,0 @@
1
- /**
2
- * @license
3
- * Universis Project Version 1.0
4
- * Copyright (c) 2018, Universis Project All rights reserved
5
- *
6
- * Use of this source code is governed by an LGPL 3.0 license that can be
7
- * found in the LICENSE file at https://universis.io/license
8
- */
9
- import {ConfigurationBase, ConfigurationStrategy} from '@themost/common';
10
-
11
- export declare class ScopeString {
12
- constructor(str: string);
13
- split(): string[];
14
- }
15
-
16
- /**
17
- * Declares a configuration element for managing scope-based permissions on server resources
18
- */
19
- export declare interface ScopeAccessConfigurationElement {
20
- /**
21
- * Gets or sets an array of strings that holds an array of scopes e.g. students or students:read or students,teachers etc
22
- */
23
- scope: string[],
24
- /**
25
- * Gets or sets a string which represents the regular expression that is going to be used for validating endpoint
26
- */
27
- resource: string;
28
- /**
29
- * Gets or sets an array of strings which represents the access levels for the given scopes e.g. READ or READ,WRITE etc
30
- */
31
- access: string[];
32
- /**
33
- * Gets or sets a string which represents a short description for this item
34
- */
35
- description?: string;
36
- }
37
-
38
- export declare class ScopeAccessConfiguration extends ConfigurationStrategy {
39
-
40
- constructor(configuration: ConfigurationBase);
41
-
42
- /**
43
- * Gets an array of scope access configuration elements
44
- */
45
- public elements: ScopeAccessConfigurationElement[];
46
-
47
- /**
48
- * Verifies the given request and returns a promise that resolves with a scope access configuration element
49
- */
50
- verify(req: Request): Promise<ScopeAccessConfigurationElement>;
51
- }
52
-
53
- export declare class DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {
54
-
55
- constructor(configuration: ConfigurationBase);
56
- /**
57
- * Gets an array of scope access configuration elements
58
- */
59
- public elements: ScopeAccessConfigurationElement[];
60
- /**
61
- * Verifies the given request and returns a promise that resolves with a scope access configuration element
62
- */
63
- verify(req: Request): Promise<ScopeAccessConfigurationElement>;
64
-
65
- }
@@ -1,123 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.ScopeString = exports.ScopeAccessConfiguration = exports.DefaultScopeAccessConfiguration = void 0;var _common = require("@themost/common");
2
- var _path = _interopRequireDefault(require("path"));
3
- var _url = _interopRequireDefault(require("url"));function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
4
-
5
- const HTTP_METHOD_REGEXP = /^\b(POST|PUT|PATCH|DELETE)\b$/i;
6
-
7
- class ScopeString {
8
- constructor(str) {
9
- this.value = str;
10
- }
11
- toString() {
12
- return this.value;
13
- }
14
- /**
15
- * Splits a comma-separated or space-separated scope string e.g. "profile email" or "profile,email"
16
- *
17
- * Important note: https://www.rfc-editor.org/rfc/rfc6749#section-3.3 defines the regular expression of access token scopes
18
- * which is a space separated string. Several OAuth2 servers use a comma-separated list instead.
19
- *
20
- * The operation will try to use both implementations by excluding comma ',' from access token regular expressions
21
- * @returns {Array<string>}
22
- */
23
- split() {
24
- // the default regular expression includes comma /([\x21\x23-\x5B\x5D-\x7E]+)/g
25
- // the modified regular expression excludes comma /x2C /([\x21\x23-\x2B\x2D-\x5B\x5D-\x7E]+)/g
26
- const re = /([\x21\x23-\x2B\x2D-\x5B\x5D-\x7E]+)/g;
27
- const results = [];
28
- let match = re.exec(this.value);
29
- while (match !== null) {
30
- results.push(match[0]);
31
- match = re.exec(this.value);
32
- }
33
- return results;
34
- }
35
- }exports.ScopeString = ScopeString;
36
-
37
- class ScopeAccessConfiguration extends _common.ConfigurationStrategy {
38
- /**
39
- * @param {import('@themost/common').ConfigurationBase} configuration
40
- */
41
- constructor(configuration) {
42
- super(configuration);
43
- let elements = [];
44
- // define property
45
- Object.defineProperty(this, 'elements', {
46
- get: () => {
47
- return elements;
48
- },
49
- enumerable: true
50
- });
51
- }
52
-
53
- /**
54
- * @param {Request} req
55
- * @returns Promise<ScopeAccessConfigurationElement>
56
- */
57
- verify(req) {
58
- return new Promise((resolve, reject) => {
59
- try {
60
- // validate request context
61
- _common.Args.notNull(req.context, 'Context');
62
- // validate request context user
63
- _common.Args.notNull(req.context.user, 'User');
64
- if (req.context.user.authenticationScope && req.context.user.authenticationScope.length > 0) {
65
- // get original url
66
- let reqUrl = _url.default.parse(req.originalUrl).pathname;
67
- // get user context scopes as array e.g, ['students', 'students:read']
68
- let reqScopes = new ScopeString(req.context.user.authenticationScope).split();
69
- // get user access based on HTTP method e.g. GET -> read access
70
- let reqAccess = HTTP_METHOD_REGEXP.test(req.method) ? 'write' : 'read';
71
- let result = this.elements.find((x) => {
72
- // filter element by access level
73
- return x.access.indexOf(reqAccess) >= 0
74
- // resource path
75
- && new RegExp('^' + x.resource, 'i').test(reqUrl)
76
- // and scopes
77
- && x.scope.find((y) => {
78
- // search user scopes (validate wildcard scope)
79
- return y === '*' || reqScopes.indexOf(y) >= 0;
80
- });
81
- });
82
- return resolve(result);
83
- }
84
- return resolve();
85
- }
86
- catch (err) {
87
- return reject(err);
88
- }
89
-
90
- });
91
- }
92
-
93
- }
94
-
95
- /**
96
- * @class
97
- */exports.ScopeAccessConfiguration = ScopeAccessConfiguration;
98
- class DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {
99
- /**
100
- * @param {import('@themost/common').ConfigurationBase} configuration
101
- */
102
- constructor(configuration) {
103
- super(configuration);
104
- let defaults = [];
105
- // load scope access from configuration resource
106
- try {
107
- /**
108
- * @type {Array<ScopeAccessConfigurationElement>}
109
- */
110
- defaults = require(_path.default.resolve(configuration.getConfigurationPath(), 'scope.access.json'));
111
- }
112
- catch (err) {
113
- // if an error occurred other than module not found (there are no default access policies)
114
- if (err.code !== 'MODULE_NOT_FOUND') {
115
- // throw error
116
- throw err;
117
- }
118
- // otherwise continue
119
- }
120
- this.elements.push.apply(this.elements, defaults);
121
- }
122
- }exports.DefaultScopeAccessConfiguration = DefaultScopeAccessConfiguration;
123
- //# sourceMappingURL=ScopeAccessConfiguration.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ScopeAccessConfiguration.js","names":["_common","require","_path","_interopRequireDefault","_url","obj","__esModule","default","HTTP_METHOD_REGEXP","ScopeString","constructor","str","value","toString","split","re","results","match","exec","push","exports","ScopeAccessConfiguration","ConfigurationStrategy","configuration","elements","Object","defineProperty","get","enumerable","verify","req","Promise","resolve","reject","Args","notNull","context","user","authenticationScope","length","reqUrl","url","parse","originalUrl","pathname","reqScopes","reqAccess","test","method","result","find","x","access","indexOf","RegExp","resource","scope","y","err","DefaultScopeAccessConfiguration","defaults","path","getConfigurationPath","code","apply"],"sources":["../src/ScopeAccessConfiguration.js"],"sourcesContent":["import {ConfigurationStrategy, Args} from '@themost/common';\nimport path from 'path';\nimport url from 'url';\n\nconst HTTP_METHOD_REGEXP = /^\\b(POST|PUT|PATCH|DELETE)\\b$/i;\n\nclass ScopeString {\n constructor(str) {\n this.value = str;\n }\n toString() {\n return this.value;\n }\n /**\n * Splits a comma-separated or space-separated scope string e.g. \"profile email\" or \"profile,email\"\n *\n * Important note: https://www.rfc-editor.org/rfc/rfc6749#section-3.3 defines the regular expression of access token scopes\n * which is a space separated string. Several OAuth2 servers use a comma-separated list instead.\n *\n * The operation will try to use both implementations by excluding comma ',' from access token regular expressions\n * @returns {Array<string>}\n */\n split() {\n // the default regular expression includes comma /([\\x21\\x23-\\x5B\\x5D-\\x7E]+)/g\n // the modified regular expression excludes comma /x2C /([\\x21\\x23-\\x2B\\x2D-\\x5B\\x5D-\\x7E]+)/g\n const re = /([\\x21\\x23-\\x2B\\x2D-\\x5B\\x5D-\\x7E]+)/g\n const results = [];\n let match = re.exec(this.value);\n while(match !== null) {\n results.push(match[0]);\n match = re.exec(this.value);\n }\n return results;\n }\n}\n\nclass ScopeAccessConfiguration extends ConfigurationStrategy {\n /**\n * @param {import('@themost/common').ConfigurationBase} configuration\n */\n constructor(configuration) {\n super(configuration);\n let elements = [];\n // define property\n Object.defineProperty(this, 'elements', {\n get: () => {\n return elements;\n },\n enumerable: true\n });\n }\n\n /**\n * @param {Request} req\n * @returns Promise<ScopeAccessConfigurationElement>\n */\n verify(req) {\n return new Promise((resolve, reject) => {\n try {\n // validate request context\n Args.notNull(req.context,'Context');\n // validate request context user\n Args.notNull(req.context.user,'User');\n if (req.context.user.authenticationScope && req.context.user.authenticationScope.length>0) {\n // get original url\n let reqUrl = url.parse(req.originalUrl).pathname;\n // get user context scopes as array e.g, ['students', 'students:read']\n let reqScopes = new ScopeString(req.context.user.authenticationScope).split();\n // get user access based on HTTP method e.g. GET -> read access\n let reqAccess = HTTP_METHOD_REGEXP.test(req.method) ? 'write' : 'read';\n let result = this.elements.find(x => {\n // filter element by access level\n return x.access.indexOf(reqAccess)>=0\n // resource path\n && new RegExp( '^' + x.resource, 'i').test(reqUrl)\n // and scopes\n && x.scope.find(y => {\n // search user scopes (validate wildcard scope)\n return y === '*' || reqScopes.indexOf(y)>=0;\n });\n });\n return resolve(result);\n }\n return resolve();\n }\n catch(err) {\n return reject(err);\n }\n\n });\n }\n\n}\n\n/**\n * @class\n */\nclass DefaultScopeAccessConfiguration extends ScopeAccessConfiguration {\n /**\n * @param {import('@themost/common').ConfigurationBase} configuration\n */\n constructor(configuration) {\n super(configuration);\n let defaults = [];\n // load scope access from configuration resource\n try {\n /**\n * @type {Array<ScopeAccessConfigurationElement>}\n */\n defaults = require(path.resolve(configuration.getConfigurationPath(), 'scope.access.json'));\n }\n catch(err) {\n // if an error occurred other than module not found (there are no default access policies)\n if (err.code !== 'MODULE_NOT_FOUND') {\n // throw error\n throw err;\n }\n // otherwise continue\n }\n this.elements.push.apply(this.elements, defaults);\n }\n}\n\nexport {\n ScopeString,\n ScopeAccessConfiguration,\n DefaultScopeAccessConfiguration\n}\n"],"mappings":"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"}
@@ -1,4 +0,0 @@
1
- import { ApplicationService } from '@themost/common';
2
- export declare class SpeedLimitService extends ApplicationService {
3
-
4
- }
@@ -1,113 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.SpeedLimitService = void 0;var _common = require("@themost/common");
2
- var _expressSlowDown = _interopRequireDefault(require("express-slow-down"));
3
- var _express = _interopRequireDefault(require("express"));
4
- var _path = _interopRequireDefault(require("path"));function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
5
-
6
- class SpeedLimitService extends _common.ApplicationService {
7
- constructor(app) {
8
- super(app);
9
-
10
- app.serviceRouter.subscribe((serviceRouter) => {
11
- if (serviceRouter == null) {
12
- return;
13
- }
14
- try {
15
- const addRouter = _express.default.Router();
16
- let serviceConfiguration = app.getConfiguration().getSourceAt('settings/universis/janitor/speedLimit') || {
17
- profiles: [],
18
- paths: []
19
- };
20
- if (serviceConfiguration.extends) {
21
- // get additional configuration
22
- const configurationPath = app.getConfiguration().getConfigurationPath();
23
- const extendsPath = _path.default.resolve(configurationPath, serviceConfiguration.extends);
24
- _common.TraceUtils.log(`@universis/janitor#SpeedLimitService will try to extend service configuration from ${extendsPath}`);
25
- serviceConfiguration = require(extendsPath);
26
- }
27
- const pathsArray = serviceConfiguration.paths || [];
28
- const profilesArray = serviceConfiguration.profiles || [];
29
- // create maps
30
- const paths = new Map(pathsArray);
31
- const profiles = new Map(profilesArray);
32
- if (paths.size === 0) {
33
- _common.TraceUtils.warn('@universis/janitor#SpeedLimitService is being started but the collection of paths is empty.');
34
- }
35
- // get proxy address forwarding option
36
- let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');
37
- if (typeof proxyAddressForwarding !== 'boolean') {
38
- proxyAddressForwarding = false;
39
- }
40
- paths.forEach((value, path) => {
41
- let profile;
42
- // get profile
43
- if (value.profile) {
44
- profile = profiles.get(value.profile);
45
- } else {
46
- // or options defined inline
47
- profile = value;
48
- }
49
- if (profile != null) {
50
- const slowDownOptions = Object.assign({
51
- windowMs: 5 * 60 * 1000, // 5 minutes
52
- delayAfter: 20, // 20 requests
53
- delayMs: 500, // 500 ms
54
- maxDelayMs: 10000 // 10 seconds
55
- }, profile, {
56
- keyGenerator: (req) => {
57
- let remoteAddress;
58
- if (proxyAddressForwarding) {
59
- // get proxy headers or remote address
60
- remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);
61
- } else {
62
- // get remote address
63
- remoteAddress = req.connection ? req.connection.remoteAddress : req.socket.remoteAddress;
64
- }
65
- return `${path}:${remoteAddress}`;
66
- }
67
- });
68
- if (Array.isArray(slowDownOptions.randomDelayMs)) {
69
- slowDownOptions.delayMs = () => {
70
- const delayMs = Math.floor(Math.random() * (slowDownOptions.randomDelayMs[1] - slowDownOptions.randomDelayMs[0] + 1) + slowDownOptions.randomDelayMs[0]);
71
- return delayMs;
72
- };
73
- }
74
- if (Array.isArray(slowDownOptions.randomMaxDelayMs)) {
75
- slowDownOptions.maxDelayMs = () => {
76
- const maxDelayMs = Math.floor(Math.random() * (slowDownOptions.randomMaxDelayMs[1] - slowDownOptions.randomMaxDelayMs[0] + 1) + slowDownOptions.randomMaxDelayMs[0]);
77
- return maxDelayMs;
78
- };
79
- }
80
- if (typeof slowDownOptions.store === 'string') {
81
- // load store
82
- const store = slowDownOptions.store.split('#');
83
- let StoreClass;
84
- if (store.length === 2) {
85
- const storeModule = require(store[0]);
86
- if (Object.prototype.hasOwnProperty.call(storeModule, store[1])) {
87
- StoreClass = storeModule[store[1]];
88
- slowDownOptions.store = new StoreClass(this, slowDownOptions);
89
- } else {
90
- throw new Error(`${store} cannot be found or is inaccessible`);
91
- }
92
- } else {
93
- StoreClass = require(store[0]);
94
- // create store
95
- slowDownOptions.store = new StoreClass(this, slowDownOptions);
96
- }
97
- }
98
- addRouter.use(path, (0, _expressSlowDown.default)(slowDownOptions));
99
- }
100
- });
101
- if (addRouter.stack.length) {
102
- serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);
103
- }
104
- } catch (err) {
105
- _common.TraceUtils.error('An error occurred while validating speed limit configuration.');
106
- _common.TraceUtils.error(err);
107
- _common.TraceUtils.warn('Speed limit service is inactive due to an error occured while loading configuration.');
108
- }
109
- });
110
- }
111
-
112
- }exports.SpeedLimitService = SpeedLimitService;
113
- //# sourceMappingURL=SpeedLimitService.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SpeedLimitService.js","names":["_common","require","_expressSlowDown","_interopRequireDefault","_express","_path","obj","__esModule","default","SpeedLimitService","ApplicationService","constructor","app","serviceRouter","subscribe","addRouter","express","Router","serviceConfiguration","getConfiguration","getSourceAt","profiles","paths","extends","configurationPath","getConfigurationPath","extendsPath","path","resolve","TraceUtils","log","pathsArray","profilesArray","Map","size","warn","proxyAddressForwarding","forEach","value","profile","get","slowDownOptions","Object","assign","windowMs","delayAfter","delayMs","maxDelayMs","keyGenerator","req","remoteAddress","headers","connection","socket","Array","isArray","randomDelayMs","Math","floor","random","randomMaxDelayMs","store","split","StoreClass","length","storeModule","prototype","hasOwnProperty","call","Error","use","slowDown","stack","unshift","apply","err","error","exports"],"sources":["../src/SpeedLimitService.js"],"sourcesContent":["import { ApplicationService, TraceUtils } from '@themost/common';\nimport slowDown from 'express-slow-down';\nimport express from 'express';\nimport path from 'path';\n\nexport class SpeedLimitService extends ApplicationService {\n constructor(app) {\n super(app);\n\n app.serviceRouter.subscribe(serviceRouter => {\n if (serviceRouter == null) {\n return;\n }\n try {\n const addRouter = express.Router();\n let serviceConfiguration = app.getConfiguration().getSourceAt('settings/universis/janitor/speedLimit') || {\n profiles: [],\n paths: []\n };\n if (serviceConfiguration.extends) {\n // get additional configuration\n const configurationPath = app.getConfiguration().getConfigurationPath();\n const extendsPath = path.resolve(configurationPath, serviceConfiguration.extends);\n TraceUtils.log(`@universis/janitor#SpeedLimitService will try to extend service configuration from ${extendsPath}`);\n serviceConfiguration = require(extendsPath);\n }\n const pathsArray = serviceConfiguration.paths || [];\n const profilesArray = serviceConfiguration.profiles || [];\n // create maps\n const paths = new Map(pathsArray);\n const profiles = new Map(profilesArray);\n if (paths.size === 0) {\n TraceUtils.warn('@universis/janitor#SpeedLimitService is being started but the collection of paths is empty.');\n }\n // get proxy address forwarding option\n let proxyAddressForwarding = app.getConfiguration().getSourceAt('settings/universis/api/proxyAddressForwarding');\n if (typeof proxyAddressForwarding !== 'boolean') {\n proxyAddressForwarding = false;\n }\n paths.forEach((value, path) => {\n let profile;\n // get profile\n if (value.profile) {\n profile = profiles.get(value.profile);\n } else {\n // or options defined inline\n profile = value\n }\n if (profile != null) {\n const slowDownOptions = Object.assign({\n windowMs: 5 * 60 * 1000, // 5 minutes\n delayAfter: 20, // 20 requests\n delayMs: 500, // 500 ms\n maxDelayMs: 10000 // 10 seconds\n }, profile, {\n keyGenerator: (req) => {\n let remoteAddress;\n if (proxyAddressForwarding) {\n // get proxy headers or remote address\n remoteAddress = req.headers['x-real-ip'] || req.headers['x-forwarded-for'] || (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n } else {\n // get remote address\n remoteAddress = (req.connection ? req.connection.remoteAddress : req.socket.remoteAddress);\n }\n return `${path}:${remoteAddress}`;\n }\n });\n if (Array.isArray(slowDownOptions.randomDelayMs)) {\n slowDownOptions.delayMs = () => {\n const delayMs = Math.floor(Math.random() * (slowDownOptions.randomDelayMs[1] - slowDownOptions.randomDelayMs[0] + 1) + slowDownOptions.randomDelayMs[0]);\n return delayMs;\n }\n }\n if (Array.isArray(slowDownOptions.randomMaxDelayMs)) {\n slowDownOptions.maxDelayMs = () => {\n const maxDelayMs = Math.floor(Math.random() * (slowDownOptions.randomMaxDelayMs[1] - slowDownOptions.randomMaxDelayMs[0] + 1) + slowDownOptions.randomMaxDelayMs[0]);\n return maxDelayMs;\n }\n }\n if (typeof slowDownOptions.store === 'string') {\n // load store\n const store = slowDownOptions.store.split('#');\n let StoreClass;\n if (store.length === 2) {\n const storeModule = require(store[0]);\n if (Object.prototype.hasOwnProperty.call(storeModule, store[1])) {\n StoreClass = storeModule[store[1]];\n slowDownOptions.store = new StoreClass(this, slowDownOptions);\n } else {\n throw new Error(`${store} cannot be found or is inaccessible`);\n }\n } else {\n StoreClass = require(store[0]);\n // create store\n slowDownOptions.store = new StoreClass(this, slowDownOptions);\n }\n }\n addRouter.use(path, slowDown(slowDownOptions));\n }\n });\n if (addRouter.stack.length) {\n serviceRouter.stack.unshift.apply(serviceRouter.stack, addRouter.stack);\n }\n } catch (err) {\n TraceUtils.error('An error occurred while validating speed limit configuration.');\n TraceUtils.error(err);\n TraceUtils.warn('Speed limit service is inactive due to an error occured while loading configuration.')\n }\n });\n }\n\n}"],"mappings":"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"}
package/dist/polyfills.js DELETED
@@ -1,11 +0,0 @@
1
- "use strict";if (!String.prototype.replaceAll) {
2
- String.prototype.replaceAll = function (str, newStr) {
3
- // If a regex pattern
4
- if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
5
- return this.replace(str, newStr);
6
- }
7
- // If a string
8
- return this.replace(new RegExp(str, 'g'), newStr);
9
- };
10
- }
11
- //# sourceMappingURL=polyfills.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"polyfills.js","names":["String","prototype","replaceAll","str","newStr","Object","toString","call","toLowerCase","replace","RegExp"],"sources":["../src/polyfills.js"],"sourcesContent":["if (!String.prototype.replaceAll) {\n\tString.prototype.replaceAll = function(str, newStr){\n\t\t// If a regex pattern\n\t\tif (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {\n\t\t\treturn this.replace(str, newStr);\n\t\t}\n\t\t// If a string\n\t\treturn this.replace(new RegExp(str, 'g'), newStr);\n\t};\n}"],"mappings":"aAAA,IAAI,CAACA,MAAM,CAACC,SAAS,CAACC,UAAU,EAAE;EACjCF,MAAM,CAACC,SAAS,CAACC,UAAU,GAAG,UAASC,GAAG,EAAEC,MAAM,EAAC;IAClD;IACA,IAAIC,MAAM,CAACJ,SAAS,CAACK,QAAQ,CAACC,IAAI,CAACJ,GAAG,CAAC,CAACK,WAAW,EAAE,KAAK,iBAAiB,EAAE;MAC5E,OAAO,IAAI,CAACC,OAAO,CAACN,GAAG,EAAEC,MAAM,CAAC;IACjC;IACA;IACA,OAAO,IAAI,CAACK,OAAO,CAAC,IAAIC,MAAM,CAACP,GAAG,EAAE,GAAG,CAAC,EAAEC,MAAM,CAAC;EAClD,CAAC;AACF"}
@@ -1,2 +0,0 @@
1
- import { Handler } from 'express';
2
- export declare function validateScope(): Handler;
@@ -1,23 +0,0 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.validateScope = validateScope;var _ScopeAccessConfiguration = require("./ScopeAccessConfiguration");
2
- var _common = require("@themost/common");
3
-
4
- function validateScope() {
5
- return (req, res, next) => {
6
- /**
7
- * @type {ScopeAccessConfiguration}
8
- */
9
- let scopeAccessConfiguration = req.context.getApplication().getConfiguration().getStrategy(_ScopeAccessConfiguration.ScopeAccessConfiguration);
10
- if (typeof scopeAccessConfiguration === 'undefined') {
11
- return next(new Error('Invalid application configuration. Scope access configuration strategy is missing or is in accessible.'));
12
- }
13
- scopeAccessConfiguration.verify(req).then((value) => {
14
- if (value) {
15
- return next();
16
- }
17
- return next(new _common.HttpForbiddenError('Access denied due to authorization scopes.'));
18
- }).catch((reason) => {
19
- return next(reason);
20
- });
21
- };
22
- }
23
- //# sourceMappingURL=validateScope.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validateScope.js","names":["_ScopeAccessConfiguration","require","_common","validateScope","req","res","next","scopeAccessConfiguration","context","getApplication","getConfiguration","getStrategy","ScopeAccessConfiguration","Error","verify","then","value","HttpForbiddenError","catch","reason"],"sources":["../src/validateScope.js"],"sourcesContent":["import { ScopeAccessConfiguration } from './ScopeAccessConfiguration';\nimport {HttpForbiddenError} from '@themost/common';\n\nfunction validateScope() {\n return (req, res, next) => {\n /**\n * @type {ScopeAccessConfiguration}\n */\n let scopeAccessConfiguration = req.context.getApplication().getConfiguration().getStrategy(ScopeAccessConfiguration);\n if (typeof scopeAccessConfiguration === 'undefined') {\n return next(new Error('Invalid application configuration. Scope access configuration strategy is missing or is in accessible.'));\n }\n scopeAccessConfiguration.verify(req).then(value => {\n if (value) {\n return next();\n }\n return next(new HttpForbiddenError('Access denied due to authorization scopes.'))\n }).catch(reason => {\n return next(reason);\n });\n };\n}\n\nexport {\n validateScope\n}\n"],"mappings":"iHAAA,IAAAA,yBAAA,GAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;;AAEA,SAASE,aAAaA,CAAA,EAAG;EACrB,OAAO,CAACC,GAAG,EAAEC,GAAG,EAAEC,IAAI,KAAK;IACvB;AACR;AACA;IACQ,IAAIC,wBAAwB,GAAGH,GAAG,CAACI,OAAO,CAACC,cAAc,EAAE,CAACC,gBAAgB,EAAE,CAACC,WAAW,CAACC,kDAAwB,CAAC;IACpH,IAAI,OAAOL,wBAAwB,KAAK,WAAW,EAAE;MACjD,OAAOD,IAAI,CAAC,IAAIO,KAAK,CAAC,wGAAwG,CAAC,CAAC;IACpI;IACAN,wBAAwB,CAACO,MAAM,CAACV,GAAG,CAAC,CAACW,IAAI,CAAC,CAAAC,KAAK,KAAI;MAC/C,IAAIA,KAAK,EAAE;QACP,OAAOV,IAAI,EAAE;MACjB;MACA,OAAOA,IAAI,CAAC,IAAIW,0BAAkB,CAAC,4CAA4C,CAAC,CAAC;IACrF,CAAC,CAAC,CAACC,KAAK,CAAC,CAAAC,MAAM,KAAI;MACf,OAAOb,IAAI,CAACa,MAAM,CAAC;IACvB,CAAC,CAAC;EACN,CAAC;AACL"}