hola-server 0.6.10 → 0.6.13

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/core/meta.js CHANGED
@@ -13,6 +13,7 @@ const meta_manager = {};
13
13
  * create is false, this attribute can be shown in property list but sys property can't be shown in property list
14
14
  * secure: secure properties will not be read by client, this is useful for password
15
15
  * group: this is used to control user sharing entities, this means the entity is shared by user group, this is only valid for user field
16
+ * view: this is used to control for edit form, for one entity, may have many forms to edit the entity, so use view to seperate them, this can be string or array
16
17
  *
17
18
  * routes: configure customer defined routes
18
19
  * link property: field link property link to entity field and the field should ref to an entity.
@@ -20,7 +21,7 @@ const meta_manager = {};
20
21
  *
21
22
  *
22
23
  */
23
- const field_attrs = ["name", "type", "required", "ref", "link", "delete", "create", "list", "search", "update", "clone", "sys", "secure", "group"];
24
+ const field_attrs = ["name", "type", "required", "ref", "link", "delete", "create", "list", "search", "update", "clone", "sys", "secure", "group", "view"];
24
25
  const meta_attrs = ["collection", "roles", "primary_keys", "fields", "creatable", "readable", "updatable", "deleteable", "cloneable", "after_read",
25
26
  "before_create", "after_create", "before_clone", "after_clone", "before_update", "after_update", "before_delete", "after_delete", "create", "clone", "update", "batch_update", "after_batch_update", "delete",
26
27
  "ref_label", "ref_filter", "route", "user_field"];
@@ -90,6 +91,19 @@ const validate_field = (meta, field) => {
90
91
  });
91
92
  }
92
93
 
94
+ const editable = (field.create != false) || (field.update != false);
95
+
96
+ if (field.view) {
97
+ if (!editable) {
98
+ throw new Error("view can just defined for editable (create/update) field only. Field:" + JSON.stringify(field) + "] and meta:" + meta.collection);
99
+ }
100
+ } else {
101
+ //no view defined for create/update field, then set view to default value "0"
102
+ if (editable) {
103
+ field.view = "0";
104
+ }
105
+ }
106
+
93
107
  const keys = Object.keys(field);
