data-primals-engine 1.2.2 → 1.2.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/client/src/DataEditor.jsx +1 -202
- package/client/src/DataTable.jsx +1 -1
- package/client/src/constants.js +1 -1
- package/package.json +1 -1
- package/src/constants.js +2 -2
- package/src/defaultModels.js +1 -14
- package/src/email.js +7 -5
- package/src/engine.js +2 -1
- package/src/events.js +1 -1
- package/src/filter.js +221 -0
- package/src/modules/data.js +9 -9
- package/src/modules/workflow.js +266 -100
- package/src/packs.js +245 -7
- package/test/data.backup.integration.test.js +4 -1
- package/test/data.integration.test.js +10 -4
- package/test/file.test.js +11 -14
- package/test/import_export.integration.test.js +23 -19
- package/test/model.integration.test.js +20 -19
- package/test/user.test.js +30 -23
- package/test/vm.test.js +51 -0
- package/test/workflow.integration.test.js +6 -1
- package/test/workflow.robustness.test.js +6 -1
package/test/user.test.js
CHANGED
|
@@ -17,7 +17,7 @@ async function setupTestContext() {
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
// Créer un utilisateur unique pour ce test
|
|
20
|
-
const username = generateUniqueName('
|
|
20
|
+
const username = generateUniqueName('testuserUserIntegration');
|
|
21
21
|
currentTestUser = {
|
|
22
22
|
username,
|
|
23
23
|
userPlan: 'free',
|
|
@@ -58,6 +58,8 @@ async function setupTestContext() {
|
|
|
58
58
|
]);
|
|
59
59
|
testUser = {...currentTestUser, _id: users.insertedIds[0].toString(), roles: [roleEditor.toString()] };
|
|
60
60
|
adminUser = {...currentTestUser, _id: users.insertedIds[1].toString(), roles: [roleEditor.toString()] };
|
|
61
|
+
|
|
62
|
+
return testDatasColInstance;
|
|
61
63
|
};
|
|
62
64
|
let engine;
|
|
63
65
|
describe('User Permission Logic', () => {
|
|
@@ -72,26 +74,24 @@ describe('User Permission Logic', () => {
|
|
|
72
74
|
// --- Tests pour la fonction principale de calcul ---
|
|
73
75
|
describe('getUserActivePermissions()', () => {
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
beforeEach(async () =>{
|
|
77
|
-
await setupTestContext();
|
|
78
|
-
})
|
|
79
77
|
it('should return base permissions from the user\'s role', async () => {
|
|
78
|
+
const coll = await setupTestContext();
|
|
80
79
|
const permissions = await getUserActivePermissions(testUser);
|
|
81
80
|
expect(permissions).to.be.an.instanceOf(Set);
|
|
82
81
|
expect(permissions.size).to.equal(2);
|
|
83
82
|
expect(permissions.has('post:read')).to.be.true;
|
|
84
83
|
expect(permissions.has('post:write')).to.be.true;
|
|
85
84
|
expect(permissions.has('post:delete')).to.be.false;
|
|
85
|
+
await coll.drop();
|
|
86
86
|
});
|
|
87
87
|
|
|
88
88
|
it('should grant a temporary permission via an exception', async () => {
|
|
89
|
-
|
|
89
|
+
const coll = await setupTestContext();
|
|
90
90
|
// Ajoute une exception qui donne la permission de supprimer, expirant demain
|
|
91
91
|
const futureDate = new Date();
|
|
92
92
|
futureDate.setDate(futureDate.getDate() + 1);
|
|
93
93
|
|
|
94
|
-
await
|
|
94
|
+
await coll.insertOne({
|
|
95
95
|
_model: 'userPermission',
|
|
96
96
|
user: testUser._id,
|
|
97
97
|
permission: permDelete,
|
|
@@ -104,15 +104,18 @@ describe('User Permission Logic', () => {
|
|
|
104
104
|
expect(permissions.has('post:delete')).to.be.true;
|
|
105
105
|
|
|
106
106
|
// Nettoyage de l'exception pour ne pas affecter les autres tests
|
|
107
|
-
await
|
|
107
|
+
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
108
|
+
|
|
109
|
+
await coll.drop();
|
|
108
110
|
});
|
|
109
111
|
|
|
110
112
|
it('should NOT grant an expired temporary permission', async () => {
|
|
113
|
+
const coll = await setupTestContext();
|
|
111
114
|
// Ajoute une exception qui a expiré hier
|
|
112
115
|
const pastDate = new Date();
|
|
113
116
|
pastDate.setDate(pastDate.getDate() - 1);
|
|
114
117
|
|
|
115
|
-
await
|
|
118
|
+
await coll.insertOne({
|
|
116
119
|
_model: 'userPermission',
|
|
117
120
|
user: testUser._id,
|
|
118
121
|
permission: permDelete,
|
|
@@ -124,15 +127,17 @@ describe('User Permission Logic', () => {
|
|
|
124
127
|
expect(permissions.size).to.equal(2); // Revient la normale
|
|
125
128
|
expect(permissions.has('post:delete')).to.be.false;
|
|
126
129
|
|
|
127
|
-
await
|
|
130
|
+
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
131
|
+
await coll.drop();
|
|
128
132
|
});
|
|
129
133
|
|
|
130
134
|
it('should revoke a base permission via an exception', async () => {
|
|
135
|
+
const coll = await setupTestContext();
|
|
131
136
|
// L'utilisateur est "Editor", mais on lui retire le droit d'écriture temporairement
|
|
132
137
|
const futureDate = new Date();
|
|
133
138
|
futureDate.setDate(futureDate.getDate() + 1);
|
|
134
139
|
|
|
135
|
-
await
|
|
140
|
+
await coll.insertOne({
|
|
136
141
|
_model: 'userPermission',
|
|
137
142
|
user: testUser._id,
|
|
138
143
|
permission: permWrite,
|
|
@@ -145,15 +150,17 @@ describe('User Permission Logic', () => {
|
|
|
145
150
|
expect(permissions.has('post:read')).to.be.true;
|
|
146
151
|
expect(permissions.has('post:write')).to.be.false; // La permission a été retirée
|
|
147
152
|
|
|
148
|
-
await
|
|
153
|
+
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
154
|
+
await coll.drop();
|
|
149
155
|
});
|
|
150
156
|
|
|
151
157
|
it('should restore a revoked permission if the revocation has expired', async () => {
|
|
158
|
+
const coll = await setupTestContext();
|
|
152
159
|
// La révocation a expiré, l'utilisateur devrait retrouver son droit d'écriture
|
|
153
160
|
const pastDate = new Date();
|
|
154
161
|
pastDate.setDate(pastDate.getDate() - 1);
|
|
155
162
|
|
|
156
|
-
await
|
|
163
|
+
await coll.insertOne({
|
|
157
164
|
_model: 'userPermission',
|
|
158
165
|
user: testUser._id,
|
|
159
166
|
permission: permWrite,
|
|
@@ -165,39 +172,39 @@ describe('User Permission Logic', () => {
|
|
|
165
172
|
expect(permissions.size).to.equal(2);
|
|
166
173
|
expect(permissions.has('post:write')).to.be.true; // La permission est de retour
|
|
167
174
|
|
|
168
|
-
await
|
|
175
|
+
await coll.deleteOne({ _model: 'userPermission', user: testUser._id });
|
|
176
|
+
await coll.drop();
|
|
169
177
|
});
|
|
170
178
|
});
|
|
171
179
|
|
|
172
180
|
// --- Tests pour la fonction publique `hasPermission` ---
|
|
173
181
|
describe('hasPermission()', () => {
|
|
174
|
-
beforeEach(async () => {
|
|
175
|
-
await setupTestContext();
|
|
176
|
-
});
|
|
177
182
|
it('should return true for a permission the user has', async () => {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
console.log(await testDatasColInstance.find({ _model: 'permission' }).toArray());
|
|
181
|
-
console.log(await testDatasColInstance.find({ _model: 'role' }).toArray());
|
|
182
|
-
console.log(await testDatasColInstance.find({ _model: 'user' }).toArray());
|
|
183
|
-
console.log(await testDatasColInstance.find({ _model: 'userPermission' }).toArray());
|
|
183
|
+
const coll = await setupTestContext();
|
|
184
184
|
const result = await hasPermission('post:read', testUser);
|
|
185
185
|
expect(result).to.be.true;
|
|
186
|
+
await coll.drop();
|
|
186
187
|
});
|
|
187
188
|
|
|
188
189
|
it('should return false for a permission the user does not have', async () => {
|
|
190
|
+
const coll = await setupTestContext();
|
|
189
191
|
const result = await hasPermission('user:manage', testUser);
|
|
190
192
|
expect(result).to.be.false;
|
|
193
|
+
await coll.drop();
|
|
191
194
|
});
|
|
192
195
|
|
|
193
196
|
it('should return true if user has at least one of the required permissions', async () => {
|
|
197
|
+
const coll = await setupTestContext();
|
|
194
198
|
const result = await hasPermission(['user:manage', 'post:write'], testUser);
|
|
195
199
|
expect(result).to.be.true;
|
|
200
|
+
await coll.drop();
|
|
196
201
|
});
|
|
197
202
|
|
|
198
203
|
it('should return false if user has none of the required permissions', async () => {
|
|
204
|
+
const coll = await setupTestContext();
|
|
199
205
|
const result = await hasPermission(['user:manage', 'post:delete'], testUser);
|
|
200
206
|
expect(result).to.be.false;
|
|
207
|
+
await coll.drop();
|
|
201
208
|
});
|
|
202
209
|
});
|
|
203
210
|
});
|
package/test/vm.test.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {expect, describe, it, beforeEach, afterEach, beforeAll, afterAll, vi, vitest} from 'vitest';
|
|
2
|
+
import ivm from "isolated-vm";
|
|
3
|
+
import {sleep} from "data-primals-engine/core";
|
|
4
|
+
|
|
5
|
+
vi.stubEnv('ENCRYPTION_KEY', '12345678901234567890123456789012');
|
|
6
|
+
|
|
7
|
+
async function executeSafeJavascript() {
|
|
8
|
+
const isolate = new ivm.Isolate()
|
|
9
|
+
|
|
10
|
+
async function myAsyncFunction(str) {
|
|
11
|
+
await sleep(1000);
|
|
12
|
+
console.log("hello"+str)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const context = await isolate.createContext();
|
|
16
|
+
const jail = context.global;
|
|
17
|
+
|
|
18
|
+
await jail.set('myAsync', new ivm.Reference(myAsyncFunction));
|
|
19
|
+
|
|
20
|
+
const fn = await context.eval(`
|
|
21
|
+
const normalizeArgs = args => args.map(arg => {
|
|
22
|
+
if (typeof arg === 'object' && arg !== null) {
|
|
23
|
+
return JSON.stringify(arg); // Convert objects to strings
|
|
24
|
+
}
|
|
25
|
+
return arg;
|
|
26
|
+
});
|
|
27
|
+
const t = (...args) => {
|
|
28
|
+
myAsync.applySyncPromise(null, normalizeArgs(args));
|
|
29
|
+
}
|
|
30
|
+
(async function untrusted() {
|
|
31
|
+
let str = await t("ok", {"ok":true});
|
|
32
|
+
return str;
|
|
33
|
+
})
|
|
34
|
+
`, { reference: true })
|
|
35
|
+
const value = await fn.apply(undefined, [], { result: { promise: true } })
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
beforeAll(async () => {
|
|
40
|
+
});
|
|
41
|
+
describe('VM system ingration', () => {
|
|
42
|
+
|
|
43
|
+
it('should successfully add a file with local storage', async () => {
|
|
44
|
+
console.log(await executeSafeJavascript({
|
|
45
|
+
script: 'const t = await addSync();'
|
|
46
|
+
}, {}, { username:'test'}));
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
expect(true).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -7,6 +7,7 @@ import { modelsCollection as getAppModelsCollection, getCollectionForUser } from
|
|
|
7
7
|
import * as workflowModule from 'data-primals-engine/modules/workflow';
|
|
8
8
|
import {getUniquePort, initEngine} from "../src/setenv.js";
|
|
9
9
|
import process from "process";
|
|
10
|
+
import {getUserCollectionName} from "../src/modules/mongodb.js";
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
beforeAll(async () =>{
|
|
@@ -18,7 +19,7 @@ vi.mock('data-primals-engine/modules/workflow', { spy: true })
|
|
|
18
19
|
const mockUser = {
|
|
19
20
|
username: 'testuserWorkflow',
|
|
20
21
|
_user: 'testuserWorkflow',
|
|
21
|
-
userPlan: '
|
|
22
|
+
userPlan: 'premium',
|
|
22
23
|
email: 'testWorkflow@example.com'
|
|
23
24
|
};
|
|
24
25
|
|
|
@@ -155,6 +156,10 @@ beforeEach(async () => {
|
|
|
155
156
|
console.log({mods})
|
|
156
157
|
});
|
|
157
158
|
|
|
159
|
+
afterAll(async () => {
|
|
160
|
+
const coll = await getCollectionForUser(mockUser);
|
|
161
|
+
await coll.drop();
|
|
162
|
+
})
|
|
158
163
|
describe('Intégration des Workflows - triggerWorkflows', () => {
|
|
159
164
|
|
|
160
165
|
let testWorkflow;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ObjectId } from 'mongodb';
|
|
2
|
-
import {
|
|
2
|
+
import {expect, describe, it, beforeEach, beforeAll, vi, afterAll} from 'vitest';
|
|
3
3
|
import { Config } from "data-primals-engine/config";
|
|
4
4
|
// --- Importations des modules de l'application ---
|
|
5
5
|
import { insertData, editData } from 'data-primals-engine/modules/data';
|
|
@@ -7,6 +7,7 @@ import { modelsCollection as getAppModelsCollection, getCollectionForUser, getCo
|
|
|
7
7
|
import * as workflowModule from 'data-primals-engine/modules/workflow';
|
|
8
8
|
import {initEngine} from "../src/setenv.js";
|
|
9
9
|
import {maxExecutionsByStep} from "../src/constants.js";
|
|
10
|
+
import {getUserCollectionName} from "../src/modules/mongodb.js";
|
|
10
11
|
|
|
11
12
|
vi.mock('data-primals-engine/modules/workflow', { spy: true })
|
|
12
13
|
|
|
@@ -47,6 +48,10 @@ beforeEach(async () => {
|
|
|
47
48
|
}
|
|
48
49
|
});
|
|
49
50
|
|
|
51
|
+
afterAll(async () => {
|
|
52
|
+
const coll = await getCollectionForUser(mockUser);
|
|
53
|
+
await coll.drop();
|
|
54
|
+
})
|
|
50
55
|
// ====================================================================================
|
|
51
56
|
// =================== DÉBUT DES TESTS DE ROBUSTESSE ==================================
|
|
52
57
|
// ====================================================================================
|