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.
Files changed (83) hide show
  1. package/README.md +196 -1
  2. package/core/array.js +79 -142
  3. package/core/bash.js +208 -259
  4. package/core/chart.js +26 -16
  5. package/core/cron.js +14 -3
  6. package/core/date.js +15 -44
  7. package/core/encrypt.js +19 -9
  8. package/core/file.js +42 -29
  9. package/core/lhs.js +32 -6
  10. package/core/meta.js +213 -289
  11. package/core/msg.js +20 -7
  12. package/core/number.js +105 -103
  13. package/core/obj.js +15 -12
  14. package/core/random.js +9 -6
  15. package/core/role.js +69 -77
  16. package/core/thread.js +12 -2
  17. package/core/type.js +300 -261
  18. package/core/url.js +20 -12
  19. package/core/validate.js +29 -26
  20. package/db/db.js +297 -227
  21. package/db/entity.js +631 -963
  22. package/db/gridfs.js +120 -166
  23. package/design/add_default_field_attr.md +56 -0
  24. package/http/context.js +22 -8
  25. package/http/cors.js +25 -8
  26. package/http/error.js +27 -9
  27. package/http/express.js +70 -41
  28. package/http/params.js +70 -42
  29. package/http/router.js +51 -40
  30. package/http/session.js +59 -36
  31. package/index.js +85 -9
  32. package/package.json +2 -2
  33. package/router/clone.js +28 -36
  34. package/router/create.js +21 -26
  35. package/router/delete.js +24 -28
  36. package/router/read.js +137 -123
  37. package/router/update.js +38 -56
  38. package/setting.js +22 -6
  39. package/skills/array.md +155 -0
  40. package/skills/bash.md +91 -0
  41. package/skills/chart.md +54 -0
  42. package/skills/code.md +422 -0
  43. package/skills/context.md +177 -0
  44. package/skills/date.md +58 -0
  45. package/skills/express.md +255 -0
  46. package/skills/file.md +60 -0
  47. package/skills/lhs.md +54 -0
  48. package/skills/meta.md +1023 -0
  49. package/skills/msg.md +30 -0
  50. package/skills/number.md +88 -0
  51. package/skills/obj.md +36 -0
  52. package/skills/params.md +206 -0
  53. package/skills/random.md +22 -0
  54. package/skills/role.md +59 -0
  55. package/skills/session.md +281 -0
  56. package/skills/storage.md +743 -0
  57. package/skills/thread.md +22 -0
  58. package/skills/type.md +547 -0
  59. package/skills/url.md +34 -0
  60. package/skills/validate.md +48 -0
  61. package/test/cleanup/close-db.js +5 -0
  62. package/test/core/array.js +226 -0
  63. package/test/core/chart.js +51 -0
  64. package/test/core/file.js +59 -0
  65. package/test/core/lhs.js +44 -0
  66. package/test/core/number.js +167 -12
  67. package/test/core/obj.js +47 -0
  68. package/test/core/random.js +24 -0
  69. package/test/core/thread.js +20 -0
  70. package/test/core/type.js +216 -0
  71. package/test/core/validate.js +67 -0
  72. package/test/db/db-ops.js +99 -0
  73. package/test/db/pipe_test.txt +0 -0
  74. package/test/db/test_case_design.md +528 -0
  75. package/test/db/test_db_class.js +613 -0
  76. package/test/db/test_entity_class.js +414 -0
  77. package/test/db/test_gridfs_class.js +234 -0
  78. package/test/entity/create.js +1 -1
  79. package/test/entity/delete-mixed.js +156 -0
  80. package/test/entity/ref-filter.js +63 -0
  81. package/tool/gen_i18n.js +55 -21
  82. package/test/crud/router.js +0 -99
  83. package/test/router/user.js +0 -17
