not-node 6.3.0 → 6.3.2

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.
Files changed (50) hide show
  1. package/index.js +2 -0
  2. package/package.json +2 -2
  3. package/src/auth/const.js +17 -0
  4. package/src/auth/fields.js +10 -5
  5. package/src/auth/roles.js +2 -2
  6. package/src/auth/rules.js +49 -13
  7. package/src/bootstrap/logic.js +12 -11
  8. package/src/bootstrap/route.js +1 -1
  9. package/src/common.js +7 -0
  10. package/src/fields/filter.js +326 -0
  11. package/src/fields/index.js +2 -2
  12. package/src/form/env_extractors/activeUser.js +1 -1
  13. package/src/form/env_extractors/activeUserId.js +6 -0
  14. package/src/form/env_extractors/index.js +3 -0
  15. package/src/form/env_extractors/query.js +6 -0
  16. package/src/form/fabric.js +3 -3
  17. package/src/form/form.js +37 -10
  18. package/src/generic/form.authorizedAction.js +6 -8
  19. package/src/generic/form.getByID.js +8 -10
  20. package/src/generic/form.getById.js +8 -9
  21. package/src/generic/form.listAndCount.js +28 -26
  22. package/src/generic/logic.js +31 -85
  23. package/src/identity/index.js +6 -2
  24. package/src/identity/providers/session.js +14 -12
  25. package/src/identity/providers/token.js +14 -7
  26. package/src/init/lib/sessions/index.js +1 -1
  27. package/src/manifest/manifest.filter.js +118 -17
  28. package/src/manifest/manifest.js +8 -2
  29. package/src/manifest/module.js +21 -16
  30. package/src/manifest/registrator/fields.js +8 -1
  31. package/src/manifest/registrator/forms.js +1 -0
  32. package/src/manifest/registrator/locales.js +9 -1
  33. package/src/manifest/registrator/logics.js +2 -2
  34. package/src/manifest/registrator/models.js +2 -2
  35. package/src/manifest/registrator/routes.js +8 -8
  36. package/src/manifest/result.filter.js +3 -2
  37. package/src/manifest/route.js +42 -14
  38. package/src/model/default.js +1 -1
  39. package/src/model/proto.js +1 -1
  40. package/src/obsolete.js +23 -7
  41. package/src/types.js +83 -0
  42. package/test/auth/fields.js +2 -2
  43. package/test/auth/obsolete.js +16 -9
  44. package/test/extractors.js +60 -0
  45. package/test/filter.js +286 -0
  46. package/test/init/sessions.js +14 -2
  47. package/test/notManifestFilter.js +358 -19
  48. package/test/notModule.js +41 -1
  49. package/test/transformers.js +21 -0
  50. package/tmpl/files/module.server/layers/routes.manifest.ejs +9 -0
@@ -1,7 +1,7 @@
1
1
  const CONST_BEFORE_ACTION = "before";
2
2
  const CONST_AFTER_ACTION = "after";
3
3
 
4
- const obsoleteWarning = require("../obsolete");
4
+ const { obsoleteRuleFields, obsoleteActionFields } = require("../obsolete");
5
5
 
6
6
  const notAppIdentity = require("../identity");
7
7
  const Auth = require("../auth"),
