hola-server 1.0.10 → 2.0.1
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/README.md +196 -1
- package/core/array.js +79 -142
- package/core/bash.js +208 -259
- package/core/chart.js +26 -16
- package/core/cron.js +14 -3
- package/core/date.js +15 -44
- package/core/encrypt.js +19 -9
- package/core/file.js +42 -29
- package/core/lhs.js +32 -6
- package/core/meta.js +213 -289
- package/core/msg.js +20 -7
- package/core/number.js +105 -103
- package/core/obj.js +15 -12
- package/core/random.js +9 -6
- package/core/role.js +69 -77
- package/core/thread.js +12 -2
- package/core/type.js +300 -261
- package/core/url.js +20 -12
- package/core/validate.js +29 -26
- package/db/db.js +297 -227
- package/db/entity.js +631 -963
- package/db/gridfs.js +120 -166
- package/design/add_default_field_attr.md +56 -0
- package/http/context.js +22 -8
- package/http/cors.js +25 -8
- package/http/error.js +27 -9
- package/http/express.js +70 -41
- package/http/params.js +70 -42
- package/http/router.js +51 -40
- package/http/session.js +59 -36
- package/index.js +85 -9
- package/package.json +2 -2
- package/router/clone.js +28 -36
- package/router/create.js +21 -26
- package/router/delete.js +24 -28
- package/router/read.js +137 -123
- package/router/update.js +38 -56
- package/setting.js +22 -6
- package/skills/array.md +155 -0
- package/skills/bash.md +91 -0
- package/skills/chart.md +54 -0
- package/skills/code.md +422 -0
- package/skills/context.md +177 -0
- package/skills/date.md +58 -0
- package/skills/express.md +255 -0
- package/skills/file.md +60 -0
- package/skills/lhs.md +54 -0
- package/skills/meta.md +1023 -0
- package/skills/msg.md +30 -0
- package/skills/number.md +88 -0
- package/skills/obj.md +36 -0
- package/skills/params.md +206 -0
- package/skills/random.md +22 -0
- package/skills/role.md +59 -0
- package/skills/session.md +281 -0
- package/skills/storage.md +743 -0
- package/skills/thread.md +22 -0
- package/skills/type.md +547 -0
- package/skills/url.md +34 -0
- package/skills/validate.md +48 -0
- package/test/cleanup/close-db.js +5 -0
- package/test/core/array.js +226 -0
- package/test/core/chart.js +51 -0
- package/test/core/file.js +59 -0
- package/test/core/lhs.js +44 -0
- package/test/core/number.js +167 -12
- package/test/core/obj.js +47 -0
- package/test/core/random.js +24 -0
- package/test/core/thread.js +20 -0
- package/test/core/type.js +216 -0
- package/test/core/validate.js +67 -0
- package/test/db/db-ops.js +99 -0
- package/test/db/pipe_test.txt +0 -0
- package/test/db/test_case_design.md +528 -0
- package/test/db/test_db_class.js +613 -0
- package/test/db/test_entity_class.js +414 -0
- package/test/db/test_gridfs_class.js +234 -0
- package/test/entity/create.js +1 -1
- package/test/entity/delete-mixed.js +156 -0
- package/test/entity/ref-filter.js +63 -0
- package/tool/gen_i18n.js +55 -21
- package/test/crud/router.js +0 -99
- package/test/router/user.js +0 -17
package/http/params.js
CHANGED
|
@@ -1,57 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Request parameter extraction utilities.
|
|
3
|
+
* @module http/params
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const { has_value, is_undefined } = require('../core/validate');
|
|
2
7
|
|
|
3
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Extract parameters from input object using a filter function.
|
|
10
|
+
* @param {Object} input - Source object (req.query or req.body)
|
|
11
|
+
* @param {string[]} params - Parameter names to extract
|
|
12
|
+
* @param {Function} filter_fn - Function to determine if param should be included
|
|
13
|
+
* @returns {Object} Object containing extracted parameters
|
|
14
|
+
*/
|
|
15
|
+
const extract_params = (input, params, filter_fn) => {
|
|
4
16
|
const obj = {};
|
|
5
|
-
|
|
6
|
-
if (
|
|
17
|
+
for (const param of params) {
|
|
18
|
+
if (filter_fn(input[param])) {
|
|
7
19
|
obj[param] = input[param];
|
|
8
20
|
}
|
|
9
|
-
}
|
|
21
|
+
}
|
|
10
22
|
return obj;
|
|
11
23
|
};
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
25
|
+
/**
|
|
26
|
+
* Extract specified parameters from input object (only if values are present).
|
|
27
|
+
* @param {Object} input - Source object (req.query or req.body)
|
|
28
|
+
* @param {string[]} params - Parameter names to extract
|
|
29
|
+
* @returns {Object} Object containing extracted parameters
|
|
30
|
+
*/
|
|
31
|
+
const parse_params = (input, params) => extract_params(input, params, has_value);
|
|
16
32
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
33
|
+
/**
|
|
34
|
+
* Extract query parameters from request.
|
|
35
|
+
* @param {Object} req - Express request
|
|
36
|
+
* @param {string[]} params - Parameter names to extract
|
|
37
|
+
* @returns {Object} Extracted parameters
|
|
38
|
+
*/
|
|
39
|
+
const get_params = (req, params) => parse_params(req.query, params);
|
|
20
40
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
return obj;
|
|
30
|
-
};
|
|
41
|
+
/**
|
|
42
|
+
* Extract body parameters from request.
|
|
43
|
+
* @param {Object} req - Express request
|
|
44
|
+
* @param {string[]} params - Parameter names to extract
|
|
45
|
+
* @returns {Object} Extracted parameters
|
|
46
|
+
*/
|
|
47
|
+
const post_params = (req, params) => parse_params(req.body, params);
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
if (passed === false) {
|
|
43
|
-
return null;
|
|
44
|
-
} else {
|
|
45
|
-
return obj;
|
|
46
|
-
}
|
|
47
|
-
};
|
|
49
|
+
/**
|
|
50
|
+
* Extract update parameters from request body, including undefined values.
|
|
51
|
+
* Used for partial updates where undefined means "don't change".
|
|
52
|
+
* @param {Object} req - Express request
|
|
53
|
+
* @param {string[]} params - Parameter names to extract
|
|
54
|
+
* @returns {Object} Extracted parameters
|
|
55
|
+
*/
|
|
56
|
+
const post_update_params = (req, params) => extract_params(req.body, params, v => !is_undefined(v));
|
|
48
57
|
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Extract required parameters, returning null if any are missing.
|
|
60
|
+
* @param {Object} input - Source object
|
|
61
|
+
* @param {string[]} params - Required parameter names
|
|
62
|
+
* @returns {Object|null} Extracted parameters or null if any missing
|
|
63
|
+
*/
|
|
64
|
+
const required_params = (input, params) => {
|
|
65
|
+
const result = parse_params(input, params);
|
|
66
|
+
return Object.keys(result).length === params.length ? result : null;
|
|
51
67
|
};
|
|
52
68
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract required query parameters from request.
|
|
71
|
+
* @param {Object} req - Express request
|
|
72
|
+
* @param {string[]} params - Required parameter names
|
|
73
|
+
* @returns {Object|null} Extracted parameters or null if any missing
|
|
74
|
+
*/
|
|
75
|
+
const required_get_params = (req, params) => required_params(req.query, params);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Extract required body parameters from request.
|
|
79
|
+
* @param {Object} req - Express request
|
|
80
|
+
* @param {string[]} params - Required parameter names
|
|
81
|
+
* @returns {Object|null} Extracted parameters or null if any missing
|
|
82
|
+
*/
|
|
83
|
+
const required_post_params = (req, params) => required_params(req.body, params);
|
|
56
84
|
|
|
57
|
-
module.exports = { get_params, post_params, post_update_params, required_get_params, required_post_params, required_params }
|
|
85
|
+
module.exports = { get_params, post_params, post_update_params, required_get_params, required_post_params, required_params };
|
package/http/router.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Express router initialization and loading utilities.
|
|
3
|
+
* @module http/router
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const path = require("path");
|
|
2
7
|
const fs = require("fs");
|
|
3
8
|
const express = require('express');
|
|
@@ -10,63 +15,69 @@ const { init_clone_router } = require('../router/clone');
|
|
|
10
15
|
const { init_delete_router } = require('../router/delete');
|
|
11
16
|
const { get_settings } = require('../setting');
|
|
12
17
|
|
|
18
|
+
/** CRUD operation configurations: [capability_key, init_function] */
|
|
19
|
+
const CRUD_OPERATIONS = [
|
|
20
|
+
['creatable', init_create_router],
|
|
21
|
+
['readable', init_read_router],
|
|
22
|
+
['updatable', init_update_router],
|
|
23
|
+
['cloneable', init_clone_router],
|
|
24
|
+
['deleteable', init_delete_router],
|
|
25
|
+
];
|
|
26
|
+
|
|
13
27
|
/**
|
|
14
|
-
* Automatically load all
|
|
15
|
-
*
|
|
16
|
-
*
|
|
28
|
+
* Automatically load all router modules from configured directories.
|
|
29
|
+
* Scans directories specified in settings.server.routes and mounts each router.
|
|
30
|
+
* After loading, validates all entity metadata definitions.
|
|
31
|
+
* @param {Object} app - Express application instance.
|
|
32
|
+
* @param {string} base_dir - Base directory of the project.
|
|
17
33
|
*/
|
|
18
34
|
const init_router_dirs = (app, base_dir) => {
|
|
19
|
-
const
|
|
35
|
+
const settings = get_settings();
|
|
36
|
+
if (!settings?.server?.routes) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const route_dir of settings.server.routes) {
|
|
41
|
+
const full_route_dir = path.join(base_dir, route_dir);
|
|
42
|
+
if (!fs.existsSync(full_route_dir)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
20
45
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
routes.forEach(route => {
|
|
26
|
-
const router = require(`${base_dir}/${route_dir}/${route}`);
|
|
27
|
-
const basename = path.basename(route, '.js');
|
|
28
|
-
app.use('/' + basename, router);
|
|
29
|
-
});
|
|
30
|
-
});
|
|
46
|
+
for (const route of fs.readdirSync(full_route_dir)) {
|
|
47
|
+
if (!route.endsWith('.js')) {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
31
50
|
|
|
32
|
-
|
|
33
|
-
|
|
51
|
+
const router = require(`${base_dir}/${route_dir}/${route}`);
|
|
52
|
+
const basename = path.basename(route, '.js');
|
|
53
|
+
app.use('/' + basename, router);
|
|
54
|
+
}
|
|
34
55
|
}
|
|
35
|
-
|
|
56
|
+
|
|
57
|
+
validate_all_metas();
|
|
58
|
+
};
|
|
36
59
|
|
|
37
60
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
61
|
+
* Initialize Express router for an entity with CRUD operations.
|
|
62
|
+
* Registers routes based on entity metadata capabilities (creatable, readable, etc.).
|
|
63
|
+
* @param {Object} meta - Entity metadata configuration.
|
|
64
|
+
* @returns {Object} Configured Express router.
|
|
40
65
|
*/
|
|
41
|
-
const init_router =
|
|
66
|
+
const init_router = (meta) => {
|
|
42
67
|
const router = express.Router();
|
|
43
68
|
const meta_entity = new EntityMeta(meta);
|
|
44
69
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (meta_entity.readable) {
|
|
50
|
-
init_read_router(router, meta_entity);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (meta_entity.updatable) {
|
|
54
|
-
init_update_router(router, meta_entity);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (meta_entity.cloneable) {
|
|
58
|
-
init_clone_router(router, meta_entity);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (meta_entity.deleteable) {
|
|
62
|
-
init_delete_router(router, meta_entity);
|
|
70
|
+
for (const [capability, init_fn] of CRUD_OPERATIONS) {
|
|
71
|
+
if (meta_entity[capability]) {
|
|
72
|
+
init_fn(router, meta_entity);
|
|
73
|
+
}
|
|
63
74
|
}
|
|
64
75
|
|
|
65
|
-
if (meta.route) {
|
|
76
|
+
if (typeof meta.route === 'function') {
|
|
66
77
|
meta.route(router, meta_entity);
|
|
67
78
|
}
|
|
68
79
|
|
|
69
80
|
return router;
|
|
70
|
-
}
|
|
81
|
+
};
|
|
71
82
|
|
|
72
83
|
module.exports = { init_router_dirs, init_router };
|
package/http/session.js
CHANGED
|
@@ -1,50 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Session middleware initialization and helpers.
|
|
3
|
+
* @module http/session
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const express_session = require('express-session');
|
|
2
7
|
const MongoStore = require('connect-mongo');
|
|
3
8
|
const { get_settings } = require('../setting');
|
|
4
9
|
const { is_root_user } = require('../core/role');
|
|
5
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Initialize session middleware with MongoDB store.
|
|
13
|
+
* @param {Object} app - Express application instance
|
|
14
|
+
*/
|
|
6
15
|
const init_session = (app) => {
|
|
7
|
-
const server = get_settings()
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const session = server.session;
|
|
12
|
-
|
|
13
|
-
app.use(express_session({
|
|
14
|
-
secret: session.secret,
|
|
15
|
-
resave: true,
|
|
16
|
-
saveUninitialized: true,
|
|
17
|
-
cookie: { maxAge: session.cookie_max_age },
|
|
18
|
-
store: MongoStore.create({ mongoUrl: mongo.url })
|
|
19
|
-
}));
|
|
16
|
+
const { server, mongo } = get_settings();
|
|
17
|
+
if (!server?.keep_session) return;
|
|
18
|
+
if (!server.session?.secret) {
|
|
19
|
+
throw new Error('Session secret required when keep_session is enabled');
|
|
20
20
|
}
|
|
21
|
-
}
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
app.use(express_session({
|
|
23
|
+
secret: server.session.secret,
|
|
24
|
+
resave: true,
|
|
25
|
+
saveUninitialized: true,
|
|
26
|
+
cookie: { maxAge: server.session.cookie_max_age || 86400000 },
|
|
27
|
+
store: MongoStore.create({ mongoUrl: mongo.url })
|
|
28
|
+
}));
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Get a value from the session.
|
|
33
|
+
* @param {Object} req - Express request
|
|
34
|
+
* @param {string} key - Session key
|
|
35
|
+
* @returns {*} Session value or null
|
|
36
|
+
*/
|
|
37
|
+
const get_session_value = (req, key) => req?.session?.[key] ?? null;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get current user ID from session.
|
|
41
|
+
* @param {Object} req - Express request
|
|
42
|
+
* @returns {string|null} User ID or null
|
|
43
|
+
*/
|
|
44
|
+
const get_session_user_id = (req) => get_session_value(req, 'user')?.id ?? null;
|
|
27
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Get current user groups from session.
|
|
48
|
+
* @param {Object} req - Express request
|
|
49
|
+
* @returns {string[]|null} User group IDs or null
|
|
50
|
+
*/
|
|
28
51
|
const get_session_user_groups = (req) => {
|
|
29
|
-
const group = req
|
|
30
|
-
return
|
|
31
|
-
}
|
|
52
|
+
const group = get_session_value(req, 'group');
|
|
53
|
+
return Array.isArray(group) ? group : null;
|
|
54
|
+
};
|
|
32
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Check if current user owns the entity.
|
|
58
|
+
* @param {Object} req - Express request
|
|
59
|
+
* @param {Object} meta - Entity meta
|
|
60
|
+
* @param {Object} entity - Entity instance
|
|
61
|
+
* @param {Object} query - MongoDB query
|
|
62
|
+
* @returns {Promise<boolean>} True if owner or root
|
|
63
|
+
*/
|
|
33
64
|
const is_owner = async (req, meta, entity, query) => {
|
|
34
|
-
if (is_root_user(req))
|
|
35
|
-
return true;
|
|
36
|
-
}
|
|
65
|
+
if (is_root_user(req) || !meta.user_field) return true;
|
|
37
66
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const user_query = {};
|
|
44
|
-
user_query[meta.user_field] = user_id;
|
|
45
|
-
return await entity.count({ ...query, ...user_query }) == 1;
|
|
46
|
-
}
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
67
|
+
const user_id = get_session_user_id(req);
|
|
68
|
+
if (!user_id) throw new Error("no user id found in session");
|
|
69
|
+
|
|
70
|
+
return await entity.count({ ...query, [meta.user_field]: user_id }) === 1;
|
|
71
|
+
};
|
|
49
72
|
|
|
50
|
-
module.exports = { init_session,
|
|
73
|
+
module.exports = { init_session, get_session_user_id, get_session_user_groups, is_owner };
|
package/index.js
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hola Server - Main entry point and public API.
|
|
3
|
+
* @module index
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Database
|
|
1
7
|
const { get_db } = require('./db/db');
|
|
2
8
|
const { Entity } = require('./db/entity');
|
|
9
|
+
const { log_debug, log_info, log_warn, log_error, is_log_debug, is_log_info, is_log_warn, is_log_error, get_session_user_id, oid_queries, oid_query } = require('./db/db');
|
|
10
|
+
const gridfs = require('./db/gridfs');
|
|
11
|
+
|
|
12
|
+
// Settings and Configuration
|
|
3
13
|
const { init_settings } = require('./setting');
|
|
14
|
+
|
|
15
|
+
// HTTP Layer
|
|
4
16
|
const { init_router } = require('./http/router');
|
|
5
17
|
const { init_express_server } = require('./http/express');
|
|
18
|
+
const code = require('./http/code');
|
|
19
|
+
const err = require('./http/error');
|
|
20
|
+
const params = require('./http/params');
|
|
21
|
+
const context = require('./http/context');
|
|
22
|
+
|
|
23
|
+
// Core Type System
|
|
6
24
|
const { register_type, get_type } = require('./core/type');
|
|
7
25
|
const { EntityMeta, get_entity_meta } = require('./core/meta');
|
|
26
|
+
|
|
27
|
+
// Core Role System
|
|
8
28
|
const { is_root_role, is_root_user, check_user_role, get_user_role_right, get_session_user } = require('./core/role');
|
|
29
|
+
|
|
30
|
+
// Core Utilities
|
|
9
31
|
const { url } = require('./core/url');
|
|
10
32
|
const array = require('./core/array');
|
|
11
33
|
const bash = require('./core/bash');
|
|
@@ -20,17 +42,71 @@ const obj = require('./core/obj');
|
|
|
20
42
|
const random = require('./core/random');
|
|
21
43
|
const thread = require('./core/thread');
|
|
22
44
|
const validate = require('./core/validate');
|
|
23
|
-
const code = require('./http/code');
|
|
24
|
-
const err = require('./http/error');
|
|
25
|
-
const params = require('./http/params');
|
|
26
|
-
const context = require('./http/context');
|
|
27
|
-
const gridfs = require('./db/gridfs');
|
|
28
45
|
|
|
46
|
+
// Tools
|
|
29
47
|
const { gen_i18n } = require('./tool/gen_i18n');
|
|
30
|
-
const { log_debug, log_info, log_warn, log_error, is_log_debug, is_log_info, is_log_warn, is_log_error, get_session_userid, oid_queries, oid_query } = require('./db/db');
|
|
31
48
|
|
|
32
49
|
module.exports = {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
50
|
+
// Settings
|
|
51
|
+
init_settings,
|
|
52
|
+
|
|
53
|
+
// Express Server
|
|
54
|
+
init_express_server,
|
|
55
|
+
init_router,
|
|
56
|
+
|
|
57
|
+
// Database
|
|
58
|
+
get_db,
|
|
59
|
+
Entity,
|
|
60
|
+
oid_queries,
|
|
61
|
+
oid_query,
|
|
62
|
+
gridfs,
|
|
63
|
+
|
|
64
|
+
// Logging
|
|
65
|
+
log_debug,
|
|
66
|
+
log_info,
|
|
67
|
+
log_warn,
|
|
68
|
+
log_error,
|
|
69
|
+
is_log_debug,
|
|
70
|
+
is_log_info,
|
|
71
|
+
is_log_warn,
|
|
72
|
+
is_log_error,
|
|
73
|
+
|
|
74
|
+
// Type System
|
|
75
|
+
register_type,
|
|
76
|
+
get_type,
|
|
77
|
+
EntityMeta,
|
|
78
|
+
get_entity_meta,
|
|
79
|
+
|
|
80
|
+
// Role & Auth
|
|
81
|
+
is_root_role,
|
|
82
|
+
is_root_user,
|
|
83
|
+
check_user_role,
|
|
84
|
+
get_user_role_right,
|
|
85
|
+
get_session_user,
|
|
86
|
+
get_session_user_id,
|
|
87
|
+
|
|
88
|
+
// HTTP Utilities
|
|
89
|
+
url,
|
|
90
|
+
code,
|
|
91
|
+
err,
|
|
92
|
+
params,
|
|
93
|
+
context,
|
|
94
|
+
|
|
95
|
+
// Core Utilities
|
|
96
|
+
array,
|
|
97
|
+
bash,
|
|
98
|
+
chart,
|
|
99
|
+
cron,
|
|
100
|
+
date,
|
|
101
|
+
file,
|
|
102
|
+
lhs,
|
|
103
|
+
msg,
|
|
104
|
+
number,
|
|
105
|
+
obj,
|
|
106
|
+
random,
|
|
107
|
+
thread,
|
|
108
|
+
validate,
|
|
109
|
+
|
|
110
|
+
// Tools
|
|
111
|
+
gen_i18n
|
|
36
112
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hola-server",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "a meta programming framework used to build nodejs restful api",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -43,4 +43,4 @@
|
|
|
43
43
|
"url": "https://github.com/hery-node/hola-server/issues"
|
|
44
44
|
},
|
|
45
45
|
"homepage": "https://github.com/hery-node/hola-server#readme"
|
|
46
|
-
}
|
|
46
|
+
}
|
package/router/clone.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Entity clone router handlers.
|
|
3
|
+
* @module router/clone
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const { set_file_fields, save_file_fields_to_db } = require('../db/gridfs');
|
|
2
7
|
const { SUCCESS, NO_PARAMS, NO_RIGHTS } = require('../http/code');
|
|
3
|
-
const {
|
|
8
|
+
const { get_session_user_id, is_owner } = require('../http/session');
|
|
4
9
|
const { wrap_http } = require('../http/error');
|
|
5
10
|
const { post_params, required_post_params } = require('../http/params');
|
|
6
11
|
const { has_value } = require('../core/validate');
|
|
@@ -12,62 +17,49 @@ const multer = require('multer');
|
|
|
12
17
|
const upload_file = multer({ dest: 'file_tmp/' });
|
|
13
18
|
|
|
14
19
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {
|
|
20
|
+
* Initialize clone router for entity.
|
|
21
|
+
* @param {Object} router - Express router
|
|
22
|
+
* @param {Object} meta - Entity metadata
|
|
18
23
|
*/
|
|
19
|
-
const init_clone_router =
|
|
24
|
+
const init_clone_router = (router, meta) => {
|
|
20
25
|
const entity = new Entity(meta);
|
|
21
26
|
const cp_upload = meta.upload_fields.length > 0 ? upload_file.fields(meta.upload_fields) : upload_file.none();
|
|
22
27
|
|
|
23
|
-
router.post('/clone', cp_upload, wrap_http(async
|
|
24
|
-
|
|
25
|
-
let { _view } = post_params(req, ["_view"]);
|
|
26
|
-
if (!_view) {
|
|
27
|
-
_view = "*";
|
|
28
|
-
}
|
|
28
|
+
router.post('/clone', cp_upload, wrap_http(async (req, res) => {
|
|
29
|
+
const _view = post_params(req, ["_view"])._view || "*";
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
res.json({ code: NO_RIGHTS, err: "no rights error" });
|
|
33
|
-
return;
|
|
31
|
+
if (!check_user_role(req, meta, "o", _view)) {
|
|
32
|
+
return res.json({ code: NO_RIGHTS, err: "no rights to clone" });
|
|
34
33
|
}
|
|
35
34
|
|
|
36
|
-
|
|
37
|
-
if (params
|
|
38
|
-
res.json({ code: NO_PARAMS, err:
|
|
39
|
-
return;
|
|
35
|
+
const params = required_post_params(req, ["_id"]);
|
|
36
|
+
if (!params) {
|
|
37
|
+
return res.json({ code: NO_PARAMS, err: "[_id] required for clone" });
|
|
40
38
|
}
|
|
41
39
|
|
|
42
40
|
const param_obj = post_params(req, meta.field_names);
|
|
43
41
|
set_file_fields(meta, req, param_obj);
|
|
44
42
|
|
|
45
|
-
const query = params
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
res.json({ code: NO_RIGHTS, err: "no rights error" });
|
|
49
|
-
return;
|
|
43
|
+
const query = params._id ? oid_query(params._id) : entity.primary_key_query(param_obj);
|
|
44
|
+
if (!await is_owner(req, meta, entity, query)) {
|
|
45
|
+
return res.json({ code: NO_RIGHTS, err: "no ownership rights" });
|
|
50
46
|
}
|
|
51
47
|
|
|
52
48
|
if (meta.user_field) {
|
|
53
|
-
const user_id =
|
|
54
|
-
if (user_id == null)
|
|
55
|
-
throw new Error("no user is found in session");
|
|
56
|
-
}
|
|
49
|
+
const user_id = get_session_user_id(req);
|
|
50
|
+
if (user_id == null) throw new Error("no user found in session for clone");
|
|
57
51
|
param_obj[meta.user_field] = user_id;
|
|
58
52
|
}
|
|
59
53
|
|
|
60
|
-
const { code, err } = await entity.clone_entity(params
|
|
61
|
-
if (!has_value(code))
|
|
62
|
-
throw new Error("the method should return code");
|
|
63
|
-
}
|
|
54
|
+
const { code, err } = await entity.clone_entity(params._id, param_obj, _view);
|
|
55
|
+
if (!has_value(code)) throw new Error("clone_entity must return code");
|
|
64
56
|
|
|
65
|
-
if (code
|
|
57
|
+
if (code === SUCCESS) {
|
|
66
58
|
await save_file_fields_to_db(meta.collection, meta.file_fields, req, param_obj);
|
|
67
59
|
}
|
|
68
60
|
|
|
69
|
-
res.json({ code
|
|
61
|
+
res.json({ code, err });
|
|
70
62
|
}));
|
|
71
|
-
}
|
|
63
|
+
};
|
|
72
64
|
|
|
73
|
-
module.exports = { init_clone_router }
|
|
65
|
+
module.exports = { init_clone_router };
|
package/router/create.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Create router initialization.
|
|
3
|
+
* @module router/create
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
const { set_file_fields, save_file_fields_to_db } = require('../db/gridfs');
|
|
2
7
|
const { SUCCESS, NO_RIGHTS } = require('../http/code');
|
|
3
|
-
const {
|
|
8
|
+
const { get_session_user_id } = require('../http/session');
|
|
4
9
|
const { wrap_http } = require('../http/error');
|
|
5
10
|
const { post_params } = require('../http/params');
|
|
6
11
|
const { has_value } = require('../core/validate');
|
|
@@ -11,49 +16,39 @@ const multer = require('multer');
|
|
|
11
16
|
const upload_file = multer({ dest: 'file_tmp/' });
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
|
-
*
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {
|
|
19
|
+
* Initialize HTTP create router.
|
|
20
|
+
* @param {Object} router - Express router
|
|
21
|
+
* @param {Object} meta - Entity metadata
|
|
17
22
|
*/
|
|
18
|
-
const init_create_router =
|
|
23
|
+
const init_create_router = (router, meta) => {
|
|
19
24
|
const entity = new Entity(meta);
|
|
20
25
|
const cp_upload = meta.upload_fields.length > 0 ? upload_file.fields(meta.upload_fields) : upload_file.none();
|
|
21
26
|
|
|
22
|
-
router.post('/create', cp_upload, wrap_http(async
|
|
23
|
-
|
|
24
|
-
let { _view } = post_params(req, ["_view"]);
|
|
25
|
-
if (!_view) {
|
|
26
|
-
_view = "*";
|
|
27
|
-
}
|
|
27
|
+
router.post('/create', cp_upload, wrap_http(async (req, res) => {
|
|
28
|
+
const _view = post_params(req, ["_view"])._view || "*";
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
res.json({ code: NO_RIGHTS, err: "no rights error" });
|
|
32
|
-
return;
|
|
30
|
+
if (!check_user_role(req, meta, "c", _view)) {
|
|
31
|
+
return res.json({ code: NO_RIGHTS, err: "no rights" });
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
const param_obj = post_params(req, meta.field_names);
|
|
36
35
|
set_file_fields(meta, req, param_obj);
|
|
37
36
|
|
|
38
37
|
if (meta.user_field) {
|
|
39
|
-
const user_id =
|
|
40
|
-
if (user_id == null)
|
|
41
|
-
throw new Error("no user is found in session");
|
|
42
|
-
}
|
|
38
|
+
const user_id = get_session_user_id(req);
|
|
39
|
+
if (user_id == null) throw new Error("no user found in session");
|
|
43
40
|
param_obj[meta.user_field] = user_id;
|
|
44
41
|
}
|
|
45
42
|
|
|
46
43
|
const { code, err } = await entity.create_entity(param_obj, _view);
|
|
47
|
-
if (!has_value(code))
|
|
48
|
-
throw new Error("the method should return code");
|
|
49
|
-
}
|
|
44
|
+
if (!has_value(code)) throw new Error("create_entity must return code");
|
|
50
45
|
|
|
51
|
-
if (code
|
|
46
|
+
if (code === SUCCESS) {
|
|
52
47
|
await save_file_fields_to_db(meta.collection, meta.file_fields, req, param_obj);
|
|
53
48
|
}
|
|
54
49
|
|
|
55
|
-
res.json({ code
|
|
50
|
+
res.json({ code, err });
|
|
56
51
|
}));
|
|
57
|
-
}
|
|
52
|
+
};
|
|
58
53
|
|
|
59
|
-
module.exports = { init_create_router }
|
|
54
|
+
module.exports = { init_create_router };
|