@@ -0,0 +1,281 @@
1
+ # Session Management Skill
2
+
3
+ ## Overview
4
+
5
+ The `hola-server/http/session.js` module provides session management utilities using `express-session` with MongoDB storage. It includes helpers for accessing session data and checking ownership permissions.
6
+
7
+ ## Importing
8
+
9
+ ```javascript
10
+ const {
11
+ init_session,
12
+ get_session_user_id,
13
+ get_session_user_groups,
14
+ is_owner
15
+ } = require("hola-server/http/session");
16
+ ```
17
+
18
+ ## API Reference
19
+
20
+ ### 1. Session Initialization
21
+
22
+ #### `init_session(app)`
23
+ Initializes session middleware with MongoDB storage.
24
+
25
+ **Called automatically** by `init_express_server()`. You typically don't call this directly.
26
+
27
+ **Configuration:**
28
+ ```javascript
29
+ // settings.json
30
+ {
31
+ "server": {
32
+ "keep_session": true,
33
+ "session": {
34
+ "secret": "your-secret-key-change-in-production",
35
+ "cookie_max_age": 86400000 // 24 hours in ms
36
+ }
37
+ },
38
+ "mongo": {
39
+ "url": "mongodb://localhost:27017/mydb"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ### 2. Session Access
45
+
46
+ #### `get_session_user_id(req)`
47
+ Gets the current user ID from session.
48
+
49
+ **Returns:** `string|null` - User ID or null if not logged in
50
+
51
+ ```javascript
52
+ const { NO_SESSION } = require("hola-server/http/code");
53
+
54
+ const user_id = get_session_user_id(req);
55
+ if (!user_id) {
56
+ return res.json({ code: NO_SESSION });
57
+ }
58
+ ```
59
+
60
+ #### `get_session_user_groups(req)`
61
+ Gets the current user's group IDs from session.
62
+
63
+ **Returns:** `string[]|null` - Array of group IDs or null
64
+
65
+ ```javascript
66
+ const { NO_RIGHTS } = require("hola-server/http/code");
67
+
68
+ const groups = get_session_user_groups(req);
69
+ if (!groups || !groups.includes("admin")) {
70
+ return res.json({ code: NO_RIGHTS });
71
+ }
72
+ ```
73
+
74
+ ### 3. Ownership Checking
75
+
76
+ #### `is_owner(req, meta, entity, query)`
77
+ Checks if the current user owns the entity being accessed.
78
+
79
+ **Parameters:**
80
+ - `req` (Object): Express request
81
+ - `meta` (Object): Entity meta definition
82
+ - `entity` (Entity): Entity instance
83
+ - `query` (Object): MongoDB query for the entity
84
+
85
+ **Returns:** `Promise<boolean>` - True if user is owner or root user
86
+
87
+ ```javascript
88
+ const { NO_RIGHTS } = require("hola-server/http/code");
89
+
90
+ const can_access = await is_owner(req, meta, entity, { _id: req.params.id });
91
+ if (!can_access) {
92
+ return res.json({ code: NO_RIGHTS });
93
+ }
94
+ ```
95
+
96
+ **Logic:**
97
+ 1. Returns `true` if user is root (via `is_root_user()`)
98
+ 2. Returns `true` if meta has no `user_field` defined
99
+ 3. Otherwise, checks if entity's `user_field` matches current user ID
100
+
101
+ ## Session Structure
102
+
103
+ The framework expects sessions to contain:
104
+
105
+ ```javascript
106
+ req.session = {
107
+ user: {
108
+ id: "507f1f77bcf86cd799439011", // User ObjectId
109
+ name: "John Doe",
110
+ role: "admin",
111
+ // ... other user fields
112
+ },
113
+ group: ["group_id_1", "group_id_2"] // Optional: user's group memberships
114
+ };
115
+ ```
116
+
117
+ ## Usage Patterns
118
+
119
+ ### Pattern 1: Login Flow
120
+
121
+ ```javascript
122
+ const { ERROR, SUCCESS } = require("hola-server/http/code");
123
+
124
+ router.post("/login", async (req, res) => {
125
+ const { username, password } = req.body;
126
+
127
+ // Authenticate user
128
+ const user = await authenticate(username, password);
129
+ if (!user) {
130
+ return res.json({ code: ERROR, err: "Invalid credentials" });
131
+ }
132
+
133
+ // Set session
134
+ req.session.user = {
135
+ id: user._id,
136
+ name: user.name,
137
+ email: user.email,
138
+ role: user.role
139
+ };
140
+
141
+ if (user.groups) {
142
+ req.session.group = user.groups;
143
+ }
144
+
145
+ return res.json({ code: SUCCESS, user });
146
+ });
147
+ ```
148
+
149
+ ### Pattern 2: Logout
150
+
151
+ ```javascript
152
+ const { ERROR, SUCCESS } = require("hola-server/http/code");
153
+
154
+ router.post("/logout", (req, res) => {
155
+ req.session.destroy((err) => {
156
+ if (err) {
157
+ return res.json({ code: ERROR, err: "Logout failed" });
158
+ }
159
+ res.json({ code: SUCCESS });
160
+ });
161
+ });
162
+ ```
163
+
164
+ ### Pattern 3: Protected Routes
165
+
166
+ ```javascript
167
+ const { NO_SESSION, SUCCESS } = require("hola-server/http/code");
168
+
169
+ router.get("/profile", async (req, res) => {
170
+ const user_id = get_session_user_id(req);
171
+ if (!user_id) {
172
+ return res.json({ code: NO_SESSION });
173
+ }
174
+
175
+ const user = await user_entity.find_one({ _id: user_id }, {});
176
+ return res.json({ code: SUCCESS, data: user });
177
+ });
178
+ ```
179
+
180
+ ### Pattern 4: Ownership-Based Access
181
+
182
+ ```javascript
183
+ // Meta definition with ownership
184
+ const meta = {
185
+ collection: "document",
186
+ user_field: "owner_id", // Links document to user
187
+ fields: [
188
+ { name: "title", type: "string" },
189
+ { name: "owner_id", ref: "user" }
190
+ ]
191
+ };
192
+
193
+ // Route using ownership check
194
+ const { NO_RIGHTS } = require("hola-server/http/code");
195
+
196
+ router.delete("/:id", async (req, res) => {
197
+ const query = { _id: req.params.id };
198
+ const entity = new Entity(meta);
199
+
200
+ if (!await is_owner(req, meta, entity, query)) {
201
+ return res.json({ code: NO_RIGHTS });
202
+ }
203
+
204
+ const result = await entity.delete_entity([req.params.id]);
205
+ return res.json(result);
206
+ });
207
+ ```
208
+
209
+ ### Pattern 5: Group-Based Access
210
+
211
+ ```javascript
212
+ const { NO_RIGHTS, SUCCESS } = require("hola-server/http/code");
213
+
214
+ router.post("/admin/action", async (req, res) => {
215
+ const groups = get_session_user_groups(req);
216
+
217
+ if (!groups || !groups.includes("admin")) {
218
+ return res.json({ code: NO_RIGHTS });
219
+ }
220
+
221
+ // Perform admin action
222
+ await perform_admin_action(req.body);
223
+ return res.json({ code: SUCCESS });
224
+ });
225
+ ```
226
+
227
+ ### Pattern 6: Auto-Set Owner on Create
228
+
229
+ ```javascript
230
+ const { NO_SESSION } = require("hola-server/http/code");
231
+
232
+ router.post("/document", async (req, res) => {
233
+ const user_id = get_session_user_id(req);
234
+ if (!user_id) {
235
+ return res.json({ code: NO_SESSION });
236
+ }
237
+
238
+ // Automatically set owner
239
+ req.body.owner_id = user_id;
240
+
241
+ const result = await entity.create_entity(req.body, "*");
242
+ return res.json(result);
243
+ });
244
+ ```
245
+
246
+ ## Session Storage
247
+
248
+ Sessions are stored in MongoDB via `connect-mongo`:
249
+ - Collection: `sessions` (created automatically)
250
+ - Expires: Based on `cookie_max_age` setting
251
+ - Cleanup: Automatic (expired sessions removed by MongoDB TTL)
252
+
253
+ ## Best Practices
254
+
255
+ 1. **Always validate session**: Check `get_session_user_id()` in protected routes.
256
+
257
+ 2. **Use secure secrets**: Never commit session secret to version control.
258
+ ```javascript
259
+ // Good: from environment
260
+ "secret": process.env.SESSION_SECRET
261
+
262
+ // Bad: hardcoded
263
+ "secret": "my-secret-123"
264
+ ```
265
+
266
+ 3. **Set appropriate cookie age**: Balance security vs. user convenience.
267
+ ```javascript
268
+ "cookie_max_age": 3600000 // 1 hour for high-security
269
+ "cookie_max_age": 604800000 // 7 days for convenience
270
+ ```
271
+
272
+ 4. **Use HTTPS in production**: Session cookies should use `secure` flag.
273
+
274
+ 5. **Implement ownership where applicable**: Use `user_field` in meta for user-owned data.
275
+
276
+ ## Security Considerations
277
+
278
+ - **Session fixation**: Express-session regenerates session ID on login
279
+ - **XSS protection**: Don't expose session data to client-side JavaScript
280
+ - **CSRF**: Consider adding CSRF tokens for state-changing operations
281
+ - **Session hijacking**: Use HTTPS and secure cookies in production