data-primals-engine 1.6.3 → 1.7.0
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 +52 -900
- package/client/index.js +3 -0
- package/client/package-lock.json +7563 -8811
- package/client/package.json +11 -1
- package/client/src/App.scss +29 -0
- package/client/src/AssistantChat.jsx +369 -362
- package/client/src/DataEditor.jsx +383 -383
- package/client/src/DataLayout.jsx +54 -20
- package/client/src/ModelList.jsx +280 -280
- package/client/src/ViewSwitcher.scss +0 -31
- package/client/src/_variables.scss +3 -0
- package/client/src/constants.js +81 -100
- package/client/src/contexts/CommandContext.jsx +274 -259
- package/client/vite.config.js +30 -30
- package/doc/AI-assistance.md +93 -0
- package/doc/Advanced-workflows.md +90 -0
- package/doc/Event-system.md +79 -0
- package/doc/Packs-gallery.md +73 -0
- package/doc/automation-workflows.md +102 -0
- package/doc/core-concepts.md +33 -0
- package/doc/custom-api-endpoints.md +40 -0
- package/doc/dashboards-kpis-charts.md +49 -0
- package/doc/data-management.md +120 -0
- package/doc/data-models.md +75 -0
- package/doc/index.md +14 -0
- package/doc/roles-permissions.md +43 -0
- package/doc/users.md +30 -0
- package/package.json +20 -10
- package/src/client.js +6 -4
- package/src/constants.js +1 -1
- package/src/core.js +31 -12
- package/src/defaultModels.js +1 -1
- package/src/engine.js +342 -335
- package/src/filter.js +72 -173
- package/src/migrate.js +1 -1
- package/src/modules/assistant/assistant.js +30 -20
- package/src/modules/data/data.backup.js +4 -4
- package/src/modules/data/data.js +8 -7
- package/src/modules/data/data.operations.js +186 -133
- package/src/modules/data/data.relations.js +3 -2
- package/src/modules/data/data.scheduling.js +1 -1
- package/src/modules/mongodb.js +17 -8
- package/src/modules/swagger.js +25 -5
- package/src/modules/user.js +108 -79
- package/src/modules/workflow.js +138 -3
- package/src/packs.js +5697 -5697
- package/src/profiles.js +19 -0
- package/swagger-en.yml +3391 -1550
- package/swagger-fr.yml +3385 -2896
- package/test/assistant.test.js +2 -2
- package/test/core.test.js +341 -0
- package/test/data.backup.integration.test.js +3 -1
- package/test/data.history.integration.test.js +0 -1
- package/test/data.integration.test.js +137 -2
- package/test/user.test.js +33 -29
package/test/user.test.js
CHANGED
|
@@ -16,34 +16,39 @@ describe('User Permission System with Filters', () => {
|
|
|
16
16
|
let permNoFilter, permWithSimpleFilter, permWithUserFilter, permWithReqFilter, permOrderEditForManager;
|
|
17
17
|
let roleWithPerms;
|
|
18
18
|
|
|
19
|
+
// Le parent qui possède les définitions de rôles et permissions
|
|
20
|
+
const parentUser = { username: generateUniqueName('perm_parent_user') };
|
|
21
|
+
|
|
19
22
|
beforeAll(async () => {
|
|
20
23
|
Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow", "user", "assistant"]);
|
|
21
24
|
engine = await initEngine();
|
|
22
25
|
logger = engine.getComponent(Logger);
|
|
23
26
|
await onInit(engine);
|
|
27
|
+
// La collection est celle du parent, car c'est lui qui stocke les définitions
|
|
28
|
+
collection = await getCollectionForUser(parentUser);
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
beforeEach(async () => {
|
|
27
32
|
// Utiliser un utilisateur unique pour l'isolation des tests
|
|
28
33
|
const username = generateUniqueName('perm_test_user');
|
|
29
|
-
|
|
30
|
-
|
|
34
|
+
// L'utilisateur de test est un "enfant" de parentUser
|
|
35
|
+
testUser = { _id: new ObjectId(), username: username, _user: parentUser.username, roles: [], _model: 'user' };
|
|
36
|
+
testUserWithRole = { _id: new ObjectId(), username: username, _user: parentUser.username, roles: [], _model: 'user' };
|
|
31
37
|
systemUser = { roles: ['admin', 'product.view'] };
|
|
32
38
|
|
|
33
|
-
collection
|
|
34
|
-
await collection.deleteMany({ _user: username });
|
|
39
|
+
await collection.deleteMany({ _user: parentUser.username });
|
|
35
40
|
|
|
36
41
|
// --- Création des données de test ---
|
|
37
42
|
// Créer les modèles nécessaires pour les permissions et les rôles
|
|
38
|
-
await createModel({ name: 'permission', _user: username, fields: [{ name: 'name', type: 'string' }, { name: 'filter', type: 'code' }] });
|
|
39
|
-
await createModel({ name: 'role', _user: username, fields: [{ name: 'name', type: 'string' }, { name: 'permissions', type: 'relation', relation: 'permission', multiple: true }] });
|
|
40
|
-
await createModel({ name: 'userPermission', _user: username, fields: [{ name: 'user', type: 'relation', relation: 'user' }, { name: 'permission', type: 'relation', relation: 'permission' }, { name: 'isGranted', type: 'boolean' }, { name: 'filter', type: 'code' }] });
|
|
43
|
+
await createModel({ name: 'permission', description: '', _user: parentUser.username, fields: [{ name: 'name', type: 'string' }, { name: 'filter', type: 'code' }] });
|
|
44
|
+
await createModel({ name: 'role', description: '', _user: parentUser.username, fields: [{ name: 'name', type: 'string' }, { name: 'permissions', type: 'relation', relation: 'permission', multiple: true }] });
|
|
45
|
+
await createModel({ name: 'userPermission', description: '', _user: parentUser.username, fields: [{ name: 'user', type: 'relation', relation: 'user' }, { name: 'permission', type: 'relation', relation: 'permission' }, { name: 'isGranted', type: 'boolean' }, { name: 'filter', type: 'code',language:'json' }] });
|
|
41
46
|
|
|
42
47
|
const permResult = await collection.insertMany([
|
|
43
|
-
{ _model: 'permission', name: 'product.view', _user: username },
|
|
44
|
-
{ _model: 'permission', name: 'order.edit', filter: { status: 'pending' }, _user: username },
|
|
45
|
-
{ _model: 'permission', name: 'document.edit', filter: { createdBy: '{user._id}' }, _user: username },
|
|
46
|
-
{ _model: 'permission', name: 'login.attempt', filter: { "ip": "{req.ip}" }, _user: username }
|
|
48
|
+
{ _model: 'permission', name: 'product.view', _user: parentUser.username },
|
|
49
|
+
{ _model: 'permission', name: 'order.edit', filter: { status: 'pending' }, _user: parentUser.username },
|
|
50
|
+
{ _model: 'permission', name: 'document.edit', filter: { createdBy: '{user._id}' }, _user: parentUser.username },
|
|
51
|
+
{ _model: 'permission', name: 'login.attempt', filter: { "ip": "{req.ip}" }, _user: parentUser.username }
|
|
47
52
|
]);
|
|
48
53
|
permNoFilter = permResult.insertedIds[0];
|
|
49
54
|
permWithSimpleFilter = permResult.insertedIds[1];
|
|
@@ -54,7 +59,7 @@ describe('User Permission System with Filters', () => {
|
|
|
54
59
|
_model: 'role',
|
|
55
60
|
name: 'Editor',
|
|
56
61
|
permissions: [permNoFilter.toString(), permWithSimpleFilter.toString()],
|
|
57
|
-
_user: username
|
|
62
|
+
_user: parentUser.username
|
|
58
63
|
});
|
|
59
64
|
roleWithPerms = roleResult.insertedId;
|
|
60
65
|
|
|
@@ -65,9 +70,9 @@ describe('User Permission System with Filters', () => {
|
|
|
65
70
|
afterEach(async () => {
|
|
66
71
|
// Nettoyer les données créées
|
|
67
72
|
if (collection) {
|
|
68
|
-
await collection.deleteMany({ _user:
|
|
73
|
+
await collection.deleteMany({ _user: parentUser.username });
|
|
69
74
|
}
|
|
70
|
-
await deleteModels({ _user:
|
|
75
|
+
await deleteModels({ _user: parentUser.username });
|
|
71
76
|
});
|
|
72
77
|
|
|
73
78
|
it('should return true for a permission without filter granted by a role', async () => {
|
|
@@ -91,7 +96,7 @@ describe('User Permission System with Filters', () => {
|
|
|
91
96
|
user: testUser._id.toString(),
|
|
92
97
|
permission: permWithUserFilter.toString(),
|
|
93
98
|
isGranted: true,
|
|
94
|
-
_user:
|
|
99
|
+
_user: parentUser.username
|
|
95
100
|
});
|
|
96
101
|
|
|
97
102
|
const result = await hasPermission('document.edit', testUser);
|
|
@@ -104,7 +109,7 @@ describe('User Permission System with Filters', () => {
|
|
|
104
109
|
user: testUserWithRole._id.toString(),
|
|
105
110
|
permission: permWithUserFilter.toString(),
|
|
106
111
|
isGranted: true,
|
|
107
|
-
_user:
|
|
112
|
+
_user: parentUser.username
|
|
108
113
|
});
|
|
109
114
|
|
|
110
115
|
const result = await hasPermission('document.edit', testUserWithRole);
|
|
@@ -117,7 +122,7 @@ describe('User Permission System with Filters', () => {
|
|
|
117
122
|
user: testUser._id.toString(),
|
|
118
123
|
permission: permWithReqFilter.toString(),
|
|
119
124
|
isGranted: true,
|
|
120
|
-
_user:
|
|
125
|
+
_user: parentUser.username
|
|
121
126
|
});
|
|
122
127
|
|
|
123
128
|
const mockReq = {
|
|
@@ -134,14 +139,14 @@ describe('User Permission System with Filters', () => {
|
|
|
134
139
|
it('should revoke a permission from a role via userPermission exception', async () => {
|
|
135
140
|
let result = await hasPermission('order.edit', testUserWithRole);
|
|
136
141
|
expect(result).toEqual({ status: 'pending' });
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
142
|
+
|
|
143
|
+
// Utiliser insertData pour déclencher l'invalidation du cache
|
|
144
|
+
await insertData('userPermission', {
|
|
140
145
|
user: testUserWithRole._id.toString(),
|
|
141
146
|
permission: permWithSimpleFilter.toString(),
|
|
142
147
|
isGranted: false,
|
|
143
|
-
|
|
144
|
-
|
|
148
|
+
}, {}, parentUser, true, true, false // le dernier false pour bypasser la vérification de permission pour le test
|
|
149
|
+
);
|
|
145
150
|
|
|
146
151
|
result = await hasPermission('order.edit', testUserWithRole);
|
|
147
152
|
expect(result).toBe(false);
|
|
@@ -152,7 +157,7 @@ describe('User Permission System with Filters', () => {
|
|
|
152
157
|
_model: 'permission',
|
|
153
158
|
name: 'order.edit',
|
|
154
159
|
filter: { manager_id: '{user._id}' },
|
|
155
|
-
_user:
|
|
160
|
+
_user: parentUser.username
|
|
156
161
|
});
|
|
157
162
|
permOrderEditForManager = permResult.insertedId;
|
|
158
163
|
|
|
@@ -161,7 +166,7 @@ describe('User Permission System with Filters', () => {
|
|
|
161
166
|
user: testUserWithRole._id.toString(),
|
|
162
167
|
permission: permOrderEditForManager.toString(),
|
|
163
168
|
isGranted: true,
|
|
164
|
-
_user:
|
|
169
|
+
_user: parentUser.username
|
|
165
170
|
});
|
|
166
171
|
|
|
167
172
|
const result = await hasPermission('order.edit', testUserWithRole);
|
|
@@ -175,14 +180,13 @@ describe('User Permission System with Filters', () => {
|
|
|
175
180
|
expect(result).toEqual({ status: 'pending' });
|
|
176
181
|
|
|
177
182
|
// On ajoute une exception qui accorde la même permission mais avec un filtre différent
|
|
178
|
-
|
|
179
|
-
|
|
183
|
+
// Utiliser insertData pour s'assurer que le cache est invalidé
|
|
184
|
+
await insertData('userPermission', {
|
|
180
185
|
user: testUserWithRole._id.toString(),
|
|
181
186
|
permission: permWithSimpleFilter.toString(), // La permission 'order.edit'
|
|
182
187
|
isGranted: true,
|
|
183
188
|
filter: { "assignedTo": "{user._id}" }, // Le nouveau filtre
|
|
184
|
-
|
|
185
|
-
});
|
|
189
|
+
}, {}, parentUser, true, true, false);
|
|
186
190
|
|
|
187
191
|
// La fonction doit maintenant retourner le filtre de l'exception
|
|
188
192
|
result = await hasPermission('order.edit', testUserWithRole);
|
|
@@ -198,7 +202,7 @@ describe('User Permission System with Filters', () => {
|
|
|
198
202
|
permission: permWithUserFilter.toString(), // La permission 'document.edit'
|
|
199
203
|
isGranted: true,
|
|
200
204
|
// Pas de champ 'filter' ici
|
|
201
|
-
_user:
|
|
205
|
+
_user: parentUser.username
|
|
202
206
|
});
|
|
203
207
|
|
|
204
208
|
// La fonction doit retourner le filtre de la permission de base.
|