data-primals-engine 1.0.11 → 1.1.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/client/README.md +8 -0
- package/client/index.html +31 -0
- package/client/index.js +25 -0
- package/client/package-lock.json +11664 -0
- package/client/package.json +70 -0
- package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
- package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
- package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
- package/client/public/doc/API.postman_collection.json +214 -0
- package/client/public/github.svg +1 -0
- package/client/public/profilCompany.jpg +0 -0
- package/client/public/profilDeveloper.jpg +0 -0
- package/client/public/profilEngineer.jpg +0 -0
- package/client/public/profilPersonal.jpg +0 -0
- package/client/public/profils .psd +0 -0
- package/client/public/react.svg +9 -0
- package/client/src/APIInfo.jsx +328 -0
- package/client/src/AddWidgetTypeModal.jsx +44 -0
- package/client/src/AddWidgetTypeModal.scss +87 -0
- package/client/src/App.css +42 -0
- package/client/src/App.jsx +586 -0
- package/client/src/App.scss +1466 -0
- package/client/src/AssistantChat.jsx +280 -0
- package/client/src/AssistantChat.scss +229 -0
- package/client/src/Button.jsx +12 -0
- package/client/src/Button.scss +197 -0
- package/client/src/CalculationBuilder.jsx +338 -0
- package/client/src/CalculationStepRow.jsx +199 -0
- package/client/src/CalendarConfigModal.jsx +49 -0
- package/client/src/ChartConfigModal.jsx +402 -0
- package/client/src/ConditionBuilder.jsx +622 -0
- package/client/src/ConditionBuilder.scss +672 -0
- package/client/src/ConditionBuilder2.jsx +757 -0
- package/client/src/ContentView.jsx +274 -0
- package/client/src/CronBuilder.jsx +126 -0
- package/client/src/CronBuilder.scss +128 -0
- package/client/src/CronPartBuilder.jsx +150 -0
- package/client/src/Dashboard.jsx +210 -0
- package/client/src/Dashboard.scss +445 -0
- package/client/src/DashboardChart.jsx +362 -0
- package/client/src/DashboardFlexViewItem.jsx +129 -0
- package/client/src/DashboardView.jsx +554 -0
- package/client/src/DataChart.jsx +349 -0
- package/client/src/DataEditor.jsx +556 -0
- package/client/src/DataLayout.jsx +709 -0
- package/client/src/DataTable.jsx +996 -0
- package/client/src/DataTable.scss +73 -0
- package/client/src/Dialog.jsx +90 -0
- package/client/src/Dialog.scss +117 -0
- package/client/src/DisplayFlexNodeRenderer.jsx +115 -0
- package/client/src/DocumentationPageLayout.jsx +93 -0
- package/client/src/DocumentationPageLayout.scss +262 -0
- package/client/src/Draggable.jsx +222 -0
- package/client/src/Draggable.scss +49 -0
- package/client/src/ExportDialog.jsx +172 -0
- package/client/src/Field.jsx +1558 -0
- package/client/src/FlexBuilder.jsx +269 -0
- package/client/src/FlexBuilder.scss +226 -0
- package/client/src/FlexBuilderControls.jsx +170 -0
- package/client/src/FlexBuilderModal.jsx +75 -0
- package/client/src/FlexBuilderModal.scss +109 -0
- package/client/src/FlexBuilderPreview.jsx +48 -0
- package/client/src/FlexBuilderUtils.js +84 -0
- package/client/src/FlexDataRenderer.jsx +170 -0
- package/client/src/FlexDataRenderer.scss +80 -0
- package/client/src/FlexNode.jsx +290 -0
- package/client/src/FlexTreeUtils.js +129 -0
- package/client/src/HiddenableCell.jsx +46 -0
- package/client/src/HiddenableCell.scss +36 -0
- package/client/src/KPIDialog.jsx +39 -0
- package/client/src/KPIWidget.jsx +139 -0
- package/client/src/KanbanCard.jsx +92 -0
- package/client/src/KanbanColumn.jsx +29 -0
- package/client/src/KanbanConfigModal.jsx +115 -0
- package/client/src/KanbanView.jsx +113 -0
- package/client/src/KanbanView.scss +107 -0
- package/client/src/MessageRotator.jsx +77 -0
- package/client/src/MessageRotator.scss +14 -0
- package/client/src/ModelCreator.jsx +640 -0
- package/client/src/ModelCreator.scss +154 -0
- package/client/src/ModelCreatorField.jsx +810 -0
- package/client/src/ModelImporter.jsx +120 -0
- package/client/src/ModelList.jsx +205 -0
- package/client/src/Notification.jsx +137 -0
- package/client/src/Notification.scss +126 -0
- package/client/src/NotificationProvider.jsx +73 -0
- package/client/src/PackGallery.jsx +211 -0
- package/client/src/PackGallery.scss +156 -0
- package/client/src/Pagination.jsx +141 -0
- package/client/src/RTE.jsx +415 -0
- package/client/src/RTETrans.jsx +103 -0
- package/client/src/RelationField.jsx +247 -0
- package/client/src/RelationValue.jsx +230 -0
- package/client/src/RestoreConfirmationModal.jsx +183 -0
- package/client/src/RestoreDialog.jsx +134 -0
- package/client/src/RestoreDialog.scss +67 -0
- package/client/src/RichTextEditorModal.jsx +34 -0
- package/client/src/RichTextEditorModal.scss +54 -0
- package/client/src/TourSpotlight.jsx +234 -0
- package/client/src/TourSpotlight.scss +100 -0
- package/client/src/TutorialsMenu.jsx +83 -0
- package/client/src/TutorialsMenu.scss +217 -0
- package/client/src/TutorialsRewardModal.jsx +65 -0
- package/client/src/Utils.jsx +78 -0
- package/client/src/ViewSwitcher.jsx +54 -0
- package/client/src/ViewSwitcher.scss +74 -0
- package/client/src/Webpage.jsx +69 -0
- package/client/src/_variables.scss +21 -0
- package/client/src/assets/react.svg +1 -0
- package/client/src/constants.js +68 -0
- package/client/src/contexts/AuthContext.jsx +28 -0
- package/client/src/contexts/ModelContext.jsx +328 -0
- package/client/src/contexts/UIContext.jsx +52 -0
- package/client/src/core/data.js +35 -0
- package/client/src/entry-client.jsx +15 -0
- package/client/src/entry-server.jsx +13 -0
- package/client/src/filter.js +222 -0
- package/client/src/hooks/data.js +101 -0
- package/client/src/hooks/useDebounce.js +20 -0
- package/client/src/hooks/useDragAndDrop.js +59 -0
- package/client/src/hooks/useLocalStorage.js +100 -0
- package/client/src/hooks/useMount.js +42 -0
- package/client/src/hooks/useTutorials.jsx +227 -0
- package/client/src/hooks/useWindowSize.js +24 -0
- package/client/src/i18n.js +47 -0
- package/client/src/index.css +90 -0
- package/client/src/index.js +10 -0
- package/client/src/main.jsx +11 -0
- package/client/src/translations.js +15940 -0
- package/client/src/tutorials.js +112 -0
- package/client/vite.config.js +30 -0
- package/eslint.config.js +50 -0
- package/package.json +48 -27
- package/server.js +9 -0
- package/src/constants.js +12 -23
- package/src/core.js +9 -8
- package/src/data.js +81 -80
- package/src/defaultModels.js +114 -115
- package/src/email.js +8 -9
- package/src/engine.js +5 -5
- package/src/events.js +1 -2
- package/src/i18n.js +212 -211
- package/src/middlewares/middleware-mongodb.js +94 -93
- package/src/migrate.js +24 -24
- package/src/modules/assistant.js +55 -55
- package/src/modules/bucket.js +10 -9
- package/src/modules/data.js +387 -357
- package/src/modules/file.js +3 -6
- package/src/modules/mongodb.js +6 -7
- package/src/modules/user.js +24 -47
- package/src/modules/workflow.js +68 -67
- package/src/openai.jobs.js +2 -2
- package/src/packs.js +30 -31
- package/src/providers.js +101 -3
- package/src/setenv.js +1 -1
- package/src/user.js +0 -17
- package/src/workers/crypto-worker.js +21 -20
- package/src/workers/import-export-worker.js +18 -18
- package/test/data.backup.integration.test.js +7 -12
- package/test/data.integration.test.js +27 -25
- package/test/globalSetup.js +2 -2
- package/test/import_export.integration.test.js +6 -6
- package/test/model.integration.test.js +21 -22
- package/test/workflow.integration.test.js +2 -5
- package/test/workflow.robustness.test.js +6 -13
- package/vitest.config.js +2 -2
|
@@ -1,110 +1,108 @@
|
|
|
1
|
-
import {isIsoDate} from "../core.js";
|
|
2
|
-
|
|
3
1
|
const TEST_REGEX = /^\$|\./;
|
|
4
2
|
const TEST_REGEX_WITHOUT_DOT = /^\$/;
|
|
5
3
|
const REPLACE_REGEX = /^\$|\./g;
|
|
6
4
|
|
|
7
5
|
function isPlainObject(obj) {
|
|
8
|
-
|
|
6
|
+
return typeof obj === 'object' && obj !== null;
|
|
9
7
|
}
|
|
10
8
|
|
|
11
9
|
function getTestRegex(allowDots) {
|
|
12
|
-
|
|
10
|
+
return allowDots ? TEST_REGEX_WITHOUT_DOT : TEST_REGEX;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
function withEach(target, cb) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
(function act(obj) {
|
|
15
|
+
if (Array.isArray(obj)) {
|
|
16
|
+
obj.forEach(act);
|
|
17
|
+
} else if (isPlainObject(obj)) {
|
|
18
|
+
Object.keys(obj).forEach(function (key) {
|
|
19
|
+
const val = obj[key];
|
|
20
|
+
const resp = cb(obj, val, key);
|
|
21
|
+
if (resp.shouldRecurse) {
|
|
22
|
+
act(obj[resp.key || key]);
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
})(target);
|
|
26
|
+
})(target);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
function has(target, allowDots) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
const regex = getTestRegex(allowDots);
|
|
31
|
+
|
|
32
|
+
let hasProhibited = false;
|
|
33
|
+
withEach(target, function (obj, val, key) {
|
|
34
|
+
if (regex.test(key)) {
|
|
35
|
+
hasProhibited = true;
|
|
36
|
+
return { shouldRecurse: false };
|
|
37
|
+
} else {
|
|
38
|
+
return { shouldRecurse: true };
|
|
39
|
+
}
|
|
40
|
+
});
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
return hasProhibited;
|
|
45
43
|
}
|
|
46
44
|
|
|
47
45
|
function _sanitize(target, options) {
|
|
48
|
-
|
|
46
|
+
const regex = getTestRegex(options.allowDots);
|
|
49
47
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
let isSanitized = false;
|
|
49
|
+
let replaceWith = null;
|
|
50
|
+
const dryRun = Boolean(options.dryRun);
|
|
51
|
+
if (!regex.test(options.replaceWith) && options.replaceWith !== '.') {
|
|
52
|
+
replaceWith = options.replaceWith;
|
|
53
|
+
}
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
const wl = options.whitelist || [];
|
|
56
|
+
RegExp.prototype.toJSON = RegExp.prototype.toString;
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
withEach(target, function (obj, val, key) {
|
|
59
|
+
let shouldRecurse = true;
|
|
60
|
+
|
|
61
|
+
if( (key === 'regex' && obj.input) || key === '$regex' ){
|
|
62
|
+
obj[key] = new RegExp(val, "ui");
|
|
63
|
+
console.log('regex san', obj[key]);
|
|
64
|
+
}
|
|
65
|
+
else if (!wl.includes(key) && regex.test(key)) {
|
|
66
|
+
isSanitized = true;
|
|
67
|
+
// if dryRun is enabled, do not modify the target
|
|
68
|
+
if (dryRun) {
|
|
69
|
+
return {
|
|
70
|
+
shouldRecurse: shouldRecurse,
|
|
71
|
+
key: key
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
delete obj[key];
|
|
75
|
+
if (replaceWith) {
|
|
76
|
+
key = key.replace(REPLACE_REGEX, replaceWith);
|
|
77
|
+
// Avoid to set __proto__ and constructor.prototype
|
|
78
|
+
// https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications
|
|
79
|
+
// https://snyk.io/vuln/SNYK-JS-LODASH-73638
|
|
80
|
+
if (
|
|
81
|
+
key !== '__proto__' &&
|
|
82
|
+
key !== 'constructor' &&
|
|
83
|
+
key !== 'prototype'
|
|
84
|
+
) {
|
|
85
|
+
obj[key] = val;
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
shouldRecurse = false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
62
91
|
|
|
63
|
-
if( (key === 'regex' && obj.input) || key === '$regex' ){
|
|
64
|
-
obj[key] = new RegExp(val, "ui");
|
|
65
|
-
console.log('regex san', obj[key]);
|
|
66
|
-
}
|
|
67
|
-
else if (!wl.includes(key) && regex.test(key)) {
|
|
68
|
-
isSanitized = true;
|
|
69
|
-
// if dryRun is enabled, do not modify the target
|
|
70
|
-
if (dryRun) {
|
|
71
92
|
return {
|
|
72
|
-
|
|
73
|
-
|
|
93
|
+
shouldRecurse: shouldRecurse,
|
|
94
|
+
key: key
|
|
74
95
|
};
|
|
75
|
-
|
|
76
|
-
delete obj[key];
|
|
77
|
-
if (replaceWith) {
|
|
78
|
-
key = key.replace(REPLACE_REGEX, replaceWith);
|
|
79
|
-
// Avoid to set __proto__ and constructor.prototype
|
|
80
|
-
// https://portswigger.net/daily-swig/prototype-pollution-the-dangerous-and-underrated-vulnerability-impacting-javascript-applications
|
|
81
|
-
// https://snyk.io/vuln/SNYK-JS-LODASH-73638
|
|
82
|
-
if (
|
|
83
|
-
key !== '__proto__' &&
|
|
84
|
-
key !== 'constructor' &&
|
|
85
|
-
key !== 'prototype'
|
|
86
|
-
) {
|
|
87
|
-
obj[key] = val;
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
shouldRecurse = false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
96
|
+
});
|
|
93
97
|
|
|
94
98
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
99
|
+
isSanitized,
|
|
100
|
+
target
|
|
97
101
|
};
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
isSanitized,
|
|
102
|
-
target,
|
|
103
|
-
};
|
|
104
102
|
}
|
|
105
103
|
|
|
106
104
|
function sanitize(target, options = {}) {
|
|
107
|
-
|
|
105
|
+
return _sanitize(target, options).target;
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
/**
|
|
@@ -112,20 +110,23 @@ function sanitize(target, options = {}) {
|
|
|
112
110
|
* @returns {function}
|
|
113
111
|
*/
|
|
114
112
|
export function middleware(options = {}) {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
113
|
+
const hasOnSanitize = typeof options.onSanitize === 'function';
|
|
114
|
+
return function (req, res, next) {
|
|
115
|
+
['body', 'params', 'headers', 'query'].forEach(function (key) {
|
|
116
|
+
if (req[key]) {
|
|
117
|
+
// The _sanitize function mutates the req[key] object in-place.
|
|
118
|
+
// We only need to capture whether it was sanitized to call the hook.
|
|
119
|
+
const { isSanitized } = _sanitize(req[key], options);
|
|
120
|
+
|
|
121
|
+
// The problematic assignment `req[key] = target;` is removed.
|
|
122
|
+
if (isSanitized && hasOnSanitize) {
|
|
123
|
+
options.onSanitize({
|
|
124
|
+
req,
|
|
125
|
+
key
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
next();
|
|
131
|
+
};
|
|
132
|
+
}
|
package/src/migrate.js
CHANGED
|
@@ -30,30 +30,30 @@ engine.start(port, async () => {
|
|
|
30
30
|
const { executedNames, allMigrationFiles } = await getMigrationStatus(db);
|
|
31
31
|
|
|
32
32
|
switch (command) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
33
|
+
case 'create':
|
|
34
|
+
if (!target) throw new Error("Please provide a name for the migration.");
|
|
35
|
+
await createMigrationFile(target, logger);
|
|
36
|
+
break;
|
|
37
|
+
case 'status':
|
|
38
|
+
displayStatus(executedNames, allMigrationFiles, logger);
|
|
39
|
+
break;
|
|
40
|
+
case 'up':
|
|
41
|
+
await runMigrations('up', null, logger, db, executedNames, allMigrationFiles);
|
|
42
|
+
break;
|
|
43
|
+
case 'down':
|
|
44
|
+
// Annule la dernière migration
|
|
45
|
+
await runMigrations('down', 'last', logger, db, executedNames, allMigrationFiles);
|
|
46
|
+
break;
|
|
47
|
+
case 'to':
|
|
48
|
+
if (!target) throw new Error("Please specify a target migration file for the 'to' command.");
|
|
49
|
+
await runMigrations('up', target, logger, db, executedNames, allMigrationFiles);
|
|
50
|
+
break;
|
|
51
|
+
case 'revert':
|
|
52
|
+
if (!target) throw new Error("Please specify a target migration file for the 'revert' command. Use '0' to revert all.");
|
|
53
|
+
await runMigrations('down', target, logger, db, executedNames, allMigrationFiles);
|
|
54
|
+
break;
|
|
55
|
+
default:
|
|
56
|
+
throw new Error(`Unknown command: ${command}. Use 'up', 'down', 'create', 'status', 'to', 'revert'.`);
|
|
57
57
|
}
|
|
58
58
|
} catch (error) {
|
|
59
59
|
logger.error(chalk.red("Migration process failed:"), error.message);
|
package/src/modules/assistant.js
CHANGED
|
@@ -25,13 +25,13 @@ export const assistantGlobalLimiter = rateLimit({
|
|
|
25
25
|
});
|
|
26
26
|
|
|
27
27
|
const createSystemPrompt = (modelDefs) => {
|
|
28
|
-
const cond1 = JSON.stringify({ "model": "event", "sort": "startDate:ASC", "limit": 0, "filter": { "$and": [{ "$nin": ["$tags", "festival"] }, { "$lt": ["$endDate", "$$NOW"] }] }}, null, 2);
|
|
28
|
+
const cond1 = JSON.stringify({ "model": "event", "sort": "startDate:ASC", "limit": 0, "filter": { "$and": [{ "$nin": ["$tags", "festival"] }, { "$lt": ["$endDate", "$$NOW"] }] }}, null, 2);
|
|
29
29
|
const cond2 = JSON.stringify({ "model": "contact", "sort": "legalName:ASC", "limit": 5,"filter": {"$ne": [{ "$type": "$legalName"}, "missing"] }}, null, 2);
|
|
30
30
|
const cond3 = JSON.stringify({ "model": "order", "sort": "_id:DESC", "limit": 10,"filter": {"lang": { "$find": [{ "$eq": ["$$this.code", "fr"] }] } }}, null, 2);
|
|
31
31
|
const cond4 = JSON.stringify({ "model": "order", "sort": "updatedAt:DESC", "limit": 0,"filter": {"user": { "$find": { "roles": { "$find": [{ "$in": ["$$this.name", ["admin", "moderator"]] }] } }}}}, null, 2);
|
|
32
32
|
|
|
33
33
|
return `
|
|
34
|
-
Tu es "Prior", un assistant expert en analyse de données pour
|
|
34
|
+
Tu es "Prior", un assistant expert en analyse de données pour le moteur data-primals-engine..
|
|
35
35
|
Ta mission est d'aider l'utilisateur en répondant à ses questions sur ses données.
|
|
36
36
|
|
|
37
37
|
STRICTEMENT INTERDIT :
|
|
@@ -161,7 +161,7 @@ async function handleChatRequest(message, history, provider, context, user, conf
|
|
|
161
161
|
const envKeyName = providers[p];
|
|
162
162
|
if (!envKeyName) return { success: false, message: `Fournisseur IA non supporté : ${p}` };
|
|
163
163
|
|
|
164
|
-
const envCollection = getCollectionForUser(user);
|
|
164
|
+
const envCollection = await getCollectionForUser(user);
|
|
165
165
|
const userEnvVar = await envCollection.findOne({ _model: 'env', name: envKeyName, _user: user.username });
|
|
166
166
|
apiKey = userEnvVar?.value || process.env[envKeyName];
|
|
167
167
|
|
|
@@ -214,54 +214,54 @@ async function handleChatRequest(message, history, provider, context, user, conf
|
|
|
214
214
|
};
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
-
// Exécution IMMÉDIATE des actions sans confirmation (sauf pour post/update/delete)
|
|
217
|
+
// Exécution IMMÉDIATE des actions sans confirmation (sauf pour post/update/delete)
|
|
218
218
|
switch (parsedResponse.action) {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
219
|
+
case 'search': {
|
|
220
|
+
const searchResult = await searchData({
|
|
221
|
+
user,
|
|
222
|
+
query: {
|
|
223
|
+
model: parsedResponse.params.model,
|
|
224
|
+
filter: parsedResponse.params.filter,
|
|
225
|
+
limit: parsedResponse.params.limit || 10
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const resultString = searchResult.data.length > 0
|
|
230
|
+
? i18n.t('assistant.searchResults', "Voici les résultats :") +
|
|
231
231
|
searchResult.data.map(item =>
|
|
232
232
|
`\n- ${getDataAsString(allModels.find(m => m.name === parsedResponse.params.model), item, i18n.t, allModels, true)}`
|
|
233
233
|
).join('')
|
|
234
|
-
|
|
234
|
+
: i18n.t('assistant.noResults', "Aucun résultat trouvé.");
|
|
235
235
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
236
|
+
return { success: true, displayMessage: resultString };
|
|
237
|
+
}
|
|
238
|
+
case 'displayMessage':
|
|
239
|
+
return { success: true, displayMessage: parsedResponse.params.message };
|
|
240
|
+
case 'code':
|
|
241
|
+
return { success: true, displayMessage: "Voici le code : " + parsedResponse.params.code };
|
|
242
|
+
case 'post':
|
|
243
|
+
case 'update':
|
|
244
|
+
case 'delete': {
|
|
245
|
+
const { model, filter, data } = parsedResponse.params;
|
|
246
|
+
|
|
247
|
+
// Un message générique. Les détails seront affichés par le front-end.
|
|
248
|
+
const confirmationMessage = i18n.t('assistant.confirmActionPrompt', "Veuillez confirmer l'action suivante :");
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
success: true,
|
|
252
|
+
model,
|
|
253
|
+
filter,
|
|
254
|
+
data,
|
|
255
|
+
displayMessage: confirmationMessage, // Message détaillé pour l'utilisateur
|
|
256
|
+
confirmationRequest: parsedResponse // Action complète pour l'exécution
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
259
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
260
|
+
default:
|
|
261
|
+
return {
|
|
262
|
+
success: true,
|
|
263
|
+
displayMessage: i18n.t('assistant.unknownAction', "Commande non reconnue.")
|
|
264
|
+
};
|
|
265
265
|
}
|
|
266
266
|
}
|
|
267
267
|
|
|
@@ -278,16 +278,16 @@ async function handleChatRequest(message, history, provider, context, user, conf
|
|
|
278
278
|
async function executeConfirmedAction(action, params, user) {
|
|
279
279
|
logger.info(`[Assistant] Exécution de l'action confirmée par l'utilisateur: ${action}`);
|
|
280
280
|
switch (action) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
281
|
+
case 'post':
|
|
282
|
+
// Note : on passe false pour ne pas redéclencher de workflow ici
|
|
283
|
+
return await insertData(params.model, params.data, {}, user, false, false);
|
|
284
|
+
case 'update':
|
|
285
|
+
return await patchData(params.model, params.filter, params.data, {}, user);
|
|
286
|
+
case 'delete':
|
|
287
|
+
// Le modèle est dans les params, pas besoin de le passer en argument sparé
|
|
288
|
+
return await deleteData(params.model, [], params.filter, user);
|
|
289
|
+
default:
|
|
290
|
+
throw new Error(`Action confirmée non supportée: ${action}`);
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
293
|
|
package/src/modules/bucket.js
CHANGED
|
@@ -6,7 +6,7 @@ import {decryptValue, encryptValue} from "../data.js";
|
|
|
6
6
|
import {MongoClient} from "../engine.js";
|
|
7
7
|
import {loadFromDump, validateRestoreRequest} from "./data.js";
|
|
8
8
|
import {Logger} from "../gameObject.js";
|
|
9
|
-
import {middlewareAuthenticator,
|
|
9
|
+
import {middlewareAuthenticator, userInitiator} from "./user.js";
|
|
10
10
|
import {awsDefaultConfig, maxBytesPerSecondThrottleData} from "../constants.js";
|
|
11
11
|
import crypto from "node:crypto";
|
|
12
12
|
import i18n from "data-primals-engine/i18n";
|
|
@@ -24,7 +24,7 @@ export const requestRestore = async (user, lang) => {
|
|
|
24
24
|
restoreRequests[user?.username] = {
|
|
25
25
|
fullToken: fullRestoreToken,
|
|
26
26
|
modelsToken: modelsRestoreToken,
|
|
27
|
-
expiresAt: expiration
|
|
27
|
+
expiresAt: expiration
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
i18n.changeLanguage(lang);
|
|
@@ -51,7 +51,7 @@ const getDefaultS3Config = () => {
|
|
|
51
51
|
accessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
|
52
52
|
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, // Utiliser la clé déchiffrée
|
|
53
53
|
region: process.env.AWS_REGION || awsDefaultConfig.region,
|
|
54
|
-
bucketName: process.env.AWS_BUCKET || awsDefaultConfig.bucketName
|
|
54
|
+
bucketName: process.env.AWS_BUCKET || awsDefaultConfig.bucketName
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
57
|
const getS3Client = (s3Config) => {
|
|
@@ -77,7 +77,7 @@ export const uploadToS3 = async (s3Config, filePath, remoteFilename) => {
|
|
|
77
77
|
const params = {
|
|
78
78
|
Bucket: s3Config.bucketName,
|
|
79
79
|
Key: bucketPath,
|
|
80
|
-
Body: fileContent
|
|
80
|
+
Body: fileContent
|
|
81
81
|
};
|
|
82
82
|
|
|
83
83
|
try {
|
|
@@ -96,7 +96,7 @@ export const listS3Backups = async (s3Config) => {
|
|
|
96
96
|
|
|
97
97
|
const params = {
|
|
98
98
|
Bucket: s3Config.bucketName,
|
|
99
|
-
Prefix: bucketPathPrefix
|
|
99
|
+
Prefix: bucketPathPrefix
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
try {
|
|
@@ -119,7 +119,7 @@ export const downloadFromS3 = async (s3Config, s3FileKey, downloadPath) => {
|
|
|
119
119
|
const s3 = getS3Client(s3Config);
|
|
120
120
|
const params = {
|
|
121
121
|
Bucket: s3Config.bucketName,
|
|
122
|
-
Key: s3FileKey
|
|
122
|
+
Key: s3FileKey
|
|
123
123
|
};
|
|
124
124
|
|
|
125
125
|
try {
|
|
@@ -140,7 +140,8 @@ export async function onInit(defaultEngine) {
|
|
|
140
140
|
engine = defaultEngine;
|
|
141
141
|
logger = engine.getComponent(Logger);
|
|
142
142
|
|
|
143
|
-
|
|
143
|
+
const userMiddlewares = await engine.userProvider.getMiddlewares();
|
|
144
|
+
engine.post('/api/backup/request-restore', [throttle, middlewareAuthenticator, userInitiator, ...userMiddlewares], async (req, res) => {
|
|
144
145
|
const user = req.me; // Assuming you have user authentication middleware
|
|
145
146
|
if (!user) {
|
|
146
147
|
return res.status(401).json({ error: 'Unauthorized' });
|
|
@@ -177,7 +178,7 @@ export async function onInit(defaultEngine) {
|
|
|
177
178
|
}
|
|
178
179
|
});
|
|
179
180
|
|
|
180
|
-
engine.post('/api/user/s3-config', [middlewareAuthenticator, userInitiator,
|
|
181
|
+
engine.post('/api/user/s3-config', [middlewareAuthenticator, userInitiator, ...userMiddlewares], async (req, res) => {
|
|
181
182
|
const user = req.me;
|
|
182
183
|
const { bucketName, accessKeyId, secretAccessKey, region, pathPrefix } = req.fields;
|
|
183
184
|
|
|
@@ -192,7 +193,7 @@ export async function onInit(defaultEngine) {
|
|
|
192
193
|
's3Config.bucketName': bucketName,
|
|
193
194
|
's3Config.accessKeyId': accessKeyId, // Stocké en clair (généralement acceptable)
|
|
194
195
|
's3Config.region': region,
|
|
195
|
-
's3Config.pathPrefix': pathPrefix || ''
|
|
196
|
+
's3Config.pathPrefix': pathPrefix || '' // S'assurer qu'il y a une valeur par défaut si vide
|
|
196
197
|
};
|
|
197
198
|
|
|
198
199
|
// Chiffrer et mettre à jour la clé secrète uniquement si elle est fournie
|