@galadrim/galadmin 0.1.227 → 0.1.230

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.
@@ -360,6 +360,7 @@ export type AuthRole = {
360
360
  useArgon2?: boolean;
361
361
  };
362
362
  export type Config = {
363
+ enriched?: boolean;
363
364
  name: string;
364
365
  sessionSecret: string;
365
366
  useMysql2?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@galadrim/galadmin",
3
- "version": "0.1.227",
3
+ "version": "0.1.230",
4
4
  "main": "dist/index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1",
@@ -41,7 +41,8 @@
41
41
  "@types/express": "^4.17.13",
42
42
  "@types/express-session": "1.17.0",
43
43
  "@types/mime": "^2.0.3",
44
- "@types/node": "^16.18.11"
44
+ "@types/node": "^16.18.11",
45
+ "typescript": "^5.9.3"
45
46
  },
46
47
  "repository": {
47
48
  "type": "git",
package/src/api.ts CHANGED
@@ -23,12 +23,55 @@ function generateUniqueIdForObject(obj) {
23
23
  return hash;
24
24
  }
25
25
 
26
- export default (db, config, user) => {
26
+ declare global {
27
+ namespace Express {
28
+ interface Request {
29
+ config?: any;
30
+ }
31
+ }
32
+ }
33
+
34
+ export default (db, config) => {
27
35
  const app = express();
28
36
 
37
+ app.use((req, res, next) => {
38
+ req.config = {
39
+ ...config,
40
+ views: config.views
41
+ .filter(x => !x.roles
42
+ || (req.session.user && ([...(x.roles || []), ...(x.readRoles || [])].includes(req.session.user.role)))
43
+ )
44
+ .map(view => {
45
+ const readOnly = req.session.user && view.roles && !view.roles.includes(req.session.user.role)
46
+ if (readOnly) {
47
+ return {
48
+ ...view,
49
+ canEdit: false,
50
+ canCreate: false,
51
+ canDelete: false,
52
+ clickToEdit: false
53
+ }
54
+ } else {
55
+ return view;
56
+ }
57
+ })
58
+ .map(view => {
59
+ if (view.type === "table") {
60
+ return {
61
+ ...view,
62
+ columns: view.columns.filter(column => !column.roles || (req.session.user && column.roles.includes(req.session.user.role)))
63
+ }
64
+ } else {
65
+ return view;
66
+ }
67
+ })
68
+ }
69
+ next();
70
+ });
71
+
29
72
  app.use(async (req, res, next) => {
30
- if (!config.enriched) {
31
- await enrichConfig(config, db);
73
+ if (!req.config.enriched) {
74
+ await enrichConfig(req.config, db);
32
75
  }
33
76
  next();
34
77
  });
@@ -124,7 +167,7 @@ export default (db, config, user) => {
124
167
 
125
168
  app.get("/config", async (req, res) => {
126
169
  try {
127
- const { mysql, auth, sessionSecret, ...safeConfig } = config;
170
+ const { mysql, auth, sessionSecret, ...safeConfig } = req.config;
128
171
  res.send({
129
172
  config: serializeJs(safeConfig),
130
173
  });
@@ -201,7 +244,7 @@ export default (db, config, user) => {
201
244
  };
202
245
 
203
246
  app.post("/foreignSelectRecords", async (req, res, next) => {
204
- const view = config.views[req.body.viewIndex];
247
+ const view = req.config.views[req.body.viewIndex];
205
248
  const column = [
206
249
  ...view.columns,
207
250
  ...(view.recordViewPanels
@@ -222,7 +265,7 @@ export default (db, config, user) => {
222
265
  ? `${column.searchableName} LIKE '${column.wholeSearch ? "%" : ""}${queryEscaped}%'`
223
266
  : null,
224
267
  column.filtersFromUser
225
- ? column.filtersFromUser(user.userId, user.role)
268
+ ? column.filtersFromUser(req.session.user.userId, req.session.user.role)
226
269
  : null,
227
270
  ]),
228
271
  join: column.join,
@@ -256,7 +299,7 @@ export default (db, config, user) => {
256
299
  });
257
300
 
258
301
  app.post("/records", async function (req, res, next) {
259
- const view = config.views[req.body.viewIndex];
302
+ const view = req.config.views[req.body.viewIndex];
260
303
  const isDesc = req.body.isDesc === null ? view.isDesc : req.body.isDesc;
261
304
  const subview =
262
305
  view.subviews && req.body.subviewIndex !== undefined
@@ -277,7 +320,7 @@ export default (db, config, user) => {
277
320
  subview?.filters,
278
321
  ...req.body.filters,
279
322
  view.filtersFromUser
280
- ? view.filtersFromUser(user.userId, user.role)
323
+ ? view.filtersFromUser(req.session.user.userId, req.session.user.role)
281
324
  : null,
282
325
  ]),
283
326
  having: subview?.having,
@@ -352,11 +395,11 @@ export default (db, config, user) => {
352
395
  " = " +
353
396
  (typeof data[key] === "string"
354
397
  ? "'" +
355
- data[key]
356
- .replace(/'/g, "\\'")
357
- .replace(/\n/g, "")
358
- .replace(/\r/g, "") +
359
- "'"
398
+ data[key]
399
+ .replace(/'/g, "\\'")
400
+ .replace(/\n/g, "")
401
+ .replace(/\r/g, "") +
402
+ "'"
360
403
  : typeof data[key] === "object"
361
404
  ? JSON.stringify(data[key])
362
405
  : data[key]) +
@@ -400,7 +443,7 @@ export default (db, config, user) => {
400
443
  }
401
444
 
402
445
  app.post("/recordsExport", async function (req, res) {
403
- const view = config.views[req.body.viewIndex];
446
+ const view = req.config.views[req.body.viewIndex];
404
447
  const orderBy = req.body.orderBy || view.orderBy;
405
448
  const isDesc = req.body.isDesc === null ? view.isDesc : req.body.isDesc;
406
449
  const subview =
@@ -462,7 +505,7 @@ export default (db, config, user) => {
462
505
  return res.status(500).send(err);
463
506
  }
464
507
  // Get viewIndex in fields
465
- const view = config.views[fields.viewIndex[0]];
508
+ const view = req.config.views[fields.viewIndex[0]];
466
509
  if (typeof view.parseImportFile !== "function") {
467
510
  return res
468
511
  .status(500)
@@ -553,7 +596,7 @@ export default (db, config, user) => {
553
596
  return res.status(500).send(err);
554
597
  }
555
598
  // Get viewIndex and panelIndex in fields
556
- const view = config.views[fields.viewIndex[0]];
599
+ const view = req.config.views[fields.viewIndex[0]];
557
600
  const panel = view.recordViewPanels[fields.panelIndex[0]];
558
601
  if (typeof panel.parseImportFile !== "function") {
559
602
  return res
@@ -634,13 +677,13 @@ export default (db, config, user) => {
634
677
  });
635
678
 
636
679
  app.get("/record", async function (req, res) {
637
- const view = config.views[req.query.viewIndex as string];
680
+ const view = req.config.views[req.query.viewIndex as string];
638
681
  const { err, rows } = await db.query(
639
682
  "SELECT " +
640
- (view.selectExpression || "*") +
641
- " FROM ?? " +
642
- (view.join || "") +
643
- " WHERE ?? = ?",
683
+ (view.selectExpression || "*") +
684
+ " FROM ?? " +
685
+ (view.join || "") +
686
+ " WHERE ?? = ?",
644
687
  [
645
688
  view.tableName,
646
689
  view.tableName + "." + view.primaryId,
@@ -665,7 +708,7 @@ export default (db, config, user) => {
665
708
  });
666
709
 
667
710
  app.post("/updateRecord", async function (req, res, next) {
668
- const view = config.views[req.body.viewIndex];
711
+ const view = req.config.views[req.body.viewIndex];
669
712
  for (let key in req.body.data) {
670
713
  if (
671
714
  req.body.data[key] == "NULL" ||
@@ -703,7 +746,7 @@ export default (db, config, user) => {
703
746
  data: req.body.data,
704
747
  previousData: req.body.previousData,
705
748
  });
706
- } catch (e) {}
749
+ } catch (e) { }
707
750
  }
708
751
  if (view.editCallbackFunction) {
709
752
  await view.editCallbackFunction({
@@ -715,20 +758,20 @@ export default (db, config, user) => {
715
758
  });
716
759
 
717
760
  app.post("/customAction", async function (req, res, next) {
718
- const view = config.views[req.body.viewIndex];
761
+ const view = req.config.views[req.body.viewIndex];
719
762
  const action = view.customActions[req.body.actionIndex];
720
763
  for (const recordId of req.body.selectedRecordIds) {
721
764
  try {
722
765
  const { rows } = await db.query(
723
766
  "SELECT " +
724
- (view.selectExpression || "*") +
725
- " FROM ?? " +
726
- (view.join || "") +
727
- " WHERE ?? = ?",
767
+ (view.selectExpression || "*") +
768
+ " FROM ?? " +
769
+ (view.join || "") +
770
+ " WHERE ?? = ?",
728
771
  [view.tableName, view.tableName + "." + view.primaryId, recordId]
729
772
  );
730
773
  const record = rows[0];
731
- const actionResult = await action.action(record, user.userId);
774
+ const actionResult = await action.action(record, req.session.user.userId);
732
775
  if (actionResult) {
733
776
  return res.send({
734
777
  success: true,
@@ -750,13 +793,13 @@ export default (db, config, user) => {
750
793
  });
751
794
 
752
795
  app.post("/deleteRecord", async function (req, res) {
753
- const view = config.views[req.body.viewIndex];
796
+ const view = req.config.views[req.body.viewIndex];
754
797
  const { rows, err: err2 } = await db.query(
755
798
  "SELECT " +
756
- (view.selectExpression || "*") +
757
- " FROM ?? " +
758
- (view.join || "") +
759
- " WHERE ?? = ?",
799
+ (view.selectExpression || "*") +
800
+ " FROM ?? " +
801
+ (view.join || "") +
802
+ " WHERE ?? = ?",
760
803
  [
761
804
  view.tableName,
762
805
  view.tableName + "." + view.primaryId,
@@ -783,7 +826,7 @@ export default (db, config, user) => {
783
826
  await axios.post(view.deleteCallback, {
784
827
  id: req.body.primaryValue,
785
828
  });
786
- } catch (e) {}
829
+ } catch (e) { }
787
830
  }
788
831
  if (view.deleteCallbackFunction) {
789
832
  await view.deleteCallbackFunction({
@@ -795,7 +838,7 @@ export default (db, config, user) => {
795
838
  });
796
839
 
797
840
  app.post("/deleteRecordFromPanel", async function (req, res) {
798
- const view = config.views[req.body.viewIndex];
841
+ const view = req.config.views[req.body.viewIndex];
799
842
  const panel = view.recordViewPanels.find(
800
843
  (x) => x.__id__ === req.body.panelId
801
844
  );
@@ -820,7 +863,7 @@ export default (db, config, user) => {
820
863
  await axios.post(panel.deleteCallback, {
821
864
  id: req.body.primaryValue,
822
865
  });
823
- } catch (e) {}
866
+ } catch (e) { }
824
867
  }
825
868
  if (panel.deleteCallbackFunction) {
826
869
  await panel.deleteCallbackFunction({
@@ -832,7 +875,7 @@ export default (db, config, user) => {
832
875
  });
833
876
 
834
877
  app.post("/deleteRecords", async function (req, res, next) {
835
- const view = config.views[req.body.viewIndex];
878
+ const view = req.config.views[req.body.viewIndex];
836
879
  const { err } = await db.query(
837
880
  `DELETE FROM ?? WHERE ?? IN(${req.body.primaryValues.map((x) => "'" + x + "'").join(",")})`,
838
881
  [view.tableName, view.primaryId]
@@ -866,7 +909,7 @@ export default (db, config, user) => {
866
909
  }
867
910
  }
868
911
 
869
- for (const view of config.views) {
912
+ for (const view of req.config.views) {
870
913
  await checkAndGetNotificationBadge(view);
871
914
  if (view.subviews) {
872
915
  for (const subview of view.subviews) {
@@ -923,7 +966,7 @@ export default (db, config, user) => {
923
966
  });
924
967
 
925
968
  app.post("/createRecord", async function (req, res, next) {
926
- const view = config.views[req.body.viewIndex];
969
+ const view = req.config.views[req.body.viewIndex];
927
970
  const panel = req.body.panelIndex
928
971
  ? view.recordViewPanels[req.body.panelIndex]
929
972
  : null;
@@ -982,7 +1025,7 @@ export default (db, config, user) => {
982
1025
  id: r.insertId,
983
1026
  data: req.body.data,
984
1027
  });
985
- } catch (e) {}
1028
+ } catch (e) { }
986
1029
  }
987
1030
  if (panel ? panel.createCallbackFunction : view.createCallbackFunction) {
988
1031
  await (
@@ -1015,8 +1058,8 @@ export default (db, config, user) => {
1015
1058
  }
1016
1059
  if (req.query.viewIndex && req.query.panelIndex) {
1017
1060
  const panel =
1018
- config.views[req.query.viewIndex as string].recordViewPanels[
1019
- req.query.panelIndex as string
1061
+ req.config.views[req.query.viewIndex as string].recordViewPanels[
1062
+ req.query.panelIndex as string
1020
1063
  ];
1021
1064
  if (panel.formatValue) {
1022
1065
  for (const row of rows) {
@@ -1171,9 +1214,9 @@ export default (db, config, user) => {
1171
1214
  await sftp.fastPut(
1172
1215
  files[fileParamName][0].path,
1173
1216
  column.publicPath +
1174
- (column.subdirectory ? "/" + column.subdirectory : "") +
1175
- "/" +
1176
- filename
1217
+ (column.subdirectory ? "/" + column.subdirectory : "") +
1218
+ "/" +
1219
+ filename
1177
1220
  );
1178
1221
  await sftp.end();
1179
1222
  res.send({
@@ -1211,7 +1254,7 @@ export default (db, config, user) => {
1211
1254
  );
1212
1255
 
1213
1256
  app.post("/uploadFile", async function (req, res, next) {
1214
- const view = config.views[req.query.viewIndex as string];
1257
+ const view = req.config.views[req.query.viewIndex as string];
1215
1258
  const column = [
1216
1259
  ...view.columns,
1217
1260
  ...(view.recordViewPanels
@@ -0,0 +1,12 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*) basedir=`cygpath -w "$basedir"`;;
6
+ esac
7
+
8
+ if [ -x "$basedir/node" ]; then
9
+ exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
10
+ else
11
+ exec node "$basedir/../semver/bin/semver.js" "$@"
12
+ fi
@@ -0,0 +1,17 @@
1
+ @ECHO off
2
+ GOTO start
3
+ :find_dp0
4
+ SET dp0=%~dp0
5
+ EXIT /b
6
+ :start
7
+ SETLOCAL
8
+ CALL :find_dp0
9
+
10
+ IF EXIST "%dp0%\node.exe" (
11
+ SET "_prog=%dp0%\node.exe"
12
+ ) ELSE (
13
+ SET "_prog=node"
14
+ SET PATHEXT=%PATHEXT:;.JS;=;%
15
+ )
16
+
17
+ endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env pwsh
2
+ $basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
3
+
4
+ $exe=""
5
+ if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
6
+ # Fix case when both the Windows and Linux builds of Node
7
+ # are installed in the same directory
8
+ $exe=".exe"
9
+ }
10
+ $ret=0
11
+ if (Test-Path "$basedir/node$exe") {
12
+ # Support pipeline input
13
+ if ($MyInvocation.ExpectingInput) {
14
+ $input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
15
+ } else {
16
+ & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
17
+ }
18
+ $ret=$LASTEXITCODE
19
+ } else {
20
+ # Support pipeline input
21
+ if ($MyInvocation.ExpectingInput) {
22
+ $input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
23
+ } else {
24
+ & "node$exe" "$basedir/../semver/bin/semver.js" $args
25
+ }
26
+ $ret=$LASTEXITCODE
27
+ }
28
+ exit $ret
package/src/index.ts CHANGED
@@ -151,39 +151,7 @@ export default (config: Config): any => {
151
151
  }
152
152
  })
153
153
 
154
- app.use("/api", (req, res, next) => {
155
- return api(db, {
156
- ...config,
157
- views: config.views
158
- .filter(x => !x.roles
159
- || (req.session.user && ([...(x.roles || []), ...(x.readRoles || [])].includes(req.session.user.role)))
160
- )
161
- .map(view => {
162
- const readOnly = req.session.user && view.roles && !view.roles.includes(req.session.user.role)
163
- if (readOnly) {
164
- return {
165
- ...view,
166
- canEdit: false,
167
- canCreate: false,
168
- canDelete: false,
169
- clickToEdit: false
170
- }
171
- } else {
172
- return view;
173
- }
174
- })
175
- .map(view => {
176
- if (view.type === "table") {
177
- return {
178
- ...view,
179
- columns: view.columns.filter(column => !column.roles || (req.session.user && column.roles.includes(req.session.user.role)))
180
- }
181
- } else {
182
- return view;
183
- }
184
- })
185
- }, req.session.user)(req, res, next)
186
- })
154
+ app.use("/api", api(db, config))
187
155
 
188
156
  // Serve static files
189
157
  app.get("*", (req, res) => {
@@ -194,7 +162,8 @@ export default (config: Config): any => {
194
162
 
195
163
  // Send media files just like they are
196
164
  if ([".woff", ".png"].includes(path.extname(filePath))) {
197
- res.sendFile(filePath)
165
+ res.contentType(mime.getType(filePath));
166
+ res.send(fs.readFileSync(filePath))
198
167
  } else {
199
168
  // For text files, we replace _HOMEPAGE_ with the base url of the back-office
200
169
  let fileContent = fs.readFileSync(filePath, { encoding: "utf-8" })
@@ -429,6 +429,9 @@ export type AuthRole = {
429
429
  };
430
430
 
431
431
  export type Config = {
432
+ /** Ne pas renseigner !!! */
433
+ enriched?: boolean;
434
+
432
435
  /** Nom du projet */
433
436
  name: string;
434
437
 
package/tsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "module": "commonjs",
4
+ "skipLibCheck": true,
4
5
  "declaration": true,
5
6
  "removeComments": true,
6
7
  "emitDecoratorMetadata": true,