data-primals-engine 1.0.10 → 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.
Files changed (166) hide show
  1. package/client/README.md +8 -0
  2. package/client/index.html +31 -0
  3. package/client/index.js +25 -0
  4. package/client/package-lock.json +11664 -0
  5. package/client/package.json +70 -0
  6. package/client/public/demo/26899917-d1ba-4df4-bb33-48d09a8778da.jpg +0 -0
  7. package/client/public/demo/4b9894c7-12cd-466d-8fd3-a2757b09ec96.jpg +0 -0
  8. package/client/public/demo/7ed369ac-a1a2-4b45-b0cd-4fd5bcf5a75a.jpg +0 -0
  9. package/client/public/doc/API.postman_collection.json +214 -0
  10. package/client/public/github.svg +1 -0
  11. package/client/public/profilCompany.jpg +0 -0
  12. package/client/public/profilDeveloper.jpg +0 -0
  13. package/client/public/profilEngineer.jpg +0 -0
  14. package/client/public/profilPersonal.jpg +0 -0
  15. package/client/public/profils .psd +0 -0
  16. package/client/public/react.svg +9 -0
  17. package/client/src/APIInfo.jsx +328 -0
  18. package/client/src/AddWidgetTypeModal.jsx +44 -0
  19. package/client/src/AddWidgetTypeModal.scss +87 -0
  20. package/client/src/App.css +42 -0
  21. package/client/src/App.jsx +586 -0
  22. package/client/src/App.scss +1466 -0
  23. package/client/src/AssistantChat.jsx +280 -0
  24. package/client/src/AssistantChat.scss +229 -0
  25. package/client/src/Button.jsx +12 -0
  26. package/client/src/Button.scss +197 -0
  27. package/client/src/CalculationBuilder.jsx +338 -0
  28. package/client/src/CalculationStepRow.jsx +199 -0
  29. package/client/src/CalendarConfigModal.jsx +49 -0
  30. package/client/src/ChartConfigModal.jsx +402 -0
  31. package/client/src/ConditionBuilder.jsx +622 -0
  32. package/client/src/ConditionBuilder.scss +672 -0
  33. package/client/src/ConditionBuilder2.jsx +757 -0
  34. package/client/src/ContentView.jsx +274 -0
  35. package/client/src/CronBuilder.jsx +126 -0
  36. package/client/src/CronBuilder.scss +128 -0
  37. package/client/src/CronPartBuilder.jsx +150 -0
  38. package/client/src/Dashboard.jsx +210 -0
  39. package/client/src/Dashboard.scss +445 -0
  40. package/client/src/DashboardChart.jsx +362 -0
  41. package/client/src/DashboardFlexViewItem.jsx +129 -0
  42. package/client/src/DashboardView.jsx +554 -0
  43. package/client/src/DataChart.jsx +349 -0
  44. package/client/src/DataEditor.jsx +556 -0
  45. package/client/src/DataLayout.jsx +709 -0
  46. package/client/src/DataTable.jsx +996 -0
  47. package/client/src/DataTable.scss +73 -0
  48. package/client/src/Dialog.jsx +90 -0
  49. package/client/src/Dialog.scss +117 -0
  50. package/client/src/DisplayFlexNodeRenderer.jsx +115 -0
  51. package/client/src/DocumentationPageLayout.jsx +93 -0
  52. package/client/src/DocumentationPageLayout.scss +262 -0
  53. package/client/src/Draggable.jsx +222 -0
  54. package/client/src/Draggable.scss +49 -0
  55. package/client/src/ExportDialog.jsx +172 -0
  56. package/client/src/Field.jsx +1558 -0
  57. package/client/src/FlexBuilder.jsx +269 -0
  58. package/client/src/FlexBuilder.scss +226 -0
  59. package/client/src/FlexBuilderControls.jsx +170 -0
  60. package/client/src/FlexBuilderModal.jsx +75 -0
  61. package/client/src/FlexBuilderModal.scss +109 -0
  62. package/client/src/FlexBuilderPreview.jsx +48 -0
  63. package/client/src/FlexBuilderUtils.js +84 -0
  64. package/client/src/FlexDataRenderer.jsx +170 -0
  65. package/client/src/FlexDataRenderer.scss +80 -0
  66. package/client/src/FlexNode.jsx +290 -0
  67. package/client/src/FlexTreeUtils.js +129 -0
  68. package/client/src/HiddenableCell.jsx +46 -0
  69. package/client/src/HiddenableCell.scss +36 -0
  70. package/client/src/KPIDialog.jsx +39 -0
  71. package/client/src/KPIWidget.jsx +139 -0
  72. package/client/src/KanbanCard.jsx +92 -0
  73. package/client/src/KanbanColumn.jsx +29 -0
  74. package/client/src/KanbanConfigModal.jsx +115 -0
  75. package/client/src/KanbanView.jsx +113 -0
  76. package/client/src/KanbanView.scss +107 -0
  77. package/client/src/MessageRotator.jsx +77 -0
  78. package/client/src/MessageRotator.scss +14 -0
  79. package/client/src/ModelCreator.jsx +640 -0
  80. package/client/src/ModelCreator.scss +154 -0
  81. package/client/src/ModelCreatorField.jsx +810 -0
  82. package/client/src/ModelImporter.jsx +120 -0
  83. package/client/src/ModelList.jsx +205 -0
  84. package/client/src/Notification.jsx +137 -0
  85. package/client/src/Notification.scss +126 -0
  86. package/client/src/NotificationProvider.jsx +73 -0
  87. package/client/src/PackGallery.jsx +211 -0
  88. package/client/src/PackGallery.scss +156 -0
  89. package/client/src/Pagination.jsx +141 -0
  90. package/client/src/RTE.jsx +415 -0
  91. package/client/src/RTETrans.jsx +103 -0
  92. package/client/src/RelationField.jsx +247 -0
  93. package/client/src/RelationValue.jsx +230 -0
  94. package/client/src/RestoreConfirmationModal.jsx +183 -0
  95. package/client/src/RestoreDialog.jsx +134 -0
  96. package/client/src/RestoreDialog.scss +67 -0
  97. package/client/src/RichTextEditorModal.jsx +34 -0
  98. package/client/src/RichTextEditorModal.scss +54 -0
  99. package/client/src/TourSpotlight.jsx +234 -0
  100. package/client/src/TourSpotlight.scss +100 -0
  101. package/client/src/TutorialsMenu.jsx +83 -0
  102. package/client/src/TutorialsMenu.scss +217 -0
  103. package/client/src/TutorialsRewardModal.jsx +65 -0
  104. package/client/src/Utils.jsx +78 -0
  105. package/client/src/ViewSwitcher.jsx +54 -0
  106. package/client/src/ViewSwitcher.scss +74 -0
  107. package/client/src/Webpage.jsx +69 -0
  108. package/client/src/_variables.scss +21 -0
  109. package/client/src/assets/react.svg +1 -0
  110. package/client/src/constants.js +68 -0
  111. package/client/src/contexts/AuthContext.jsx +28 -0
  112. package/client/src/contexts/ModelContext.jsx +328 -0
  113. package/client/src/contexts/UIContext.jsx +52 -0
  114. package/client/src/core/data.js +35 -0
  115. package/client/src/entry-client.jsx +15 -0
  116. package/client/src/entry-server.jsx +13 -0
  117. package/client/src/filter.js +222 -0
  118. package/client/src/hooks/data.js +101 -0
  119. package/client/src/hooks/useDebounce.js +20 -0
  120. package/client/src/hooks/useDragAndDrop.js +59 -0
  121. package/client/src/hooks/useLocalStorage.js +100 -0
  122. package/client/src/hooks/useMount.js +42 -0
  123. package/client/src/hooks/useTutorials.jsx +227 -0
  124. package/client/src/hooks/useWindowSize.js +24 -0
  125. package/client/src/i18n.js +47 -0
  126. package/client/src/index.css +90 -0
  127. package/client/src/index.js +10 -0
  128. package/client/src/main.jsx +11 -0
  129. package/client/src/translations.js +15940 -0
  130. package/client/src/tutorials.js +112 -0
  131. package/client/vite.config.js +30 -0
  132. package/eslint.config.js +50 -0
  133. package/package.json +48 -27
  134. package/server.js +9 -0
  135. package/src/constants.js +12 -23
  136. package/src/core.js +9 -8
  137. package/src/data.js +81 -80
  138. package/src/defaultModels.js +114 -115
  139. package/src/email.js +8 -9
  140. package/src/engine.js +5 -5
  141. package/src/events.js +1 -2
  142. package/src/i18n.js +5390 -211
  143. package/src/middlewares/middleware-mongodb.js +94 -93
  144. package/src/migrate.js +24 -24
  145. package/src/modules/assistant.js +55 -55
  146. package/src/modules/bucket.js +10 -9
  147. package/src/modules/data.js +387 -357
  148. package/src/modules/file.js +3 -6
  149. package/src/modules/mongodb.js +6 -7
  150. package/src/modules/user.js +24 -47
  151. package/src/modules/workflow.js +68 -67
  152. package/src/openai.jobs.js +2 -2
  153. package/src/packs.js +30 -31
  154. package/src/providers.js +101 -3
  155. package/src/setenv.js +1 -1
  156. package/src/user.js +0 -17
  157. package/src/workers/crypto-worker.js +21 -20
  158. package/src/workers/import-export-worker.js +18 -18
  159. package/test/data.backup.integration.test.js +7 -12
  160. package/test/data.integration.test.js +27 -25
  161. package/test/globalSetup.js +2 -2
  162. package/test/import_export.integration.test.js +6 -6
  163. package/test/model.integration.test.js +21 -22
  164. package/test/workflow.integration.test.js +2 -5
  165. package/test/workflow.robustness.test.js +6 -13
  166. 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
