not-node 5.1.42 → 5.1.45

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.
package/.eslintrc.json CHANGED
@@ -1,42 +1,36 @@
1
1
  {
2
- "parserOptions": {
3
- "requireConfigFile": false,
4
- "sourceType": "module",
5
- "allowImportExportEverywhere": false,
6
- "ecmaFeatures": {
7
- "globalReturn": false
2
+ "parserOptions": {
3
+ "requireConfigFile": false,
4
+ "sourceType": "module",
5
+ "allowImportExportEverywhere": false,
6
+ "ecmaFeatures": {
7
+ "globalReturn": false
8
+ },
9
+ "ecmaVersion": "latest"
8
10
  },
9
- "ecmaVersion": "latest"
10
- },
11
- "env": {
12
- "es6": true,
13
- "node": true,
14
- "mongo": true,
15
- "mocha": true
16
- },
17
- "extends": [
18
- "eslint:recommended",
19
- "plugin:node/recommended",
20
- "plugin:sonarjs/recommended"
21
- ],
22
- "rules": {
23
- "node/exports-style": ["error", "module.exports"],
24
- "node/file-extension-in-import": ["error", "always"],
25
- "node/prefer-global/buffer": ["error", "always"],
26
- "node/prefer-global/console": ["error", "always"],
27
- "node/prefer-global/process": ["error", "always"],
28
- "node/prefer-global/url-search-params": ["error", "always"],
29
- "node/prefer-global/url": ["error", "always"],
30
- "node/no-unpublished-require": "warn",
31
- "indent": ["error", 4],
32
- "linebreak-style": [
33
- "error",
34
- "unix"
35
- ],
36
- "semi": [
37
- "error",
38
- "always"
11
+ "env": {
12
+ "es6": true,
13
+ "node": true,
14
+ "mongo": true,
15
+ "mocha": true
16
+ },
17
+ "extends": [
18
+ "eslint:recommended",
19
+ "plugin:node/recommended",
20
+ "plugin:sonarjs/recommended"
39
21
  ],
40
- "no-useless-escape": [0]
41
- }
22
+ "rules": {
23
+ "node/exports-style": ["error", "module.exports"],
24
+ "node/file-extension-in-import": ["error", "always"],
25
+ "node/prefer-global/buffer": ["error", "always"],
26
+ "node/prefer-global/console": ["error", "always"],
27
+ "node/prefer-global/process": ["error", "always"],
28
+ "node/prefer-global/url-search-params": ["error", "always"],
29
+ "node/prefer-global/url": ["error", "always"],
30
+ "node/no-unpublished-require": "warn",
31
+ "indent": ["error", 4, { "SwitchCase": 1 }],
32
+ "linebreak-style": ["error", "unix"],
33
+ "semi": ["error", "always"],
34
+ "no-useless-escape": [0]
35
+ }
42
36
  }
package/index.js CHANGED
@@ -11,6 +11,8 @@ module.exports.Error = require("./src/error.js");
11
11
  module.exports.Auth = require("./src/auth");
12
12
  /** Manifest infrastructure */
13
13
  module.exports.Manifest = require("./src/manifest/manifest");
14
+ /** Request result properties filtering */
15
+ module.exports.notManifestRouteResultFilter = require("./src/manifest/result.filter");
14
16
  /** Web Application */
15
17
  module.exports.notApp = require("./src/app");
16
18
  /** General Application */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "not-node",
3
- "version": "5.1.42",
3
+ "version": "5.1.45",
4
4
  "description": "node complimentary part for client side notFramework.",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -46,7 +46,7 @@
46
46
  "express-fileupload": "^1.4.0",
47
47
  "express-session": "^1.17.3",
48
48
  "fs-extra": "*",
49
- "helmet": "^5.1.0",
49
+ "helmet": "^6.0.0",
50
50
  "lower-case": "*",
51
51
  "method-override": "^3.0.0",
52
52
  "mock-require": "^3.0.3",
@@ -60,10 +60,10 @@
60
60
  "not-locale": "*",
61
61
  "not-log": "^0.0.20",
62
62
  "not-monitor": "^0.0.13",
63
- "not-path": "*",
63
+ "not-path": "^1.0.4",
64
64
  "not-validation": "^0.0.8",
65
- "rate-limiter-flexible": "^2.3.7",
66
- "redis": "^4.1.1",
65
+ "rate-limiter-flexible": "^2.3.9",
66
+ "redis": "^4.3.1",
67
67
  "redlock": "^5.0.0-beta.2",
68
68
  "rfdc": "^1.3.0",
69
69
  "rmdir": "^1.2.0",
@@ -76,15 +76,15 @@
76
76
  "babel-eslint": "^10.1.0",
77
77
  "chai": "*",
78
78
  "chai-as-promised": "*",
79
- "eslint": "^8.18.0",
79
+ "eslint": "^8.23.0",
80
80
  "eslint-plugin-node": "^11.1.0",
81
- "eslint-plugin-sonarjs": "^0.13.0",
81
+ "eslint-plugin-sonarjs": "^0.15.0",
82
82
  "ink-docstrap": "^1.3.2",
83
- "ioredis": "^5.1.0",
84
- "jsdoc": "^3.6.10",
83
+ "ioredis": "^5.2.3",
84
+ "jsdoc": "^3.6.11",
85
85
  "mocha": "*",
86
86
  "mocha-suppress-logs": "^0.3.1",
87
- "mongodb-memory-server": "^8.7.2",
87
+ "mongodb-memory-server": "^8.9.1",
88
88
  "npm-run-all": "^4.1.5",
89
89
  "nyc": "^15.1.0",
90
90
  "retire": "^3.0.7"
@@ -126,4 +126,4 @@
126
126
  ]
127
127
  }