94
108
  keys.forEach(key => {
95
109
  if (!field_attrs.includes(key)) {
@@ -216,7 +230,8 @@ class EntityMeta {
216
230
  //b:batch mode, c:create, d:delete, e:export, i:import, o:clone, p:page, r: refresh, s:search, u:update
217
231
  const modes = [];
218
232
  this.creatable && (modes.push("c"));
219
- this.readable && (modes.push("rps"));
233
+ //prefer the infinite scrolling mode, so doesn't include p mode
234
+ this.readable && (modes.push("rs"));
220
235
  this.updatable && (modes.push("u"));
221
236
  this.deleteable && (modes.push("db"));
222
237
  this.cloneable && (modes.push("o"));
@@ -302,9 +317,23 @@ class EntityMeta {
302
317
 
303
318
  this.roles.forEach(role => {
304
319
  const role_config = role.split(":");
320
+ if (role_config.length != 2) {
321
+ throw new Error("wrong role config [" + role + "] in meta [" + this.collection + "]. You should use : to seperate the role name with mode.");
322
+ }
323
+
305
324
  const role_name = role_config[0];
306
325
  if (!validate_meta_role(role_name)) {
307
- throw new Error("role [" + role_name + "] not defined in setting");
326
+ throw new Error("role [" + role_name + "] in meta [" + this.collection + "] not defined in setting's role config.");
327
+ }
328
+
329
+ const role_mode = role_config[1];
330
+ if (role_mode != "*") {
331
+ for (let i = 0; i < role_mode.length; i++) {
332
+ const mode = role_mode.charAt(i);
333
+ if (!this.mode.includes(mode)) {
334
+ throw new Error("role [" + role_name + "] in meta [" + this.collection + "] with mode [" + mode + "] doesn't comply with entity mode [" + this.mode + "]");
335
+ }
336
+ }
308
337
  }
309
338
  });
310
339
  }
package/core/role.js CHANGED
@@ -1,7 +1,13 @@
1
1
  const { get_settings } = require("../setting");
2
2
 
3
+ /**
4
+ * Validate the role defination in meta config
5
+ * @param {*} role_name
6
+ * @returns
7
+ */
3
8
  const validate_meta_role = (role_name) => {
4
9
  const settings = get_settings();
10
+ //there is role defined in meta but no roles config in settings
5
11
  if (!settings.roles) {
6
12
  return false;
7
13
  }
@@ -16,7 +22,7 @@ const is_valid_role = (role_name) => {
16
22
 
17
23
  const is_root_role = (role_name) => {
18
24
  const settings = get_settings();
19
- //no role defined, then every one is root
25
+ //no role defined, then there is no role limition, so treat each user as root
20
26
  if (!settings.roles) {
21
27
  return true;
22
28
  }
@@ -28,11 +34,22 @@ const is_root_role = (role_name) => {
28
34
  }
29
35
  }
30
36
 
37
+ /**
38
+ * get user's role from user session
39
+ * @param {request} req
40
+ * @returns
41
+ */
31
42
  const get_session_user_role = (req) => {
32
43
  const user = req && req.session ? req.session.user : null;
33
44
  return user ? user.role : null;
34
45
  }
35
46
 
47
+ /**
48
+ * Get the meta mode based on user's role
49
+ * @param {request} req
50
+ * @param {meta} meta
51
+ * @returns
52
+ */
36
53
  const get_user_role_mode = (req, meta) => {
37
54
  const settings = get_settings();
38
55
  //no role defined in settings or no roles defined in meta, use meta mode
@@ -53,14 +70,25 @@ const get_user_role_mode = (req, meta) => {
53
70
  const role_name = role_settings[0];
54
71
  const role_mode = role_settings[1];
55
72
  if (user_role == role_name) {
56
- return role_mode;
73
+ // * stands to get the mode from meta definition
74
+ if (role_mode == "*") {
75
+ return meta.mode;
76
+ } else {
77
+ return role_mode;
78
+ }
57
79
  }
58
80
  }
59
81
  }
60
-
61
82
  return "";
62
83
  }
63
84
 
85
+ /**
86
+ * Check whether the user has the mode right on the meta or not
87
+ * @param {http request} req
88
+ * @param {meta defination} meta
89
+ * @param {meta mode} mode
90
+ * @returns
91
+ */
64
92
  const check_user_role = (req, meta, mode) => {
65
93
  const role_mode = get_user_role_mode(req, meta);
66
94
  return role_mode.includes(mode);
package/db/entity.js CHANGED
@@ -235,10 +235,11 @@ class Entity {
235
235
  /**
236
236
  * Validate the param object and invoke the logic to save it to db
237
237
  * @param {param obj from user input} param_obj
238
+ * @param {which view to create the entity} view
238
239
  * @returns object with code and err
239
240
  */
240
- async create_entity(param_obj) {
241
- const fields = this.meta.create_fields
241
+ async create_entity(param_obj, view) {
242
+ const fields = this.meta.create_fields.filter(field => field.view == view);
242
243
  const { obj, error_field_names } = convert_type(param_obj, fields);
243
244
  if (error_field_names.length > 0) {
244
245
  if (is_log_error()) {
@@ -397,10 +398,13 @@ class Entity {
397
398
  * Validate the param object and invoke the logic to update entity
398
399
  * @param {object id of the entity} _id object id of the entity, if it is null, then use primary key
399
400
  * @param {param object from user input} param_obj
401
+ * @param {which view to update the entity} view
400
402
  *
401
403
  */
402
- async update_entity(_id, param_obj) {
403
- const { obj, error_field_names } = convert_update_type(param_obj, this.meta.update_fields);
404
+ async update_entity(_id, param_obj, view) {
405
+ const fields = this.meta.update_fields.filter(field => field.view == view);
406
+
407
+ const { obj, error_field_names } = convert_update_type(param_obj, fields);
404
408
  if (error_field_names.length > 0) {
405
409
  if (is_log_error()) {
406
410
  log_error(LOG_ENTITY, "update_entity error fields:" + JSON.stringify(error_field_names));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hola-server",
3
- "version": "0.6.10",
3
+ "version": "0.6.13",
4
4
  "description": "a meta programming framework used to build nodejs restful api",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/router/create.js CHANGED
@@ -26,6 +26,12 @@ const init_create_router = function (router, meta) {
26
26
  return;
27
27
  }
28
28
 
29
+ //which view to create the entity
30
+ let { _view } = post_params(req, ["_view"]);
31
+ if (!_view) {
32
+ _view = "0";
33
+ }
34
+
29
35
  const param_obj = post_params(req, meta.field_names);
30
36
  set_file_fields(meta, req, param_obj);
31
37
 
@@ -37,7 +43,7 @@ const init_create_router = function (router, meta) {
37
43
  param_obj[meta.user_field] = user_id;
38
44
  }
39
45
 
40
- const { code, err } = await entity.create_entity(param_obj);
46
+ const { code, err } = await entity.create_entity(param_obj, _view);
41
47
  if (!has_value(code)) {
42
48
  throw new Error("the method should return code");
43
49
  }
package/router/update.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { set_file_fields, save_file_fields_to_db } = require('../db/gridfs');
2
- const { required_post_params, post_update_params } = require('../http/params');
2
+ const { required_post_params, post_update_params, post_params } = require('../http/params');
3
3
  const { SUCCESS, NO_PARAMS, NO_RIGHTS } = require('../http/code');
4
4
  const { check_user_role } = require('../http/session');
5
5
  const { has_value } = require('../core/validate');
@@ -36,10 +36,16 @@ const init_update_router = function (router, meta) {
36
36
  }
37
37
  }
38
38
 
39
+ //which view to update the entity
40
+ let { _view } = post_params(req, ["_view"]);
41
+ if (!_view) {
42
+ _view = "0";
43
+ }
44
+
39
45
  const param_obj = post_update_params(req, meta.field_names);
40
46
  set_file_fields(meta, req, param_obj);
41
47
 
42
- const { code, err } = await entity.update_entity(params["_id"], param_obj);
48
+ const { code, err } = await entity.update_entity(params["_id"], param_obj, _view);
43
49
  if (!has_value(code)) {
44
50
  throw new Error("the method should return code");
45
51
  }