@galadrim/galadmin 0.1.234 → 0.1.236

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/src/api.ts CHANGED
@@ -18,6 +18,8 @@ import resolve from "@rollup/plugin-node-resolve";
18
18
  import axios from "axios";
19
19
  import { v4 as uuidv4 } from "uuid";
20
20
 
21
+ import { quoteIdentifier } from "./utils/dbManager";
22
+
21
23
  function generateUniqueIdForObject(obj) {
22
24
  const str = JSON.stringify(obj);
23
25
  const hash = crypto.createHash("sha256").update(str).digest("hex");
@@ -39,34 +41,47 @@ export default (db, config) => {
39
41
  req.config = {
40
42
  ...config,
41
43
  views: config.views
42
- .filter(x => !x.roles
43
- || (req.session.user && ([...(x.roles || []), ...(x.readRoles || [])].includes(req.session.user.role)))
44
+ .filter(
45
+ (x) =>
46
+ !x.roles ||
47
+ (req.session.user &&
48
+ [...(x.roles || []), ...(x.readRoles || [])].includes(
49
+ req.session.user.role,
50
+ )),
44
51
  )
45
- .map(view => {
46
- const readOnly = req.session.user && view.roles && !view.roles.includes(req.session.user.role)
52
+ .map((view) => {
53
+ const readOnly =
54
+ req.session.user &&
55
+ view.roles &&
56
+ !view.roles.includes(req.session.user.role);
47
57
  if (readOnly) {
48
58
  return {
49
59
  ...view,
50
60
  canEdit: false,
51
61
  canCreate: false,
52
62
  canDelete: false,
53
- clickToEdit: false
54
- }
63
+ clickToEdit: false,
64
+ };
55
65
  } else {
56
66
  return view;
57
67
  }
58
68
  })
59
- .map(view => {
69
+ .map((view) => {
60
70
  if (view.type === "table") {
61
71
  return {
62
72
  ...view,
63
- columns: view.columns.filter(column => !column.roles || (req.session.user && column.roles.includes(req.session.user.role)))
64
- }
73
+ columns: view.columns.filter(
74
+ (column) =>
75
+ !column.roles ||
76
+ (req.session.user &&
77
+ column.roles.includes(req.session.user.role)),
78
+ ),
79
+ };
65
80
  } else {
66
81
  return view;
67
82
  }
68
- })
69
- }
83
+ }),
84
+ };
70
85
  next();
71
86
  });
72
87
 