128
128
  }
129
- }
129
+ }
@@ -35,7 +35,7 @@ module.exports = class InitApp {
35
35
 
36
36
  static async initCore({ config, options, master, emit }) {
37
37
  await emit("app.initCore.pre", { config, options, master });
38
- master.getApp().importModuleFrom(path.join(__dirname, "../core"));
38
+ master.getApp().importModuleFrom(path.join(__dirname, "../../core"));
39
39
  await emit("app.initCore.post", { config, options, master });
40
40
  }
41
41
 
@@ -0,0 +1,268 @@
1
+ const notPath = require("not-path");
2
+ const { objHas, copyObj } = require("../common");
3
+
4
+ const PROP_NAME_RETURN_ROOT = "returnRoot"; //path to object to filter
5
+ const PROP_NAME_RETURN_RULE = "return"; //filtering rule
6
+ const PROP_NAME_RETURN_STRICT = "returnStrict"; //if filtering should be strict
7
+
8
+ /**
9
+ * @const {boolean} DEFAULT_STRICT_MODE
10
+ * active only in complex rules presented as objects
11
+ * defines if filtering should exclude any not mentioned property and sub property in map object
12
+ * Example:
13
+ * target structure =
14
+ * {
15
+ * id,
16
+ * user:{
17
+ * id,
18
+ * username,
19
+ * aliases: [
20
+ * {id, title, createdAt},
21
+ * {id, title, createdAt, banned}
22
+ * ],
23
+ * createdAt
24
+ * },
25
+ * clean
26
+ * }
27
+ * rule object =
28
+ * {
29
+ * id,
30
+ * 'user.aliases': ['id', 'title', 'banned']
31
+ * }
32
+ * in strict==true
33
+ * filtered target structure =
34
+ * {
35
+ * id,
36
+ * user:{
37
+ * aliases: [
38
+ * {id, title},
39
+ * {id, title, banned}
40
+ * ]
41
+ * }
42
+ * }
43
+ * in strict==false
44
+ * filtered target structure = {
45
+ * id,
46
+ * user:{
47
+ * id,
48
+ * username,
49
+ * aliases: [
50
+ * {id, title},
51
+ * {id, title, banned}
52
+ * ],
53
+ * createdAt
54
+ * }
55
+ * }
56
+ */
57
+ const DEFAULT_STRICT_MODE = false;
58
+
59
+ module.exports = class notManifestRouteResultFilter {
60
+ /**
61
+ * Removes fields from result object acctoding to actionData.return array
62
+ * if presented
63
+ * @param {object} notRouteData request rules and preferencies
64
+ * @param {object} result result returned by main action processor
65
+ */
66
+ static filter(notRouteData, result) {
67
+ if (!(result && typeof result === "object")) return;
68
+ const filteringRule = this.getFilteringRule(notRouteData);
69
+ if (!filteringRule) return;
70
+ const filteringTarget = this.getFilteringTarget(result, notRouteData);
71
+ if (!filteringTarget) {
72
+ return;
73
+ }
74
+ this.filterByRule(
75
+ filteringTarget,
76
+ filteringRule,
77
+ this.getFilteringStrictMode(notRouteData)
78
+ );
79
+ return result;
80
+ }
81
+
82
+ /**
83
+ * modifies target according to rule
84
+ * @param {object} target object which properties should be filtered
85
+ * @param {array} rule filtering rule
86
+ * @param {boolean} strict filtering mode
87
+ */
88
+
89
+ static filterByRule(target, rule, strict = DEFAULT_STRICT_MODE) {
90
+ if (!rule || !target) {
91
+ return;
92
+ }
93
+ if (Array.isArray(rule)) {
94
+ this.filterByArrayRule(target, rule); //flat map always strict==true
95
+ } else if (typeof rule === "object") {
96
+ this.filterByMapRule(target, rule, strict); //object map strict could vary
97
+ }
98
+ }
99
+
100
+ /**
101
+ * filters target by rule.
102
+ * Rule form: {pathToProperty: filteringRuleArray, pathToProperty: filteringRuleMap }
103
+ * pathToProperty should be in notPath notation except starting symbol (default: ':')
104
+ * if pathToProperty targets array in target, each item of array will be filtered by
105
+ * @param {object} target
106
+ * @param {object} rule map of properties.
107
+ * @param {boolean} strict filtering mode
108
+ * example:
109
+ * {
110
+ * 'user': ['username', 'id', 'email'], //filtering properties of object target.user
111
+ * 'posts': ['id', 'title'], //filtering properties of array of objects target.posts
112
+ * 'friends.list': ['id', 'username'] //filtering props of array of objects target.friends.list by path.
113
+ * //if strict==false: will not drop any from friends.*, only friends.list cotent will be processed
114
+ * //if strict==true: will drop all properties of friends except list
115
+ * 'friends': { //this will clear friends sub-object from any properties except 'list' in any strict mode
116
+ * 'list': ['id', 'username'] //and filter 'list' items
117
+ * },
118
+ * 'storage': { //filtering complex sub object by map
119
+ * 'files':{
120
+ * 'cloud': ['id','title'],
121
+ * 'local': ['id', 'title', 'size']
122
+ * }
123
+ * }
124
+ * }
125
+ */
126
+ static filterByMapRule(target, rule, strict = DEFAULT_STRICT_MODE) {
127
+ //to form ['id', 'user.username', 'files']
128
+ const filteringArray = Object.keys(rule);
129
+ //filtering direct chilren if in strict mode
130
+ if (strict) {
131
+ this.filterStrict(target, filteringArray);
132
+ }
133
+ //filter properties
134
+ for (let filteringTargetName of filteringArray) {
135
+ const subTarget = notPath.get(
136
+ `${notPath.PATH_START_OBJECT}${filteringTargetName}`,
137
+ target
138
+ );
139
+ //if sub target Array filtering each item individualy
140
+ if (Array.isArray(subTarget)) {
141
+ subTarget.forEach((subTargetItem) => {
142
+ this.filterByRule(
143
+ subTargetItem,
144
+ rule[filteringTargetName],
145
+ strict
146
+ );
147
+ });
148
+ } else if (typeof subTarget == "object") {
149
+ this.filterByRule(subTarget, rule[filteringTargetName], strict);
150
+ }
151
+ }
152
+ }
153
+
154
+ static filterStrict(target, filteringArray) {
155
+ console.log(target, filteringArray);
156
+ //to form ['id', 'user', 'files']
157
+ const filteringArrayDirectChildren = filteringArray.map(
158
+ (propName) => propName.split(notPath.PATH_SPLIT)[0]
159
+ );
160
+ //filter strict direct children
161
+ this.filterByArrayRule(target, filteringArrayDirectChildren);
162
+ //filter strict each level in props paths in filteringArray
163
+ for (let path of filteringArray) {
164
+ let pathParts = path.split(notPath.PATH_SPLIT);
165
+ if (pathParts.length === 1) {
166
+ continue;
167
+ }
168
+ //property name in which we will clean content except pathParts[1]
169
+ const directPropName = pathParts.shift();
170
+ //
171
+ const subTarget = target[directPropName];
172
+ if (Array.isArray(subTarget)) continue;
173
+ const subFilteringArray = [pathParts.join(notPath.PATH_SPLIT)];
174
+ this.filterStrict(subTarget, subFilteringArray);
175
+ }
176
+ }
177
+
178
+ /**
179
+ * filters target properties by rule, all properties which names are not presented in rule
180
+ * array will be removed from target
181
+ * @param {object} target object to filter
182
+ * @param {Array} rule list of enabled properties. example: ['id', 'title', 'createdAt']
183
+ */
184
+ static filterByArrayRule(target, rule) {
185
+ const presented = Object.keys(target);
186
+ presented.forEach((fieldName) => {
187
+ if (!rule.includes(fieldName)) {
188
+ delete target[fieldName];
189
+ }
190
+ });
191
+ }
192
+
193
+ /**
194
+ * returns filtering rule object or undefined
195
+ * @param {object} notRouteData
196
+ * @returns {object|Array|undefined} rule to filter result object properties
197
+ */
198
+ static getFilteringRule(notRouteData) {
199
+ if (objHas(notRouteData.rule, PROP_NAME_RETURN_RULE)) {
200
+ return copyObj(notRouteData.rule[PROP_NAME_RETURN_RULE]);
201
+ } else if (objHas(notRouteData.actionData, PROP_NAME_RETURN_RULE)) {
202
+ return copyObj(notRouteData.actionData[PROP_NAME_RETURN_RULE]);
203
+ } else {
204
+ return undefined;
205
+ }
206
+ }
207
+
208
+ /**
209
+ * Returns path to sub object which properties should be filtered
210
+ * @param {object} notRouteData
211
+ * @returns {string} path of sub object in notPath notation
212
+ */
213
+ static getFilteringTargetPath(notRouteData) {
214
+ let path = notPath.PATH_START_OBJECT;
215
+ if (notRouteData) {
216
+ if (objHas(notRouteData.rule, PROP_NAME_RETURN_ROOT)) {
217
+ path += notRouteData.rule[PROP_NAME_RETURN_ROOT];
218
+ } else if (objHas(notRouteData.actionData, PROP_NAME_RETURN_ROOT)) {
219
+ path += notRouteData.actionData[PROP_NAME_RETURN_ROOT];
220
+ }
221
+ }
222
+ return path;
223
+ }
224
+
225
+ /**
226
+ * Returns object which properties should be filtered
227
+ * @param {object} result request result
228
+ * @param {object} notRouteData request route rules and prefs
229
+ * @returns {object} object to filter
230
+ */
231
+ static getFilteringTarget(result, notRouteData) {
232
+ if (result && typeof result == "object") {
233
+ const returnListRoot = this.getFilteringTargetPath(notRouteData);
234
+ return notPath.get(returnListRoot, result);
235
+ } else {
236
+ return result;
237
+ }
238
+ }
239
+
240
+ static getFilteringStrictMode(notRouteData) {
241
+ if (notRouteData) {
242
+ if (objHas(notRouteData.rule, PROP_NAME_RETURN_STRICT)) {
243
+ return !!notRouteData.rule[PROP_NAME_RETURN_STRICT];
244
+ } else if (
245
+ objHas(notRouteData.actionData, PROP_NAME_RETURN_STRICT)
246
+ ) {
247
+ return !!notRouteData.actionData[PROP_NAME_RETURN_STRICT];
248
+ }
249
+ }
250
+ return this.DEFAULT_STRICT_MODE;
251
+ }
252
+
253
+ static get PROP_NAME_RETURN_ROOT() {
254
+ return PROP_NAME_RETURN_ROOT;
255
+ }
256
+
257
+ static get PROP_NAME_RETURN_RULE() {
258
+ return PROP_NAME_RETURN_RULE;
259
+ }
260
+
261
+ static get PROP_NAME_RETURN_STRICT() {
262
+ return PROP_NAME_RETURN_STRICT;
263
+ }
264
+
265
+ static get DEFAULT_STRICT_MODE() {
266
+ return DEFAULT_STRICT_MODE;
267
+ }
268
+ };
@@ -2,10 +2,12 @@ const CONST_BEFORE_ACTION = "before";
2
2
  const CONST_AFTER_ACTION = "after";
3
3
 
4
4
  const obsoleteWarning = require("../obsolete");
5
+
5
6
  const Auth = require("../auth"),
6
7
  HttpError = require("../error").Http;
7
8
 
8
- const { objHas, copyObj, executeObjectFunction } = require("../common");
9
+ const notManifestRouteResultFilter = require("./result.filter");
10
+ const { copyObj, executeObjectFunction } = require("../common");
9
11
 
10
12
  /**
11
13
  * Route representation
@@ -171,39 +173,6 @@ class notRoute {
171
173
  );
172
174
  }
173
175
 
174
- extractReturn(notRouteData) {
175
- if (objHas(notRouteData.rule, "return")) {
176
- return [...notRouteData.rule.return];
177
- } else if (objHas(notRouteData.actionData, "return")) {
178
- return [...notRouteData.actionData.return];
179
- } else {
180
- return undefined;
181
- }
182
- }
183
-
184
- /**
185
- * Removes fields from result object acctoding to actionData.return array
186
- * if presented
187
- * @param {ExpressRequest} req request object
188
- * @param {object} result result returned by main action processor
189
- */
190
- filterResultByReturnRule(req, result) {
191
- const returnList = this.extractReturn(req.notRouteData);
192
- if (
193
- result &&
194
- typeof result === "object" &&
195
- returnList &&
196
- Array.isArray(returnList)
197
- ) {
198
- let presented = Object.keys(result);
199
- presented.forEach((fieldName) => {
200
- if (!returnList.includes(fieldName)) {
201
- delete result[fieldName];
202
- }
203
- });
204
- }
205
- }
206
-
207
176
  async executeRoute(modRoute, actionName, { req, res, next }) {
208
177
  try {
209
178
  //waiting preparation
@@ -220,7 +189,7 @@ class notRoute {
220
189
  prepared,
221
190
  ]);
222
191
  //filter result IF actionData.return specified
223
- this.filterResultByReturnRule(req, result);
192
+ notManifestRouteResultFilter.filter(req.notRouteData, result);
224
193
  //run after with results, continue without waiting when it finished
225
194
  return this.executeFunction(modRoute, CONST_AFTER_ACTION, [
226
195
  req,
@@ -112,7 +112,6 @@ class ModelRoutine {
112
112
  );
113
113
  if (updateResult) {
114
114
  result = await ModelConstructor.saveVersion(
115
- ModelConstructor,
116
115
  updateResult._id
117
116
  );
118
117
  } else {