@@ -32,17 +32,22 @@ class notRoute {
32
32
  /**
33
33
  * Cycle throu rules of action and checking user credentials against them
34
34
  * If user creds comply to some rule - returns copy of rule
35
- * @param {object} action action rules object
35
+ * @param {import('../types').notActionData & import('../types').notRouteRule } action action rules object
36
36
  * @param {object} user user credentials (auth, role, root)
37
37
  * @return {object|null} returns rule or null
38
38
  **/
39
- static actionAvailableByRule(action, user) {
39
+ static actionAvailableByRule(action, user, url = "") {
40
40
  if (!action) {
41
41
  return null;
42
42
  }
43
- if (Array.isArray(action.rules) && action.rules.length > 0) {
43
+ if (
44
+ action.rules &&
45
+ Array.isArray(action.rules) &&
46
+ action.rules.length > 0
47
+ ) {
44
48
  return notRoute.cycleThruRules(action.rules, user);
45
49
  } else {
50
+ obsoleteActionFields(action, url);
46
51
  if (
47
52
  Auth.checkCredentials(action, user.auth, user.role, user.root)
48
53
  ) {
@@ -54,7 +59,7 @@ class notRoute {
54
59
 
55
60
  static cycleThruRules(rules, user, url = "") {
56
61
  for (let i = 0; i < rules.length; i++) {
57
- obsoleteWarning(rules[i], url);
62
+ obsoleteRuleFields(rules[i], url);
58
63
  if (
59
64
  Auth.checkCredentials(rules[i], user.auth, user.role, user.root)
60
65
  ) {
@@ -66,8 +71,8 @@ class notRoute {
66
71
 
67
72
  /**
68
73
  * Select rule from available or return null
69
- * @param {object} req Express Request Object
70
- * @return {object} rule or null
74
+ * @param {import('../types').ExtendedExpressRequest} req Express Request Object
75
+ * @return {import('../types').notRouteRule | null} rule or null
71
76
  */
72
77
  selectRule(req) {
73
78
  const user = notAppIdentity.extractAuthData(req);
@@ -77,8 +82,27 @@ class notRoute {
77
82
  return null;
78
83
  }
79
84
 
80
- setRequestRouteData(req, actionName, rule) {
81
- req.notRouteData = {
85
+ /**
86
+ *
87
+ *
88
+ * @param {import('../types').ExtendedExpressRequest} req
89
+ * @param {import('../types').notRouteData} notRouteData
90
+ * @memberof notRoute
91
+ */
92
+ setRequestRouteData(req, notRouteData) {
93
+ req.notRouteData = notRouteData;
94
+ }
95
+
96
+ /**
97
+ *
98
+ *
99
+ * @param {string} actionName
100
+ * @param {import('../types').notRouteRule} rule
101
+ * @return {import('../types').notRouteData}
102
+ * @memberof notRoute
103
+ */
104
+ createRequestRouteData(actionName, rule) {
105
+ return {
82
106
  actionName,
83
107
  modelName: this.routeName,
84
108
  rule: copyObj(rule),
@@ -88,9 +112,9 @@ class notRoute {
88
112
 
89
113
  /**
90
114
  * Executes route action if such exist
91
- * @param {object} req Express Request Object
92
- * @param {object} res Express Response Object
93
- * @param {function} callback
115
+ * @param {import('../types').ExtendedExpressRequest} req Express Request Object
116
+ * @param {import('express').Response} res Express Response Object
117
+ * @param {function} next
94
118
  * @return {object} result of execution or HttpError
95
119
  **/
96
120
  exec(req, res, next) {
@@ -109,7 +133,7 @@ class notRoute {
109
133
  );
110
134
  }
111
135
  console.log(rule);
112
- obsoleteWarning(rule, req.originalUrl);
136
+ obsoleteRuleFields(rule, req.originalUrl);
113
137
  let actionName = this.selectActionName(rule);
114
138
  let mod = this.notApp.getModule(this.moduleName);
115
139
  if (!mod) {
@@ -126,7 +150,10 @@ class notRoute {
126
150
  );
127
151
  }
128
152
  let modRoute = mod.getRoute(this.routeName);
129
- this.setRequestRouteData(req, actionName, rule);
153
+ this.setRequestRouteData(
154
+ req,
155
+ this.createRequestRouteData(actionName, rule)
156
+ );
130
157
  if (this.routeIsRunnable(modRoute, actionName)) {
131
158
  return this.executeRoute(modRoute, actionName, {
132
159
  req,
@@ -148,6 +175,7 @@ class notRoute {
148
175
  }
149
176
  } catch (e) {
150
177
  this.notApp.report(e);
178
+ next(e);
151
179
  }
152
180
  }
153
181
 
@@ -327,7 +327,7 @@ function countWithFilter(filter) {
327
327
  * Starts add routine
328
328
  * @static
329
329
  * @param {object} data data
330
- * @return {Promise<MongooseDocument>} Promise of saved document
330
+ * @return {Promise<import('mongoose').Document>} Promise of saved document
331
331
  */
332
332
  function add(data) {
333
333
  return routine.add(this, data);
@@ -164,7 +164,7 @@ module.exports = class ModelFabricate {
164
164
  //creating unique indexes
165
165
  ModelFabricate.createIndexesForFields(schema, fieldsForIndexes);
166
166
  ModelFabricate.createIndexesForText(schema, targetModule);
167
- //adding specific fields and indetificators
167
+ //adding specific fields and identificators
168
168
  ModelFabricate.markFor(schema, targetModule);
169
169
  //extending schema methods, statics, virtuals by user defined and default content
170
170
  ModelFabricate.extendBySource(schema, targetModule);
package/src/obsolete.js CHANGED
@@ -1,14 +1,30 @@
1
1
  const log = require("not-log")(module, "Auth");
2
2
 
3
- module.exports = function (rule, url = "") {
3
+ const obsoleteRuleFields = function (rule, url = "") {
4
4
  if (Object.prototype.hasOwnProperty.call(rule, "user")) {
5
- log.error(
6
- `Missformed rule, field "user" is not allowed, use "auth" instead: ${url}`
7
- );
5
+ log &&
6
+ log.error(
7
+ `Missformed rule, field "user" is not allowed, use "auth" instead: ${url}`
8
+ );
8
9
  }
9
10
  if (Object.prototype.hasOwnProperty.call(rule, "admin")) {
10
- log.error(
11
- `Missformed rule, field "admin" is obsolete, use "root" instead: ${url}`
12
- );
11
+ log &&
12
+ log.error(
13
+ `Missformed rule, field "admin" is obsolete, use "root" instead: ${url}`
14
+ );
13
15
  }
14
16
  };
17
+
18
+ const obsoleteActionFields = function (action, url = "") {
19
+ if (!Object.prototype.hasOwnProperty.call(action, "rules")) {
20
+ log &&
21
+ log.error(
22
+ `Missformed action, access rule should be moved to object inside property 'rules' (array<object>): ${url}`
23
+ );
24
+ }
25
+ };
26
+
27
+ module.exports = {
28
+ obsoleteRuleFields,
29
+ obsoleteActionFields,
30
+ };
package/src/types.js ADDED
@@ -0,0 +1,83 @@
1
+ /**
2
+ * @typedef {object} Query
3
+ * @property {number} skip
4
+ * @property {number} size
5
+ * @property {object} sorter
6
+ * @property {object} [filter]
7
+ * @property {string} [search]
8
+ */
9
+
10
+ /**
11
+ * @typedef {Object} PreparedData
12
+ * @property {Object} [data]
13
+ * @property {string} [action]
14
+ * @property {Query} [query]
15
+ * @property {number} [targetID] target item ID
16
+ * @property {Object} [activeUser] current user info
17
+ * @property {import('mongoose').Types.ObjectId} [activeUserId] current user document objectId
18
+ * @property {import('mongoose').Types.ObjectId} [targetId] target item objectId
19
+ * @property {string} [ip] current user ip
20
+ * @property {boolean} [root] current user is root
21
+ * @property {boolean} [shouldOwn] if user should be owner of targ
22
+ *
23
+ */
24
+
25
+ /**
26
+ * @typedef {object} notRouteRule
27
+ * @property {string} [actionName]
28
+ * @property {string} [actionPrefix]
29
+ * @property {string} [actionSignature]
30
+ * @property {boolean} [root]
31
+ * @property {boolean} [admin]
32
+ * @property {string|Array<string>} [role]
33
+ * @property {boolean} [safe]
34
+ * @property {boolean} [auth]
35
+ * @property {boolean} [user]
36
+ * @property {Array<string | Array<string>>} [fields]
37
+ * @property {Array<string>} [return]
38
+ */
39
+
40
+ /**
41
+ * @typedef {object} notActionData
42
+ * @property {string} [method]
43
+ * @property {string} [actionSignature]
44
+ * @property {string} [postFix]
45
+ * @property {Array<notRouteRule>} rules
46
+ * @property {boolean} [ws]
47
+ * @property {Array<string & Array<string>>} [fields]
48
+ * @property {Array<string>} [return]
49
+ * @property {boolean} [isArray]
50
+ * @property {Array<string>} [data]
51
+ * @property {string} [title]
52
+ */
53
+
54
+ /**
55
+ * @typedef {Object} notRouteData
56
+ * @property {string} actionName
57
+ * @property {string} modelName
58
+ * @property {notRouteRule} rule
59
+ * @property {notActionData} actionData
60
+ */
61
+
62
+ /**
63
+ * @typedef {object} notUserDocumentProperties
64
+ * @property {import('mongoose').Types.ObjectId} _id
65
+ * @property {function} isRoot
66
+ * @property {function} isAdmin
67
+ */
68
+
69
+ /**
70
+ * @typedef {import('mongoose').Document & notUserDocumentProperties} notUserDocument
71
+ */
72
+
73
+ /**
74
+ * @typedef {object} notNodeExpressRequestProperties
75
+ * @property {notRouteData} notRouteData
76
+ * @property {notUserDocument} user
77
+ */
78
+
79
+ /**
80
+ * @typedef {import('express').Request & notNodeExpressRequestProperties} notNodeExpressRequest
81
+ */
82
+
83
+ module.exports = {};
@@ -156,7 +156,7 @@ module.exports = ({ Auth, expect }) => {
156
156
  expect(result).to.deep.equal(false);
157
157
  });
158
158
 
159
- it("field.safe.action:Array<string> with special, action:string, roles:Array<string>, special:Array<string>", () => {
159
+ it("field.safe.action:Array<string> with special, action:string, roles:Array<string>, special:Array<string> = ['@owner']", () => {
160
160
  const field = {
161
161
  safe: {
162
162
  update: ["root", "@owner"],
@@ -169,7 +169,7 @@ module.exports = ({ Auth, expect }) => {
169
169
  expect(result).to.deep.equal(true);
170
170
  });
171
171
 
172
- it("field.safe.action:Array<string> with special, action:string, roles:Array<string>, special:Array<string>", () => {
172
+ it("field.safe.action:Array<string> with special, action:string, roles:Array<string>, special:Array<string> = ['@system']", () => {
173
173
  const field = {
174
174
  safe: {
175
175
  update: ["root", "@owner"],
@@ -1,13 +1,20 @@
1
- const obsolete = require('../../src/obsolete');
1
+ const obsolete = require("../../src/obsolete");
2
2
  module.exports = () => {
3
- describe('Obsolete params warnings', () => {
4
- it('user', ()=>{
5
- const obj = {
6
- user: false
7
- };
8
- obsolete(obj);
3
+ describe("Obsolete rules params warnings", () => {
4
+ it("'user' field presented", () => {
5
+ const obj = {
6
+ user: false,
7
+ };
8
+ obsolete.obsoleteRuleFields(obj);
9
+ });
9
10
  });
10
11
 
11
- });
12
-
12
+ describe("Obsolete action params warnings", () => {
13
+ it("'rules' field not presented", () => {
14
+ const obj = {
15
+ user: false,
16
+ };
17
+ obsolete.obsoleteActionFields(obj);
18
+ });
19
+ });
13
20
  };
@@ -0,0 +1,60 @@
1
+ const expect = require("chai").expect,
2
+ extractors = require("../src/form/extractors");
3
+
4
+ describe("Form//Extractors", () => {
5
+ describe("activeUserId", () => {
6
+ it("user object exists ", () => {
7
+ const _id = Math.random();
8
+ const res = extractors.activeUserId({ user: { _id } });
9
+ expect(_id).to.be.equal(res);
10
+ });
11
+ it("user object doesnt exists ", () => {
12
+ const res = extractors.activeUserId({});
13
+ expect(res).to.be.undefined;
14
+ });
15
+ });
16
+
17
+ it("activeUserModelName", () => {
18
+ const res = extractors.activeUserModelName();
19
+ expect("User").to.be.equal(res);
20
+ });
21
+
22
+ it("fromBody", () => {
23
+ const req = {
24
+ body: {
25
+ a: 1,
26
+ b: 2,
27
+ c: 3,
28
+ d: 4,
29
+ },
30
+ };
31
+ expect(extractors.fromBody(req, "b")).to.be.equal(2);
32
+ expect(extractors.fromBody(req, "e")).to.be.undefined;
33
+ });
34
+
35
+ it("fromParams", () => {
36
+ const req = {
37
+ params: {
38
+ a: 1,
39
+ b: 2,
40
+ c: 3,
41
+ d: 4,
42
+ },
43
+ };
44
+ expect(extractors.fromParams(req, "b")).to.be.equal(2);
45
+ expect(extractors.fromParams(req, "e")).to.be.undefined;
46
+ });
47
+
48
+ it("fromQuery", () => {
49
+ const req = {
50
+ query: {
51
+ a: 1,
52
+ b: 2,
53
+ c: 3,
54
+ d: 4,
55
+ },
56
+ };
57
+ expect(extractors.fromQuery(req, "b")).to.be.equal(2);
58
+ expect(extractors.fromQuery(req, "e")).to.be.undefined;
59
+ });
60
+ });
package/test/filter.js ADDED
@@ -0,0 +1,286 @@
1
+ const mongoose = require("mongoose");
2
+ const Schema = mongoose.Schema;
3
+ const expect = require("chai").expect,
4
+ notFieldsFilter = require("../src/fields/filter");
5
+
6
+ const SCHEMA = () => {
7
+ return {
8
+ role: {
9
+ type: [String],
10
+ required: true,
11
+ searchable: true,
12
+ default: ["user"],
13
+ validate: [],
14
+ safe: {
15
+ update: ["root", "admin"],
16
+ read: ["@owner", "root", "admin"],
17
+ },
18
+ },
19
+ name: {
20
+ type: String,
21
+ safe: {
22
+ update: ["@system", "@owner", "root", "admin"],
23
+ read: ["*"],
24
+ },
25
+ },
26
+ salt: {
27
+ type: String,
28
+ required: true,
29
+ },
30
+ telephone: {
31
+ type: String,
32
+ unique: false,
33
+ searchable: true,
34
+ required: false,
35
+ safe: {
36
+ update: ["@owner", "root", "admin"],
37
+ read: ["@owner", "root", "admin"],
38
+ },
39
+ },
40
+ username: {
41
+ type: String,
42
+ unique: true,
43
+ searchable: true,
44
+ required: true,
45
+ safe: {
46
+ read: ["*"],
47
+ },
48
+ },
49
+ confirm: {
50
+ type: Schema.Types.Mixed,
51
+ required: false,
52
+ searchable: true,
53
+ safe: {
54
+ update: ["@system", "root", "admin"],
55
+ },
56
+ },
57
+ code: {
58
+ type: String,
59
+ searchable: true,
60
+ required: true,
61
+ },
62
+ country: {
63
+ type: String,
64
+ required: false,
65
+ searchable: true,
66
+ default: "ru",
67
+ safe: {
68
+ update: ["@system", "@owner", "root", "admin"],
69
+ read: ["*"],
70
+ },
71
+ },
72
+ email: {
73
+ type: String,
74
+ unique: true,
75
+ searchable: true,
76
+ required: true,
77
+ safe: {
78
+ update: ["@owner", "root", "admin"],
79
+ read: ["@owner", "root", "admin"],
80
+ },
81
+ },
82
+ };
83
+ };
84
+
85
+ describe("Fields/notFieldsFilter", function () {
86
+ describe("userSets", () => {
87
+ it("static getter", () => {
88
+ expect(notFieldsFilter.userSets).to.be.deep.equal({});
89
+ });
90
+ });
91
+
92
+ describe("addSet", () => {
93
+ it("add new", () => {
94
+ const result = notFieldsFilter.addSet("test1", [
95
+ "field1",
96
+ "-field2",
97
+ ]);
98
+ expect(result).to.be.true;
99
+ expect(notFieldsFilter.userSets).to.have.key("test1");
100
+ expect(notFieldsFilter.userSets.test1).to.be.deep.equal([
101
+ "field1",
102
+ "-field2",
103
+ ]);
104
+ });
105
+
106
+ it("add new with faulty items, discarded", () => {
107
+ const result = notFieldsFilter.addSet("test2", [123123, "-field2"]);
108
+ expect(result).to.be.false;
109
+ expect(notFieldsFilter.userSets).to.not.have.key("test2");
110
+ });
111
+
112
+ it("add new with restricted name, discarded", () => {
113
+ const result = notFieldsFilter.addSet("*", ["-field2"]);
114
+ expect(result).to.be.false;
115
+ expect(notFieldsFilter.userSets).to.not.have.key("test2");
116
+ });
117
+ });
118
+
119
+ describe("removeSet", () => {
120
+ it("set exists", () => {
121
+ const result = notFieldsFilter.removeSet("test1");
122
+ expect(result).to.be.true;
123
+ });
124
+
125
+ it("set not exists", () => {
126
+ const result = notFieldsFilter.removeSet("test1");
127
+ expect(result).to.be.false;
128
+ });
129
+ });
130
+
131
+ describe("isSpecialSet", () => {
132
+ it("exclude special set", () => {
133
+ const name = "-@*";
134
+ const result = notFieldsFilter.isSpecialSet(name);
135
+ expect(result).to.be.true;
136
+ });
137
+ });
138
+ describe("specials", () => {
139
+ it("static specials getter", () => {
140
+ const result = notFieldsFilter.specials;
141
+ expect(result).to.be.instanceOf(Object);
142
+ expect(result).to.have.all.keys([
143
+ "ALL",
144
+ "SAFE",
145
+ "UNSAFE",
146
+ "TIMESTAMPS",
147
+ "OWNAGE",
148
+ "VERSIONING",
149
+ "ID_NUMERIC",
150
+ "ID_UUID",
151
+ ]);
152
+ });
153
+
154
+ it("SPECIAL_SET_SAFE; action=update other undefined", () => {
155
+ const result = notFieldsFilter.getSpecialSetContent(
156
+ notFieldsFilter.specials.SAFE,
157
+ SCHEMA(),
158
+ { action: "update" }
159
+ );
160
+ expect(result).to.be.deep.equal([]);
161
+ });
162
+
163
+ it("SPECIAL_SET_SAFE; action=read other undefined", () => {
164
+ const result = notFieldsFilter.getSpecialSetContent(
165
+ notFieldsFilter.specials.SAFE,
166
+ SCHEMA(),
167
+ { action: "read" }
168
+ );
169
+ expect(result).to.be.deep.equal(["name", "username", "country"]);
170
+ });
171
+ });
172
+
173
+ describe("specialsToPlain", () => {
174
+ it("get all fields ['@*']", () => {
175
+ const result = notFieldsFilter.specialsToPlain(["@*"], SCHEMA(), {
176
+ modelName: "SomeModel",
177
+ });
178
+ const target = ["_id", "someModelID", ...Object.keys(SCHEMA())];
179
+ expect(Array.isArray(result)).to.be.true;
180
+ expect(result.length).to.be.equal(target.length);
181
+ expect(result).to.be.deep.equal(target);
182
+ });
183
+
184
+ it("get all fields ['@*']", () => {
185
+ const result = notFieldsFilter.specialsToPlain(["@*"], SCHEMA(), {
186
+ modelName: "SomeModel",
187
+ });
188
+ const target = ["_id", "someModelID", ...Object.keys(SCHEMA())];
189
+ expect(Array.isArray(result)).to.be.true;
190
+ expect(result.length).to.be.equal(target.length);
191
+ expect(result).to.be.deep.equal(target);
192
+ });
193
+
194
+ it("list with special set exclusions", () => {
195
+ const list = ["id", "name", "-@versioning"];
196
+ const result = notFieldsFilter.specialsToPlain(list, SCHEMA(), {
197
+ modelName: "SomeModel",
198
+ });
199
+ expect(result).to.be.deep.equal([
200
+ "id",
201
+ "name",
202
+ "-__version",
203
+ "-__versions",
204
+ "-__closed",
205
+ "-__latest",
206
+ "-__v",
207
+ ]);
208
+ });
209
+ });
210
+
211
+ describe("removeExcludedFields", () => {
212
+ it("empty list", () => {
213
+ const list = [];
214
+ const result = notFieldsFilter.removeExcludedFields(list);
215
+ expect(result).to.be.deep.equal([]);
216
+ });
217
+
218
+ it("list without exclusions", () => {
219
+ const list = ["id", "name"];
220
+ const result = notFieldsFilter.removeExcludedFields(list);
221
+ expect(result).to.be.deep.equal(["id", "name"]);
222
+ });
223
+
224
+ it("list with exclusions but no target fields presentation in list", () => {
225
+ const list = ["-gag", "id", "name", "-data", "-time"];
226
+ const result = notFieldsFilter.removeExcludedFields(list);
227
+ expect(result).to.be.deep.equal(["id", "name"]);
228
+ });
229
+
230
+ it("list with exclusions predicating includsions", () => {
231
+ const list = ["-id", "id", "name", "-name", "-time"];
232
+ const result = notFieldsFilter.removeExcludedFields(list);
233
+ expect(result).to.be.deep.equal(["id"]);
234
+ });
235
+
236
+ it("list with exclusions, end up empty", () => {
237
+ const list = ["id", "-id", "name", "-name", "-time"];
238
+ const result = notFieldsFilter.removeExcludedFields(list);
239
+ expect(result).to.be.deep.equal([]);
240
+ });
241
+
242
+ it("list with exclusions, but later inclusions", () => {
243
+ const list = ["id", "-id", "name", "-name", "id"];
244
+ const result = notFieldsFilter.removeExcludedFields(list);
245
+ expect(result).to.be.deep.equal(["id"]);
246
+ });
247
+ });
248
+
249
+ describe("fieldsListIsNotPlain", () => {
250
+ it("plain list", () => {
251
+ const fields = ["field1", "field2"];
252
+ expect(notFieldsFilter.fieldsListIsNotPlain(fields)).to.be.false;
253
+ });
254
+
255
+ it("not plain list, exlusion", () => {
256
+ const fields = ["field1", "-field2"];
257
+ expect(notFieldsFilter.fieldsListIsNotPlain(fields)).to.be.true;
258
+ });
259
+
260
+ it("not plain list, special set", () => {
261
+ const fields = ["@safe"];
262
+ expect(notFieldsFilter.fieldsListIsNotPlain(fields)).to.be.true;
263
+ });
264
+ });
265
+
266
+ describe("filter", () => {
267
+ it("complex operations exclude/include with deep of 3", () => {
268
+ notFieldsFilter.addSet("user1", ["-@safe"]);
269
+ notFieldsFilter.addSet("user2", ["-@user1"]);
270
+ const result = notFieldsFilter.filter(
271
+ ["id", "name", "@user2"],
272
+ SCHEMA(),
273
+ {
274
+ action: "read",
275
+ }
276
+ );
277
+ expect(result).to.be.deep.equal([
278
+ "id",
279
+ "name",
280
+ "name",
281
+ "username",
282
+ "country",
283
+ ]);
284
+ });
285
+ });
286
+ });