data-primals-engine 1.6.2-rc1 → 1.6.3
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 +61 -20
- package/client/src/Dashboard.jsx +1 -1
- package/client/src/WorkflowEditor.jsx +101 -0
- package/client/src/WorkflowEditor.scss +29 -4
- package/package.json +145 -142
- package/src/client.js +4 -0
- package/src/defaultModels +1628 -0
- package/src/defaultModels.js +14 -0
- package/src/filter.js +170 -1
- package/src/modules/assistant/assistant.js +38 -56
- package/src/modules/assistant/providers.js +38 -0
- package/src/modules/data/data.history.js +7 -6
- package/src/modules/data/data.operations.js +20 -5
- package/src/modules/user.js +57 -25
- package/src/modules/workflow.js +53 -178
- package/src/providers.js +1 -1
- package/test/assistant.test.js +207 -0
- package/test/config.test.js +41 -0
- package/test/data.history.integration.test.js +144 -20
- package/test/user.test.js +195 -278
- package/test/workflow.integration.test.js +8 -0
package/test/user.test.js
CHANGED
|
@@ -1,315 +1,232 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from
|
|
9
|
-
|
|
10
|
-
let permRead, permWrite, permDelete, permManage;
|
|
11
|
-
let roleEditor;
|
|
12
|
-
let testUser, adminUser, roleViewer;
|
|
13
|
-
let currentTestUser;
|
|
14
|
-
let testModelsColInstance, testDatasColInstance;
|
|
15
|
-
// Cette fonction va remplacer la logique de votre beforeEach pour la création de contexte
|
|
16
|
-
async function setupTestContext() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// Créer un utilisateur unique pour ce test
|
|
20
|
-
const username = generateUniqueName('testuserUserIntegration');
|
|
21
|
-
currentTestUser = {
|
|
22
|
-
username,
|
|
23
|
-
userPlan: 'free',
|
|
24
|
-
_model: 'user',
|
|
25
|
-
_user: username,
|
|
26
|
-
email: generateUniqueName('test') + '@example.com'
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// Initialize collection instances after the engine is ready
|
|
30
|
-
testModelsColInstance = getAppModelsCollection;
|
|
31
|
-
testDatasColInstance = await getAppUserCollection(currentTestUser);
|
|
32
|
-
|
|
33
|
-
await testDatasColInstance.deleteMany({}); // Nettoyage de la base de test
|
|
34
|
-
// 1. Créer les permissions
|
|
35
|
-
const permissions = await testDatasColInstance.insertMany([
|
|
36
|
-
{ _model: 'permission', name: 'post:read', description: 'Lire les articles' },
|
|
37
|
-
{ _model: 'permission', name: 'post:write', description: 'Écrire des articles' },
|
|
38
|
-
{ _model: 'permission', name: 'post:delete', description: 'Supprimer des articles' },
|
|
39
|
-
{ _model: 'permission', name: 'user:manage', description: 'Gérer les utilisateurs' }
|
|
40
|
-
]);
|
|
41
|
-
permRead = permissions.insertedIds[0];
|
|
42
|
-
permWrite = permissions.insertedIds[1];
|
|
43
|
-
permDelete = permissions.insertedIds[2];
|
|
44
|
-
permManage = permissions.insertedIds[3];
|
|
45
|
-
|
|
46
|
-
// 2. Créer les rôles
|
|
47
|
-
const roles = await testDatasColInstance.insertMany([
|
|
48
|
-
{ _user: currentTestUser.username, _model: 'role', name: 'Viewer', permissions: [permRead.toString()] },
|
|
49
|
-
{ _user: currentTestUser.username, _model: 'role', name: 'Editor', permissions: [permRead.toString(), permWrite.toString()] }
|
|
50
|
-
]);
|
|
51
|
-
roleViewer = roles.insertedIds[0];
|
|
52
|
-
roleEditor = roles.insertedIds[1];
|
|
53
|
-
|
|
54
|
-
// 3. Créer les utilisateurs
|
|
55
|
-
const users = await testDatasColInstance.insertMany([
|
|
56
|
-
{ _user: currentTestUser.username, _model: 'user', roles: [roleEditor.toString()] },
|
|
57
|
-
{ _user: currentTestUser.username, _model: 'user', roles: [roleEditor.toString()] }
|
|
58
|
-
]);
|
|
59
|
-
testUser = {...currentTestUser, _id: users.insertedIds[0].toString(), roles: [roleEditor.toString()] };
|
|
60
|
-
adminUser = {...currentTestUser, _id: users.insertedIds[1].toString(), roles: [roleEditor.toString()] };
|
|
61
|
-
|
|
62
|
-
return testDatasColInstance;
|
|
63
|
-
};
|
|
1
|
+
import { vi, describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { ObjectId } from 'mongodb';
|
|
3
|
+
import { hasPermission, onInit } from '../src/modules/user.js';
|
|
4
|
+
import { Config } from '../src/config.js';
|
|
5
|
+
import { initEngine, generateUniqueName } from '../src/setenv.js';
|
|
6
|
+
import { getCollection, getCollectionForUser } from '../src/modules/mongodb.js';
|
|
7
|
+
import { Logger } from '../src/gameObject.js';
|
|
8
|
+
import { insertData, deleteData, deleteModels, createModel } from '../src/index.js';
|
|
9
|
+
|
|
64
10
|
let engine;
|
|
65
|
-
|
|
11
|
+
let logger;
|
|
12
|
+
|
|
13
|
+
describe('User Permission System with Filters', () => {
|
|
14
|
+
let collection;
|
|
15
|
+
let testUser, testUserWithRole, systemUser;
|
|
16
|
+
let permNoFilter, permWithSimpleFilter, permWithUserFilter, permWithReqFilter, permOrderEditForManager;
|
|
17
|
+
let roleWithPerms;
|
|
66
18
|
|
|
67
|
-
// --- SETUP : Création des données de test avant tous les tests ---
|
|
68
19
|
beforeAll(async () => {
|
|
69
|
-
Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow","user", "assistant"
|
|
20
|
+
Config.Set("modules", ["mongodb", "data", "file", "bucket", "workflow", "user", "assistant"]);
|
|
70
21
|
engine = await initEngine();
|
|
71
|
-
|
|
22
|
+
logger = engine.getComponent(Logger);
|
|
23
|
+
await onInit(engine);
|
|
72
24
|
});
|
|
73
25
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
});
|
|
26
|
+
beforeEach(async () => {
|
|
27
|
+
// Utiliser un utilisateur unique pour l'isolation des tests
|
|
28
|
+
const username = generateUniqueName('perm_test_user');
|
|
29
|
+
testUser = { _id: new ObjectId(), username: username, _user: username, roles: [], _model: 'user' };
|
|
30
|
+
testUserWithRole = { _id: new ObjectId(), username: username, _user: username, roles: [], _model: 'user' }; // roles sera ajouté après la création du rôle
|
|
31
|
+
systemUser = { roles: ['admin', 'product.view'] };
|
|
32
|
+
|
|
33
|
+
collection = await getCollectionForUser(testUser);
|
|
34
|
+
await collection.deleteMany({ _user: username });
|
|
35
|
+
|
|
36
|
+
// --- Création des données de test ---
|
|
37
|
+
// 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' }] });
|
|
41
|
+
|
|
42
|
+
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 }
|
|
47
|
+
]);
|
|
48
|
+
permNoFilter = permResult.insertedIds[0];
|
|
49
|
+
permWithSimpleFilter = permResult.insertedIds[1];
|
|
50
|
+
permWithUserFilter = permResult.insertedIds[2];
|
|
51
|
+
permWithReqFilter = permResult.insertedIds[3];
|
|
52
|
+
|
|
53
|
+
const roleResult = await collection.insertOne({
|
|
54
|
+
_model: 'role',
|
|
55
|
+
name: 'Editor',
|
|
56
|
+
permissions: [permNoFilter.toString(), permWithSimpleFilter.toString()],
|
|
57
|
+
_user: username
|
|
58
|
+
});
|
|
59
|
+
roleWithPerms = roleResult.insertedId;
|
|
60
|
+
|
|
61
|
+
// Assigner le rôle à l'utilisateur de test
|
|
62
|
+
testUserWithRole.roles = [roleWithPerms.toString()];
|
|
63
|
+
});
|
|
87
64
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
65
|
+
afterEach(async () => {
|
|
66
|
+
// Nettoyer les données créées
|
|
67
|
+
if (collection) {
|
|
68
|
+
await collection.deleteMany({ _user: testUser.username });
|
|
69
|
+
}
|
|
70
|
+
await deleteModels({ _user: testUser.username });
|
|
71
|
+
});
|
|
93
72
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
isGranted: true,
|
|
99
|
-
expiresAt: futureDate
|
|
100
|
-
});
|
|
73
|
+
it('should return true for a permission without filter granted by a role', async () => {
|
|
74
|
+
const result = await hasPermission('product.view', testUserWithRole);
|
|
75
|
+
expect(result).toBe(true);
|
|
76
|
+
});
|
|
101
77
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
78
|
+
it('should return a simple filter object for a permission with filter granted by a role', async () => {
|
|
79
|
+
const result = await hasPermission('order.edit', testUserWithRole);
|
|
80
|
+
expect(result).toEqual({ status: 'pending' });
|
|
81
|
+
});
|
|
105
82
|
|
|
106
|
-
|
|
107
|
-
|
|
83
|
+
it('should return false if user does not have the permission', async () => {
|
|
84
|
+
const result = await hasPermission('document.edit', testUserWithRole);
|
|
85
|
+
expect(result).toBe(false);
|
|
86
|
+
});
|
|
108
87
|
|
|
109
|
-
|
|
88
|
+
it('should grant a permission with a filter via userPermission exception', async () => {
|
|
89
|
+
await collection.insertOne({
|
|
90
|
+
_model: 'userPermission',
|
|
91
|
+
user: testUser._id.toString(),
|
|
92
|
+
permission: permWithUserFilter.toString(),
|
|
93
|
+
isGranted: true,
|
|
94
|
+
_user: testUser.username
|
|
110
95
|
});
|
|
111
96
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const pastDate = new Date();
|
|
116
|
-
pastDate.setDate(pastDate.getDate() - 1);
|
|
117
|
-
|
|
118
|
-
await coll.insertOne({
|
|
119
|
-
_model: 'userPermission',
|
|
120
|
-
user: testUser._id,
|
|
121
|
-
permission: permDelete,
|
|
122
|
-
isGranted: true,
|
|
123
|
-
expiresAt: pastDate
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const permissions = await getUserActivePermissions(testUser);
|
|
127
|
-
expect(permissions.size).to.equal(2); // Revient la normale
|
|
128
|
-
expect(permissions.has('post:delete')).to.be.false;
|
|
129
|
-
|
|
130
|
-
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
131
|
-
await coll.drop();
|
|
132
|
-
});
|
|
97
|
+
const result = await hasPermission('document.edit', testUser);
|
|
98
|
+
expect(result).toEqual({ createdBy: testUser._id.toString() });
|
|
99
|
+
});
|
|
133
100
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
_model: 'userPermission',
|
|
142
|
-
user: testUser._id,
|
|
143
|
-
permission: permWrite,
|
|
144
|
-
isGranted: false, // Révocation
|
|
145
|
-
expiresAt: futureDate
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
const permissions = await getUserActivePermissions(testUser);
|
|
149
|
-
expect(permissions.size).to.equal(1);
|
|
150
|
-
expect(permissions.has('post:read')).to.be.true;
|
|
151
|
-
expect(permissions.has('post:write')).to.be.false; // La permission a été retirée
|
|
152
|
-
|
|
153
|
-
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
154
|
-
await coll.drop();
|
|
101
|
+
it('should substitute user._id in the filter', async () => {
|
|
102
|
+
await collection.insertOne({
|
|
103
|
+
_model: 'userPermission',
|
|
104
|
+
user: testUserWithRole._id.toString(),
|
|
105
|
+
permission: permWithUserFilter.toString(),
|
|
106
|
+
isGranted: true,
|
|
107
|
+
_user: testUser.username
|
|
155
108
|
});
|
|
156
109
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
// La révocation a expiré, l'utilisateur devrait retrouver son droit d'écriture
|
|
160
|
-
const pastDate = new Date();
|
|
161
|
-
pastDate.setDate(pastDate.getDate() - 1);
|
|
162
|
-
|
|
163
|
-
await coll.insertOne({
|
|
164
|
-
_model: 'userPermission',
|
|
165
|
-
user: testUser._id,
|
|
166
|
-
permission: permWrite,
|
|
167
|
-
isGranted: false,
|
|
168
|
-
expiresAt: pastDate
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const permissions = await getUserActivePermissions(testUser);
|
|
172
|
-
expect(permissions.size).to.equal(2);
|
|
173
|
-
expect(permissions.has('post:write')).to.be.true; // La permission est de retour
|
|
174
|
-
|
|
175
|
-
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
176
|
-
await coll.drop();
|
|
177
|
-
});
|
|
110
|
+
const result = await hasPermission('document.edit', testUserWithRole);
|
|
111
|
+
expect(result).toEqual({ createdBy: testUserWithRole._id.toString() });
|
|
178
112
|
});
|
|
179
113
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
114
|
+
it('should substitute request context variables like req.ip', async () => {
|
|
115
|
+
await collection.insertOne({
|
|
116
|
+
_model: 'userPermission',
|
|
117
|
+
user: testUser._id.toString(),
|
|
118
|
+
permission: permWithReqFilter.toString(),
|
|
119
|
+
isGranted: true,
|
|
120
|
+
_user: testUser.username
|
|
187
121
|
});
|
|
188
122
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
123
|
+
const mockReq = {
|
|
124
|
+
ip: '192.168.1.100',
|
|
125
|
+
query: { from: 'test' },
|
|
126
|
+
body: { name: 'test-body' },
|
|
127
|
+
params: { id: '123' }
|
|
128
|
+
};
|
|
195
129
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
130
|
+
const result = await hasPermission('login.attempt', testUser, null, mockReq);
|
|
131
|
+
expect(result).toEqual({ ip: '192.168.1.100' });
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should revoke a permission from a role via userPermission exception', async () => {
|
|
135
|
+
let result = await hasPermission('order.edit', testUserWithRole);
|
|
136
|
+
expect(result).toEqual({ status: 'pending' });
|
|
202
137
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
138
|
+
await collection.insertOne({
|
|
139
|
+
_model: 'userPermission',
|
|
140
|
+
user: testUserWithRole._id.toString(),
|
|
141
|
+
permission: permWithSimpleFilter.toString(),
|
|
142
|
+
isGranted: false,
|
|
143
|
+
_user: testUser.username
|
|
208
144
|
});
|
|
145
|
+
|
|
146
|
+
result = await hasPermission('order.edit', testUserWithRole);
|
|
147
|
+
expect(result).toBe(false);
|
|
209
148
|
});
|
|
210
149
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
// --- Setup ---
|
|
218
|
-
coll = await setupTestContext();
|
|
219
|
-
user = currentTestUser; // Récupère l'utilisateur du contexte
|
|
220
|
-
|
|
221
|
-
// 1. Créer les permissions
|
|
222
|
-
const perms = await coll.insertMany([
|
|
223
|
-
{ _model: 'permission', name: 'env:read', _user: user.username },
|
|
224
|
-
{ _model: 'permission', name: 'env:write', _user: user.username }
|
|
225
|
-
]);
|
|
226
|
-
permRead = perms.insertedIds[0];
|
|
227
|
-
permWrite = perms.insertedIds[1];
|
|
228
|
-
|
|
229
|
-
// 2. Créer les environnements
|
|
230
|
-
const envs = await coll.insertMany([
|
|
231
|
-
{ _model: 'env', name: 'prod', _user: user.username },
|
|
232
|
-
{ _model: 'env', name: 'staging', _user: user.username }
|
|
233
|
-
]);
|
|
234
|
-
envProdId = envs.insertedIds[0].toString();
|
|
235
|
-
envStagingId = envs.insertedIds[1].toString();
|
|
236
|
-
|
|
237
|
-
// 3. Créer un rôle de base et l'assigner à l'utilisateur
|
|
238
|
-
const role = await coll.insertOne({
|
|
239
|
-
_model: 'role',
|
|
240
|
-
name: 'EnvTester',
|
|
241
|
-
permissions: [permRead.toString()],
|
|
242
|
-
_user: user.username
|
|
243
|
-
});
|
|
244
|
-
await coll.updateOne(
|
|
245
|
-
{ _id: user._id },
|
|
246
|
-
{ $set: { roles: [role.insertedId.toString()] } }
|
|
247
|
-
);
|
|
248
|
-
// Mettre à jour l'objet utilisateur en mémoire
|
|
249
|
-
user.roles = [role.insertedId.toString()];
|
|
250
|
-
user.permissions = ['env:read'];
|
|
150
|
+
it('should override a role filter with a userPermission filter', async () => {
|
|
151
|
+
const permResult = await collection.insertOne({
|
|
152
|
+
_model: 'permission',
|
|
153
|
+
name: 'order.edit',
|
|
154
|
+
filter: { manager_id: '{user._id}' },
|
|
155
|
+
_user: testUser.username
|
|
251
156
|
});
|
|
157
|
+
permOrderEditForManager = permResult.insertedId;
|
|
252
158
|
|
|
253
|
-
|
|
254
|
-
|
|
159
|
+
await collection.insertOne({
|
|
160
|
+
_model: 'userPermission',
|
|
161
|
+
user: testUserWithRole._id.toString(),
|
|
162
|
+
permission: permOrderEditForManager.toString(),
|
|
163
|
+
isGranted: true,
|
|
164
|
+
_user: testUser.username
|
|
255
165
|
});
|
|
256
166
|
|
|
257
|
-
|
|
258
|
-
// Nettoyer les exceptions de permission après chaque test
|
|
259
|
-
await coll.deleteMany({ _model: 'userPermission', user: user._id });
|
|
260
|
-
});
|
|
167
|
+
const result = await hasPermission('order.edit', testUserWithRole);
|
|
261
168
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
_model: 'userPermission', user: user._id, permission: permWrite, isGranted: true
|
|
265
|
-
});
|
|
266
|
-
// L'utilisateur doit avoir la permission dans n'importe quel environnement
|
|
267
|
-
expect(await hasPermission(['env:write'], user, envProdId)).toBe(true);
|
|
268
|
-
expect(await hasPermission(['env:write'], user, envStagingId)).toBe(true);
|
|
269
|
-
expect(await hasPermission(['env:write'], user, null)).toBe(true); // Environnement par défaut
|
|
270
|
-
});
|
|
169
|
+
expect(result).toEqual({ manager_id: testUserWithRole._id.toString() });
|
|
170
|
+
});
|
|
271
171
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
// L'utilisateur ne doit avoir la permission qu'en 'prod'
|
|
277
|
-
expect(await hasPermission(['env:write'], user, envProdId)).toBe(true);
|
|
278
|
-
expect(await hasPermission(['env:write'], user, envStagingId)).toBe(false);
|
|
279
|
-
expect(await hasPermission(['env:write'], user, null)).toBe(false);
|
|
280
|
-
});
|
|
172
|
+
it('should use the filter from userPermission when overriding a permission', async () => {
|
|
173
|
+
// Le rôle donne 'order.edit' avec le filtre { status: 'pending' }
|
|
174
|
+
let result = await hasPermission('order.edit', testUserWithRole);
|
|
175
|
+
expect(result).toEqual({ status: 'pending' });
|
|
281
176
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
177
|
+
// On ajoute une exception qui accorde la même permission mais avec un filtre différent
|
|
178
|
+
await collection.insertOne({
|
|
179
|
+
_model: 'userPermission',
|
|
180
|
+
user: testUserWithRole._id.toString(),
|
|
181
|
+
permission: permWithSimpleFilter.toString(), // La permission 'order.edit'
|
|
182
|
+
isGranted: true,
|
|
183
|
+
filter: { "assignedTo": "{user._id}" }, // Le nouveau filtre
|
|
184
|
+
_user: testUser.username
|
|
290
185
|
});
|
|
291
186
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// La permission de lecture ne doit être révoquée qu'en 'staging'
|
|
297
|
-
expect(await hasPermission(['env:read'], user, envProdId)).toBe(true);
|
|
298
|
-
expect(await hasPermission(['env:read'], user, envStagingId)).toBe(false);
|
|
299
|
-
expect(await hasPermission(['env:read'], user, null)).toBe(true);
|
|
300
|
-
});
|
|
187
|
+
// La fonction doit maintenant retourner le filtre de l'exception
|
|
188
|
+
result = await hasPermission('order.edit', testUserWithRole);
|
|
189
|
+
expect(result).toEqual({ assignedTo: testUserWithRole._id.toString() });
|
|
190
|
+
});
|
|
301
191
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
192
|
+
it('should fallback to base permission filter if userPermission has no filter', async () => {
|
|
193
|
+
// On accorde 'document.edit' (qui a un filtre { createdBy: '{user._id}' })
|
|
194
|
+
// via une exception qui n'a PAS de filtre personnalisé.
|
|
195
|
+
await collection.insertOne({
|
|
196
|
+
_model: 'userPermission',
|
|
197
|
+
user: testUser._id.toString(),
|
|
198
|
+
permission: permWithUserFilter.toString(), // La permission 'document.edit'
|
|
199
|
+
isGranted: true,
|
|
200
|
+
// Pas de champ 'filter' ici
|
|
201
|
+
_user: testUser.username
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
// La fonction doit retourner le filtre de la permission de base.
|
|
205
|
+
const result = await hasPermission('document.edit', testUser);
|
|
206
|
+
expect(result).toEqual({ createdBy: testUser._id.toString() });
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should handle non-local users correctly', async () => {
|
|
210
|
+
let result = await hasPermission('product.view', systemUser);
|
|
211
|
+
expect(result).toBe(true);
|
|
212
|
+
|
|
213
|
+
result = await hasPermission('order.edit', systemUser);
|
|
214
|
+
expect(result).toBe(false);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
it('should return false and log an error if an exception occurs', async ({skip}) => {
|
|
218
|
+
// Pour simuler une erreur, on peut essayer de requêter avec un utilisateur invalide
|
|
219
|
+
// ou mocker une fonction interne pour qu'elle échoue.
|
|
220
|
+
const getCollectionForUserSpy = vi.spyOn(await import('../src/modules/mongodb.js'), 'getCollectionForUser');
|
|
221
|
+
getCollectionForUserSpy.mockRejectedValueOnce(new Error("DB connection failed"));
|
|
222
|
+
const errorSpy = vi.spyOn(logger, 'error');
|
|
223
|
+
|
|
224
|
+
const result = await hasPermission('product.view', testUserWithRole);
|
|
225
|
+
|
|
226
|
+
expect(result).toBe(false);
|
|
227
|
+
expect(errorSpy).toHaveBeenCalledWith("Erreur lors de la vérification des permissions :", expect.any(Error));
|
|
228
|
+
|
|
229
|
+
getCollectionForUserSpy.mockRestore();
|
|
230
|
+
errorSpy.mockRestore();
|
|
314
231
|
});
|
|
315
232
|
});
|
|
@@ -207,6 +207,14 @@ describe('Intégration des Workflows - triggerWorkflows', () => {
|
|
|
207
207
|
expect(workflowRun.contextData.triggerData._id.toString()).toBe(insertResult.insertedIds[0].toString());
|
|
208
208
|
expect(workflowRun.contextData.triggerData.projectName).toBe('New Corp Website');
|
|
209
209
|
|
|
210
|
+
// --- Vérification du champ 'history' ---
|
|
211
|
+
expect(workflowRun.history).toBeDefined();
|
|
212
|
+
expect(Array.isArray(workflowRun.history)).toBe(true);
|
|
213
|
+
expect(workflowRun.history.length).toBeGreaterThan(0);
|
|
214
|
+
const firstStepHistory = workflowRun.history[0];
|
|
215
|
+
expect(firstStepHistory.stepId).toBe(testStep._id.toString());
|
|
216
|
+
expect(firstStepHistory.status).toBe('success');
|
|
217
|
+
|
|
210
218
|
});
|
|
211
219
|
|
|
212
220
|
it('ne devrait PAS créer de workflowRun si le trigger est inactif', async () => {
|