@@ -88,7 +103,8 @@ export default (db, config) => {
88
103
  // This block re-checks every sensitive route against the view's declared roles.
89
104
  // ---------------------------------------------------------------------------
90
105
  const ROOT_ROLE = "root";
91
- const roleOf = (req) => req.session && req.session.user && req.session.user.role;
106
+ const roleOf = (req) =>
107
+ req.session && req.session.user && req.session.user.role;
92
108
  // Write access = the view's `roles` (root always allowed).
93
109
  const canWriteView = (view, role) =>
94
110
  role === ROOT_ROLE || !view || !view.roles || view.roles.includes(role);
@@ -98,8 +114,8 @@ export default (db, config) => {
98
114
  req.body && req.body.viewIndex !== undefined
99
115
  ? req.body.viewIndex
100
116
  : req.query && req.query.viewIndex !== undefined
101
- ? req.query.viewIndex
102
- : undefined;
117
+ ? req.query.viewIndex
118
+ : undefined;
103
119
  if (idx === undefined || !req.config || !req.config.views) return undefined;
104
120
  return req.config.views[idx];
105
121
  };
@@ -122,8 +138,7 @@ export default (db, config) => {
122
138
  // Column names are interpolated into INSERT/UPDATE statements; only accept plain
123
139
  // SQL identifiers so a crafted key cannot break out of the column list.
124
140
  const areSafeColumnNames = (data) =>
125
- !data ||
126
- Object.keys(data).every((k) => /^[A-Za-z0-9_]+$/.test(k));
141
+ !data || Object.keys(data).every((k) => /^[A-Za-z0-9_]+$/.test(k));
127
142
 
128
143
  // Tables the current role is allowed to write, gathered from its writable views
129
144
  // and their creatable panels — used to bound /duplicateRecord's target table.
@@ -135,7 +150,8 @@ export default (db, config) => {
135
150
  if (view.tableName) tables.add(view.tableName);
136
151
  for (const panel of view.recordViewPanels || []) {
137
152
  if (panel.tableName) tables.add(panel.tableName);
138
- if (panel.createConfig?.tableName) tables.add(panel.createConfig.tableName);
153
+ if (panel.createConfig?.tableName)
154
+ tables.add(panel.createConfig.tableName);
139
155
  }
140
156
  }
141
157
  return tables;
@@ -147,7 +163,7 @@ export default (db, config) => {
147
163
  const looksLikeSqlBreakout = (frag) =>
148
164
  typeof frag === "string" &&
149
165
  /(;|--|\/\*|\bunion\b|\binto\s+(out|dump)file\b|\bsleep\s*\(|\bbenchmark\s*\(|\bload_file\s*\()/i.test(
150
- frag
166
+ frag,
151
167
  );
152
168
 
153
169
  app.use((req, res, next) => {
@@ -198,7 +214,7 @@ export default (db, config) => {
198
214
  } else if (columns[i].name) {
199
215
  queryString += columns[i].name
200
216
  .split(".")
201
- .map((x) => (db.dbType === "POSTGRESQL" ? x : "`" + x + "`"))
217
+ .map((x) => quoteIdentifier(x, db.dbType))
202
218
  .join(".");
203
219
  }
204
220
  queryString += " LIKE '%" + params.query.replace(/'/g, "\\'") + "%'";
@@ -210,16 +226,16 @@ export default (db, config) => {
210
226
  const limit = params.allRecords ? 999999 : parseInt(params.limit);
211
227
  const query =
212
228
  params.customQuery ||
213
- `SELECT
214
- ${params.selectExpression || "*"}
215
- FROM ${params.table}
216
- ${params.join || ""}
217
- ${queryString}
218
- ${params.groupBy ? "GROUP BY " + params.groupBy : ""}
219
- ${params.having ? " HAVING " + params.having : ""}
229
+ `SELECT
230
+ ${params.selectExpression || "*"}
231
+ FROM ${params.table}
232
+ ${params.join || ""}
233
+ ${queryString}
234
+ ${params.groupBy ? "GROUP BY " + params.groupBy : ""}
235
+ ${params.having ? " HAVING " + params.having : ""}
220
236
  ${params.orderBy || params.primaryId ? " ORDER BY " + (params.orderBy || `${params.table}.${params.primaryId}`) : ""}`;
221
237
  const { err, rows } = await db.query(
222
- `${query} LIMIT ${limit} OFFSET ${Math.max((params.page - 1) * limit, 0)}`
238
+ `${query} LIMIT ${limit} OFFSET ${Math.max((params.page - 1) * limit, 0)}`,
223
239
  );
224
240
  if (err) {
225
241
  console.error(err);
@@ -230,7 +246,7 @@ export default (db, config) => {
230
246
  let count = undefined;
231
247
  if (computeCount) {
232
248
  const { err: countErr, rows: countRows } = await db.query(
233
- `SELECT COUNT(*) AS count FROM (${query}) s`
249
+ `SELECT COUNT(*) AS count FROM (${query}) s`,
234
250
  );
235
251
  if (countErr) {
236
252
  const { rows: allRows } = await db.query(query);
@@ -256,7 +272,7 @@ export default (db, config) => {
256
272
  Object.assign(params, {
257
273
  page: parseInt(params.position) + parseInt(params.offset),
258
274
  limit: 1,
259
- })
275
+ }),
260
276
  );
261
277
  }
262
278
 
@@ -277,15 +293,15 @@ export default (db, config) => {
277
293
  const pkg = JSON.parse(
278
294
  fs.readFileSync(
279
295
  path.join(__dirname, "../src/front/package.json"),
280
- "utf-8"
281
- )
296
+ "utf-8",
297
+ ),
282
298
  );
283
299
  const external = Object.keys(pkg.dependencies || {});
284
300
  const bundle = await rollup.rollup({
285
301
  input: path.join(
286
302
  __dirname,
287
303
  "../../",
288
- req.query.componentPath as string
304
+ req.query.componentPath as string,
289
305
  ),
290
306
  plugins: [
291
307
  resolve(),
@@ -360,7 +376,10 @@ export default (db, config) => {
360
376
  ? `${column.searchableName} LIKE '${column.wholeSearch ? "%" : ""}${queryEscaped}%'`
361
377
  : null,
362
378
  column.filtersFromUser
363
- ? column.filtersFromUser(req.session.user.userId, req.session.user.role)
379
+ ? column.filtersFromUser(
380
+ req.session.user.userId,
381
+ req.session.user.role,
382
+ )
364
383
  : null,
365
384
  ]),
366
385
  join: column.join,
@@ -388,7 +407,7 @@ export default (db, config) => {
388
407
  value,
389
408
  label,
390
409
  };
391
- })
410
+ }),
392
411
  );
393
412
  res.send(options);
394
413
  });
@@ -415,7 +434,10 @@ export default (db, config) => {
415
434
  subview?.filters,
416
435
  ...req.body.filters,
417
436
  view.filtersFromUser
418
- ? view.filtersFromUser(req.session.user.userId, req.session.user.role)
437
+ ? view.filtersFromUser(
438
+ req.session.user.userId,
439
+ req.session.user.role,
440
+ )
419
441
  : null,
420
442
  ]),
421
443
  having: subview?.having,
@@ -434,7 +456,7 @@ export default (db, config) => {
434
456
  columns: view.columns,
435
457
  limit: view.limit || 10,
436
458
  },
437
- true
459
+ true,
438
460
  );
439
461
  if (error) {
440
462
  return res.status(500).send(error);
@@ -490,11 +512,11 @@ export default (db, config) => {
490
512
  " = " +
491
513
  (typeof data[key] === "string"
492
514
  ? "'" +
493
- data[key]
494
- .replace(/'/g, "\\'")
495
- .replace(/\n/g, "")
496
- .replace(/\r/g, "") +
497
- "'"
515
+ data[key]
516
+ .replace(/'/g, "\\'")
517
+ .replace(/\n/g, "")
518
+ .replace(/\r/g, "") +
519
+ "'"
498
520
  : typeof data[key] === "object"
499
521
  ? JSON.stringify(data[key])
500
522
  : data[key]) +
@@ -605,7 +627,7 @@ export default (db, config) => {
605
627
  return res
606
628
  .status(500)
607
629
  .send(
608
- '"parseImportFile" doit être défini dans la configuration de la vue.'
630
+ '"parseImportFile" doit être défini dans la configuration de la vue.',
609
631
  );
610
632
  }
611
633
 
@@ -628,7 +650,7 @@ export default (db, config) => {
628
650
 
629
651
  let queryString;
630
652
  if (db.dbType === "POSTGRESQL") {
631
- queryString = `INSERT INTO ?? (${columns.map((x) => `"${x}"`).join(", ")}) VALUES`;
653
+ queryString = `INSERT INTO ?? (${columns.map((x) => quoteIdentifier(x, db.dbType)).join(", ")}) VALUES`;
632
654
 
633
655
  for (let record of records) {
634
656
  const valuesList = columns
@@ -641,12 +663,12 @@ export default (db, config) => {
641
663
  ` ON CONFLICT (${view.importFileUniqueField}) DO UPDATE SET `;
642
664
 
643
665
  for (let column of columns) {
644
- queryString += `"${column}" = EXCLUDED."${column}",`;
666
+ queryString += `${quoteIdentifier(column, db.dbType)} = EXCLUDED.${quoteIdentifier(column, db.dbType)},`;
645
667
  }
646
668
  } else {
647
669
  queryString =
648
670
  "INSERT INTO ?? (" +
649
- columns.map((x) => "`" + x + "`").join(", ") +
671
+ columns.map((x) => quoteIdentifier(x, db.dbType)).join(", ") +
650
672
  ") VALUES";
651
673
  for (let record of records) {
652
674
  queryString +=
@@ -658,7 +680,7 @@ export default (db, config) => {
658
680
  }
659
681
  queryString = queryString.slice(0, -1) + " ON DUPLICATE KEY UPDATE";
660
682
  for (let column of columns) {
661
- queryString += " `" + column + "` = VALUES(`" + column + "`),";
683
+ queryString += ` ${quoteIdentifier(column, db.dbType)} = VALUES(${quoteIdentifier(column, db.dbType)}),`;
662
684
  }
663
685
  }
664
686
  queryString = queryString.slice(0, -1); // Remove the trailing comma
@@ -697,20 +719,20 @@ export default (db, config) => {
697
719
  return res
698
720
  .status(500)
699
721
  .send(
700
- '"parseImportFile" doit être défini dans la configuration du panneau.'
722
+ '"parseImportFile" doit être défini dans la configuration du panneau.',
701
723
  );
702
724
  }
703
725
  if (!Boolean(panel.createConfig)) {
704
726
  return res
705
727
  .status(500)
706
728
  .send(
707
- '"createConfig" doit être défini dans la configuration du panneau.'
729
+ '"createConfig" doit être défini dans la configuration du panneau.',
708
730
  );
709
731
  }
710
732
 
711
733
  const records = await panel.parseImportFile(
712
734
  files.data[0],
713
- fields.recordId[0]
735
+ fields.recordId[0],
714
736
  );
715
737
  const columns = [];
716
738
  if (records.length === 0) {
@@ -729,10 +751,10 @@ export default (db, config) => {
729
751
  }
730
752
 
731
753
  let queryString =
732
- "INSERT IGNORE INTO ?? (`" +
733
- panel.createConfig.recordIdKey +
734
- "`, " +
735
- columns.map((x) => "`" + x + "`").join(", ") +
754
+ "INSERT IGNORE INTO ?? (" +
755
+ quoteIdentifier(panel.createConfig.recordIdKey, db.dbType) +
756
+ ", " +
757
+ columns.map((x) => quoteIdentifier(x, db.dbType)).join(", ") +
736
758
  ") VALUES";
737
759
  for (let record of records) {
738
760
  queryString +=
@@ -746,7 +768,7 @@ export default (db, config) => {
746
768
  }
747
769
  queryString = queryString.slice(0, -1) + " ON DUPLICATE KEY UPDATE";
748
770
  for (let column of columns) {
749
- queryString += " `" + column + "` = VALUES(`" + column + "`),";
771
+ queryString += ` ${quoteIdentifier(column, db.dbType)} = VALUES(${quoteIdentifier(column, db.dbType)}),`;
750
772
  }
751
773
  const { err, rows: r } = await db.query(queryString.slice(0, -1), [
752
774
  panel.tableName,
@@ -775,15 +797,15 @@ export default (db, config) => {
775
797
  const view = req.config.views[req.query.viewIndex as string];
776
798
  const { err, rows } = await db.query(
777
799
  "SELECT " +
778
- (view.selectExpression || "*") +
779
- " FROM ?? " +
780
- (view.join || "") +
781
- " WHERE ?? = ?",
800
+ (view.selectExpression || "*") +
801
+ " FROM ?? " +
802
+ (view.join || "") +
803
+ " WHERE ?? = ?",
782
804
  [
783
805
  view.tableName,
784
806
  view.tableName + "." + view.primaryId,
785
807
  req.query.recordId,
786
- ]
808
+ ],
787
809
  );
788
810
  if (err) {
789
811
  return res.status(500).send(err);
@@ -820,10 +842,10 @@ export default (db, config) => {
820
842
  return res.sendStatus(200);
821
843
  }
822
844
  const queryExpression = Object.keys(req.body.data)
823
- .map((x) => `${x} = ?`)
845
+ .map((x) => `${quoteIdentifier(x, db.dbType)} = ?`)
824
846
  .join(", ");
825
847
  const queryParameters = Object.keys(req.body.data).map(
826
- (x) => req.body.data[x]
848
+ (x) => req.body.data[x],
827
849
  );
828
850
  const { err } = await db.query(
829
851
  `UPDATE ?? SET ${queryExpression} WHERE ?? = ?`,
@@ -832,7 +854,7 @@ export default (db, config) => {
832
854
  ...queryParameters,
833
855
  view.primaryId,
834
856
  req.body.primaryValue,
835
- ]
857
+ ],
836
858
  );
837
859
  if (err) {
838
860
  return res.status(500).send(err);
@@ -844,7 +866,7 @@ export default (db, config) => {
844
866
  data: req.body.data,
845
867
  previousData: req.body.previousData,
846
868
  });
847
- } catch (e) { }
869
+ } catch (e) {}
848
870
  }
849
871
  if (view.editCallbackFunction) {
850
872
  await view.editCallbackFunction({
@@ -862,14 +884,17 @@ export default (db, config) => {
862
884
  try {
863
885
  const { rows } = await db.query(
864
886
  "SELECT " +
865
- (view.selectExpression || "*") +
866
- " FROM ?? " +
867
- (view.join || "") +
868
- " WHERE ?? = ?",
869
- [view.tableName, view.tableName + "." + view.primaryId, recordId]
887
+ (view.selectExpression || "*") +
888
+ " FROM ?? " +
889
+ (view.join || "") +
890
+ " WHERE ?? = ?",
891
+ [view.tableName, view.tableName + "." + view.primaryId, recordId],
870
892
  );
871
893
  const record = rows[0];
872
- const actionResult = await action.action(record, req.session.user.userId);
894
+ const actionResult = await action.action(
895
+ record,
896
+ req.session.user.userId,
897
+ );
873
898
  if (actionResult) {
874
899
  return res.send({
875
900
  success: true,
@@ -894,15 +919,15 @@ export default (db, config) => {
894
919
  const view = req.config.views[req.body.viewIndex];
895
920
  const { rows, err: err2 } = await db.query(
896
921
  "SELECT " +
897
- (view.selectExpression || "*") +
898
- " FROM ?? " +
899
- (view.join || "") +
900
- " WHERE ?? = ?",
922
+ (view.selectExpression || "*") +
923
+ " FROM ?? " +
924
+ (view.join || "") +
925
+ " WHERE ?? = ?",
901
926
  [
902
927
  view.tableName,
903
928
  view.tableName + "." + view.primaryId,
904
929
  req.body.primaryValue,
905
- ]
930
+ ],
906
931
  );
907
932
  if (err2) {
908
933
  return res.status(500).send(err2);
@@ -924,7 +949,7 @@ export default (db, config) => {
924
949
  await axios.post(view.deleteCallback, {
925
950
  id: req.body.primaryValue,
926
951
  });
927
- } catch (e) { }
952
+ } catch (e) {}
928
953
  }
929
954
  if (view.deleteCallbackFunction) {
930
955
  await view.deleteCallbackFunction({
@@ -938,11 +963,11 @@ export default (db, config) => {
938
963
  app.post("/deleteRecordFromPanel", async function (req, res) {
939
964
  const view = req.config.views[req.body.viewIndex];
940
965
  const panel = view.recordViewPanels.find(
941
- (x) => x.__id__ === req.body.panelId
966
+ (x) => x.__id__ === req.body.panelId,
942
967
  );
943
968
  const { rows, err: err2 } = await db.query(
944
969
  "SELECT * FROM ?? WHERE ?? = ?",
945
- [panel.tableName, panel.primaryId, req.body.primaryValue]
970
+ [panel.tableName, panel.primaryId, req.body.primaryValue],
946
971
  );
947
972
  if (err2) {
948
973
  return res.status(500).send(err2);
@@ -961,7 +986,7 @@ export default (db, config) => {
961
986
  await axios.post(panel.deleteCallback, {
962
987
  id: req.body.primaryValue,
963
988
  });
964
- } catch (e) { }
989
+ } catch (e) {}
965
990
  }
966
991
  if (panel.deleteCallbackFunction) {
967
992
  await panel.deleteCallbackFunction({
@@ -976,7 +1001,7 @@ export default (db, config) => {
976
1001
  const view = req.config.views[req.body.viewIndex];
977
1002
  const { err } = await db.query(
978
1003
  `DELETE FROM ?? WHERE ?? IN(${req.body.primaryValues.map((x) => "'" + x + "'").join(",")})`,
979
- [view.tableName, view.primaryId]
1004
+ [view.tableName, view.primaryId],
980
1005
  );
981
1006
  if (err) {
982
1007
  return res.status(500).send(err);
@@ -1044,7 +1069,7 @@ export default (db, config) => {
1044
1069
  }
1045
1070
  const { err: err2, rows: r } = await db.query(
1046
1071
  "INSERT IGNORE INTO ?? SET ?",
1047
- [req.body.table, data]
1072
+ [req.body.table, data],
1048
1073
  );
1049
1074
  if (err2) {
1050
1075
  return res.status(500).send(err);
@@ -1090,7 +1115,7 @@ export default (db, config) => {
1090
1115
  req.body.data[panel.createConfig.recordIdKey] = req.body.recordId;
1091
1116
  }
1092
1117
  const primaryColumn = (view || panel)?.columns?.find(
1093
- (x) => x.name === (view || panel).primaryId
1118
+ (x) => x.name === (view || panel).primaryId,
1094
1119
  );
1095
1120
  if (primaryColumn?.dataType == "uuid") {
1096
1121
  req.body.data[primaryColumn.name] = uuidv4();
@@ -1108,16 +1133,18 @@ export default (db, config) => {
1108
1133
  if (!areSafeColumnNames(createPayload)) {
1109
1134
  return res.status(400).send({ error: "Invalid column name" });
1110
1135
  }
1111
- const queryExpression = Object.keys(createPayload).join(", ");
1136
+ const queryExpression = Object.keys(createPayload)
1137
+ .map((x) => quoteIdentifier(x, db.dbType))
1138
+ .join(", ");
1112
1139
  const queryPlaceholders = Object.keys(createPayload)
1113
1140
  .map((x) => "?")
1114
1141
  .join(", ");
1115
1142
  const queryParameters = Object.keys(createPayload).map(
1116
- (x) => createPayload[x]
1143
+ (x) => createPayload[x],
1117
1144
  );
1118
1145
  const { err, rows: r } = await db.query(
1119
1146
  `INSERT INTO ?? (${queryExpression}) VALUES(${queryPlaceholders})`,
1120
- [panel ? panel.tableName : view.tableName, ...queryParameters]
1147
+ [panel ? panel.tableName : view.tableName, ...queryParameters],
1121
1148
  );
1122
1149
  if (err) {
1123
1150
  console.error(err);
@@ -1135,7 +1162,7 @@ export default (db, config) => {
1135
1162
  id: r.insertId,
1136
1163
  data: req.body.data,
1137
1164
  });
1138
- } catch (e) { }
1165
+ } catch (e) {}
1139
1166
  }
1140
1167
  if (panel ? panel.createCallbackFunction : view.createCallbackFunction) {
1141
1168
  await (
@@ -1169,7 +1196,10 @@ export default (db, config) => {
1169
1196
  }
1170
1197
  for (const key of Object.keys(node)) {
1171
1198
  const value = node[key];
1172
- if (typeof value === "string" && (key === "query" || /Query$/.test(key))) {
1199
+ if (
1200
+ typeof value === "string" &&
1201
+ (key === "query" || /Query$/.test(key))
1202
+ ) {
1173
1203
  acc.add(value.trim());
1174
1204
  } else if (value && typeof value === "object") {
1175
1205
  collectAllowedQueries(value, acc);
@@ -1188,7 +1218,8 @@ export default (db, config) => {
1188
1218
  app.get("/customQuery", (req, res) => res.sendStatus(404));
1189
1219
  } else {
1190
1220
  app.get("/customQuery", async function (req, res, next) {
1191
- const template = typeof req.query.query === "string" ? req.query.query : "";
1221
+ const template =
1222
+ typeof req.query.query === "string" ? req.query.query : "";
1192
1223
  // SECURITY: only run whitelisted, read-only templates, and bind the record id
1193
1224
  // as a parameter instead of substituting it into the SQL string.
1194
1225
  const allowed = collectAllowedQueries(req.config.views);
@@ -1196,7 +1227,9 @@ export default (db, config) => {
1196
1227
  return res.status(403).send({ error: "Query not allowed" });
1197
1228
  }
1198
1229
  if (!/^\s*\(?\s*(select|with)\b/i.test(template) || /;/.test(template)) {
1199
- return res.status(400).send({ error: "Only read-only queries are allowed" });
1230
+ return res
1231
+ .status(400)
1232
+ .send({ error: "Only read-only queries are allowed" });
1200
1233
  }
1201
1234
  const placeholderCount = (template.match(/\?/g) || []).length;
1202
1235
  const params = new Array(placeholderCount).fill(req.query.primaryValue);
@@ -1207,7 +1240,7 @@ export default (db, config) => {
1207
1240
  if (req.query.viewIndex && req.query.panelIndex) {
1208
1241
  const panel =
1209
1242
  req.config.views[req.query.viewIndex as string].recordViewPanels[
1210
- req.query.panelIndex as string
1243
+ req.query.panelIndex as string
1211
1244
  ];
1212
1245
  if (panel.formatValue) {
1213
1246
  for (const row of rows) {
@@ -1240,7 +1273,7 @@ export default (db, config) => {
1240
1273
  }
1241
1274
  const originalFilenameWithoutExtension = originalFilename.replace(
1242
1275
  "." + extension,
1243
- ""
1276
+ "",
1244
1277
  );
1245
1278
 
1246
1279
  if (column.gcpConfig) {
@@ -1302,7 +1335,7 @@ export default (db, config) => {
1302
1335
  Key: path,
1303
1336
  ContentType: contentType,
1304
1337
  }),
1305
- { expiresIn: 150 }
1338
+ { expiresIn: 150 },
1306
1339
  )
1307
1340
  .then((signedUrl) =>
1308
1341
  axios.put(
@@ -1314,8 +1347,8 @@ export default (db, config) => {
1314
1347
  headers: {
1315
1348
  "Content-Type": contentType,
1316
1349
  },
1317
- }
1318
- )
1350
+ },
1351
+ ),
1319
1352
  )
1320
1353
  .then(() => {
1321
1354
  res.status(200).send({
@@ -1337,7 +1370,7 @@ export default (db, config) => {
1337
1370
  ContentType: contentType,
1338
1371
  ACL: "public-read",
1339
1372
  Key: path,
1340
- })
1373
+ }),
1341
1374
  )
1342
1375
  .then(() => {
1343
1376
  res.send({
@@ -1377,9 +1410,9 @@ export default (db, config) => {
1377
1410
  await sftp.fastPut(
1378
1411
  files[fileParamName][0].path,
1379
1412
  column.publicPath +
1380
- (column.subdirectory ? "/" + column.subdirectory : "") +
1381
- "/" +
1382
- filename
1413
+ (column.subdirectory ? "/" + column.subdirectory : "") +
1414
+ "/" +
1415
+ filename,
1383
1416
  );
1384
1417
  await sftp.end();
1385
1418
  res.send({
@@ -1410,10 +1443,10 @@ export default (db, config) => {
1410
1443
  "/uploadFileFromBetterRichTextInput",
1411
1444
  async function (req, res, next) {
1412
1445
  const fileUploadProperties = JSON.parse(
1413
- req.headers["file-upload-properties"] as string
1446
+ req.headers["file-upload-properties"] as string,
1414
1447
  );
1415
1448
  uploadFile(fileUploadProperties, "upload", req, res);
1416
- }
1449
+ },
1417
1450
  );
1418
1451
 
1419
1452
  app.post("/uploadFile", async function (req, res, next) {
@@ -1438,12 +1471,12 @@ export default (db, config) => {
1438
1471
  where: `denominationunitelegale LIKE '${processedQuery}*' OR siret LIKE '${processedQuery}*'`,
1439
1472
  limit: 100,
1440
1473
  },
1441
- }
1474
+ },
1442
1475
  );
1443
1476
  const results = response.data.results
1444
1477
  .filter(
1445
1478
  (etablissement) =>
1446
- etablissement.etatadministratifetablissement === "Actif"
1479
+ etablissement.etatadministratifetablissement === "Actif",
1447
1480
  )
1448
1481
  .map((etablissement) => ({
1449
1482
  id: Math.random().toString().slice(2),
@@ -1468,7 +1501,7 @@ export default (db, config) => {
1468
1501
  async function enrichConfig(config, db) {
1469
1502
  const { rows: info, err } = await db.query(
1470
1503
  "SELECT * FROM information_schema.columns WHERE table_schema = ?",
1471
- [config.mysql?.database || config.postgresql?.database]
1504
+ [config.mysql?.database || config.postgresql?.database],
1472
1505
  );
1473
1506
  if (err) {
1474
1507
  console.error(err);
@@ -1517,7 +1550,7 @@ function enrichColumn(column, tableName, info) {
1517
1550
  column.__id__ = generateUniqueIdForObject(column);
1518
1551
  }
1519
1552
  const infoEl = info.find(
1520
- (x) => x.TABLE_NAME == tableName && x.COLUMN_NAME == column.name
1553
+ (x) => x.TABLE_NAME == tableName && x.COLUMN_NAME == column.name,
1521
1554
  );
1522
1555
  if (
1523
1556
  infoEl?.IS_NULLABLE == "NO" &&
@@ -1534,7 +1567,7 @@ function enrichColumn(column, tableName, info) {
1534
1567
  column.options = JSON.parse(
1535
1568
  infoEl.COLUMN_TYPE.replace("enum(", "[")
1536
1569
  .replace(")", "]")
1537
- .replace(/'/g, '"')
1570
+ .replace(/'/g, '"'),
1538
1571
  );
1539
1572
  }
1540
1573
  }
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "files": {
3
3
  "main.css": "/_HOMEPAGE_/static/css/main.eacc50f1.css",
4
- "main.js": "/_HOMEPAGE_/static/js/main.f024ade6.js",
4
+ "main.js": "/_HOMEPAGE_/static/js/main.70ad8e58.js",
5
5
  "static/media/gt-eesti-medium.woff": "/_HOMEPAGE_/static/media/gt-eesti-medium.a48c02fa57e83ab6ddcd.woff",
6
6
  "static/media/gt-eesti-regular.woff": "/_HOMEPAGE_/static/media/gt-eesti-regular.304a7ae06ee4a4d5d04a.woff",
7
7
  "static/media/logo.png": "/_HOMEPAGE_/static/media/logo.e407b9ca7e302466a07d.png",
8
8
  "static/media/cubano.woff": "/_HOMEPAGE_/static/media/cubano.4eaa47ef94222121a371.woff",
9
9
  "index.html": "/_HOMEPAGE_/index.html",
10
10
  "main.eacc50f1.css.map": "/_HOMEPAGE_/static/css/main.eacc50f1.css.map",
11
- "main.f024ade6.js.map": "/_HOMEPAGE_/static/js/main.f024ade6.js.map"
11
+ "main.70ad8e58.js.map": "/_HOMEPAGE_/static/js/main.70ad8e58.js.map"
12
12
  },
13
13
  "entrypoints": [
14
14
  "static/css/main.eacc50f1.css",
15
- "static/js/main.f024ade6.js"
15
+ "static/js/main.70ad8e58.js"
16
16
  ]
17
17
  }