- return typeof obj === 'object' && obj !== null;
6
+ return typeof obj === 'object' && obj !== null;
9
7
  }
10
8
 
11
9
  function getTestRegex(allowDots) {
12
- return allowDots ? TEST_REGEX_WITHOUT_DOT : TEST_REGEX;
10
+ return allowDots ? TEST_REGEX_WITHOUT_DOT : TEST_REGEX;
13
11
  }
14
12
 
15
13
  function withEach(target, cb) {
16
- (function act(obj) {
17
- if (Array.isArray(obj)) {
18
- obj.forEach(act);
19
- } else if (isPlainObject(obj)) {
20
- Object.keys(obj).forEach(function (key) {
21
- const val = obj[key];
22
- const resp = cb(obj, val, key);
23
- if (resp.shouldRecurse) {
24
- act(obj[resp.key || key]);
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
- const regex = getTestRegex(allowDots);
33
-
34
- let hasProhibited = false;
35
- withEach(target, function (obj, val, key) {
36
- if (regex.test(key)) {
37
- hasProhibited = true;
38
- return { shouldRecurse: false };
39
- } else {
40
- return { shouldRecurse: true };
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
- return hasProhibited;
42
+ return hasProhibited;
45
43
  }
46
44
 
47
45
  function _sanitize(target, options) {
48
- const regex = getTestRegex(options.allowDots);
46
+ const regex = getTestRegex(options.allowDots);
49
47
 
50
- let isSanitized = false;
51
- let replaceWith = null;
52
- const dryRun = Boolean(options.dryRun);
53
- if (!regex.test(options.replaceWith) && options.replaceWith !== '.') {
54
- replaceWith = options.replaceWith;
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
- const wl = options.whitelist || [];
58
- RegExp.prototype.toJSON = RegExp.prototype.toString;
55
+ const wl = options.whitelist || [];
56
+ RegExp.prototype.toJSON = RegExp.prototype.toString;
59
57
 
60
- withEach(target, function (obj, val, key) {
61
- let shouldRecurse = true;
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
- shouldRecurse: shouldRecurse,
73
- key: key,
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
- shouldRecurse: shouldRecurse,
96
- key: key,
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
- return _sanitize(target, options).target;
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
- const hasOnSanitize = typeof options.onSanitize === 'function';
116
- return function (req, res, next) {
117
- ['body', 'params', 'headers', 'query'].forEach(function (key) {
118
- if (req[key]) {
119
- const { target, isSanitized } = _sanitize(req[key], options);
120
- req[key] = target;
121
- if (isSanitized && hasOnSanitize) {
122
- options.onSanitize({
123
- req,
124
- key,
125
- });
126
- }
127
- }
128
- });
129
- next();
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
- 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'.`);
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);
@@ -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 la plateforme data.primals.net.
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
- 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 :") +
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
- : i18n.t('assistant.noResults', "Aucun résultat trouvé.");
234
+ : i18n.t('assistant.noResults', "Aucun résultat trouvé.");
235
235
 
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
- }
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
- default:
261
- return {
262
- success: true,
263
- displayMessage: i18n.t('assistant.unknownAction', "Commande non reconnue.")
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
- 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}`);
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
 
@@ -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, myFreePremiumAnonymousLimiter, userInitiator} from "./user.js";
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
- engine.post('/api/backup/request-restore', [throttle, middlewareAuthenticator, userInitiator, myFreePremiumAnonymousLimiter], async (req, res) => {
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, myFreePremiumAnonymousLimiter], async (req, res) => {
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 || '', // S'assurer qu'il y a une valeur par défaut si vide
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