@opengis/fastify-table 2.5.18 → 2.5.21

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 (38) hide show
  1. package/dist/server/plugins/auth/funcs/getQuery.d.ts.map +1 -1
  2. package/dist/server/plugins/auth/funcs/getQuery.js +1 -1
  3. package/dist/server/plugins/crud/funcs/dataUpdate.d.ts.map +1 -1
  4. package/dist/server/plugins/crud/funcs/dataUpdate.js +2 -1
  5. package/dist/server/plugins/crud/funcs/utils/getInsertQuery.d.ts.map +1 -1
  6. package/dist/server/plugins/crud/funcs/utils/getInsertQuery.js +2 -1
  7. package/dist/server/plugins/crud/funcs/utils/nullif.d.ts +3 -0
  8. package/dist/server/plugins/crud/funcs/utils/nullif.d.ts.map +1 -0
  9. package/dist/server/plugins/crud/funcs/utils/nullif.js +10 -0
  10. package/dist/server/plugins/file/uploadMultiPart.d.ts.map +1 -1
  11. package/dist/server/plugins/file/uploadMultiPart.js +4 -1
  12. package/dist/server/plugins/policy/funcs/checkPolicy.d.ts.map +1 -1
  13. package/dist/server/plugins/policy/funcs/checkPolicy.js +2 -16
  14. package/dist/server/plugins/policy/funcs/checkTraversal.d.ts +2 -0
  15. package/dist/server/plugins/policy/funcs/checkTraversal.d.ts.map +1 -0
  16. package/dist/server/plugins/policy/funcs/checkTraversal.js +22 -0
  17. package/dist/server/plugins/policy/index.d.ts.map +1 -1
  18. package/dist/server/plugins/policy/index.js +3 -1
  19. package/dist/server/plugins/table/funcs/getSelect.js +3 -3
  20. package/dist/server/plugins/upload/startUpload.d.ts.map +1 -1
  21. package/dist/server/plugins/upload/startUpload.js +12 -3
  22. package/dist/server/plugins/usercls/index.d.ts +1 -2
  23. package/dist/server/plugins/usercls/index.d.ts.map +1 -1
  24. package/dist/server/plugins/usercls/index.js +29 -21
  25. package/dist/server/routes/file/controllers/resize.d.ts +4 -1
  26. package/dist/server/routes/file/controllers/resize.d.ts.map +1 -1
  27. package/dist/server/routes/file/controllers/resize.js +14 -1
  28. package/dist/server/routes/table/controllers/cardData.js +3 -3
  29. package/dist/server/routes/table/controllers/suggest.d.ts.map +1 -1
  30. package/dist/server/routes/table/controllers/suggest.js +17 -1
  31. package/dist/server/routes/table/functions/getData.d.ts.map +1 -1
  32. package/dist/server/routes/table/functions/getData.js +7 -6
  33. package/dist/server/routes/usercls/controllers/addUserCls.d.ts +8 -1
  34. package/dist/server/routes/usercls/controllers/addUserCls.d.ts.map +1 -1
  35. package/dist/server/routes/usercls/controllers/addUserCls.js +3 -5
  36. package/dist/server/routes/usercls/controllers/getUserCls.d.ts.map +1 -1
  37. package/dist/server/routes/usercls/controllers/getUserCls.js +18 -2
  38. package/package.json +99 -99
@@ -1 +1 @@
1
- {"version":3,"file":"getQuery.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/auth/funcs/getQuery.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,wBAA8B,QAAQ,CAAC,EACrC,EAAE,EACF,IAAI,GACL,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,gBAkIA"}
1
+ {"version":3,"file":"getQuery.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/auth/funcs/getQuery.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAGpD,wBAA8B,QAAQ,CAAC,EACrC,EAAE,EACF,IAAI,GACL,EAAE;IACD,EAAE,EAAE,UAAU,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC3B,gBAoIA"}
@@ -124,5 +124,5 @@ export default async function getQuery({ pg, data, }) {
124
124
  .query(`select * from admin.users where uid =(select uid from admin.users_social_auth
125
125
  where ${id ? "social_auth_id=$1" : "email=$1"} limit 1)`, [id || email])
126
126
  .then((el) => el.rows?.[0] || {});
127
- return result;
127
+ return { ...result, isNewUser: !(userId || socialUserId) };
128
128
  }
@@ -1 +1 @@
1
- {"version":3,"file":"dataUpdate.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataUpdate.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAepD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,EACH,GAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,gBAwPA"}
1
+ {"version":3,"file":"dataUpdate.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/crud/funcs/dataUpdate.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAiBpD,wBAA8B,UAAU,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,SAAS,EACT,OAAO,EACP,EAAE,EACF,IAAI,EACJ,EAAE,EAAE,GAAG,EACP,GAAG,EACH,GAAU,GACX,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,OAAO,CAAC;CACf,gBAwPA"}
@@ -8,6 +8,7 @@ import extraData from "../../extra/extraData.js";
8
8
  import logChanges from "./utils/logChanges.js";
9
9
  import logger from "../../logger/getLogger.js";
10
10
  import getInsertQuery from "./utils/getInsertQuery.js";
11
+ import nullif from "./utils/nullif.js";
11
12
  const rclient = getRedis();
12
13
  const srids = {};
13
14
  function assignValue(key, i, srid = 4326, columnType = "text") {
@@ -64,7 +65,7 @@ export default async function dataUpdate({ table: table1, tokenData, referer, id
64
65
  ["string", "number"].includes(typeof data[el])) {
65
66
  Object.assign(data, { [el]: data[el].split(",") });
66
67
  }
67
- return [el, data[el] === "" ? null : data[el]]; // ensure '' on number does not throw
68
+ return [el, nullif(data[el])]; // ensure '' on number does not throw
68
69
  })
69
70
  .map((el) => typeof el[1] === "object" && types[el[0]]?.includes?.("json") && el[1]
70
71
  ? JSON.stringify(el[1])
@@ -1 +1 @@
1
- {"version":3,"file":"getInsertQuery.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/getInsertQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAI5D,wBAA8B,cAAc,CAAC,EAC3C,EAAE,EACF,KAAK,EACL,IAAI,EACJ,EAAE,EACF,GAAG,GACJ,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;;;;;UA+EA"}
1
+ {"version":3,"file":"getInsertQuery.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/getInsertQuery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAM5D,wBAA8B,cAAc,CAAC,EAC3C,EAAE,EACF,KAAK,EACL,IAAI,EACJ,EAAE,EACF,GAAG,GACJ,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;;;;;UA+EA"}
@@ -1,4 +1,5 @@
1
1
  import getMeta from "../../../pg/funcs/getMeta.js";
2
+ import nullif from "./nullif.js";
2
3
  export default async function getInsertQuery({ pg, table, data, id, uid, }) {
3
4
  if (!pg?.pk || !data) {
4
5
  return null;
@@ -54,7 +55,7 @@ export default async function getInsertQuery({ pg, table, data, id, uid, }) {
54
55
  typeof el[1]?.[0] === "object" ||
55
56
  types[el[0]] === "json")
56
57
  ? JSON.stringify(el[1])
57
- : el[1]),
58
+ : nullif(el[1])),
58
59
  ];
59
60
  const keys = filterData.map((el) => el[0]);
60
61
  return { insertQuery, args, keys, systemColumns };
@@ -0,0 +1,3 @@
1
+ declare const nullif: (val: any) => any;
2
+ export default nullif;
3
+ //# sourceMappingURL=nullif.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nullif.d.ts","sourceRoot":"","sources":["../../../../../../server/plugins/crud/funcs/utils/nullif.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,MAAM,GAAI,KAAK,GAAG,QAQvB,CAAC;AAEF,eAAe,MAAM,CAAC"}
@@ -0,0 +1,10 @@
1
+ const nullif = (val) => {
2
+ if (Array.isArray(val) && val.length === 0) {
3
+ return null;
4
+ }
5
+ if (typeof val === "string" && val === "") {
6
+ return null;
7
+ }
8
+ return val;
9
+ };
10
+ export default nullif;
@@ -1 +1 @@
1
- {"version":3,"file":"uploadMultiPart.d.ts","sourceRoot":"","sources":["../../../../server/plugins/file/uploadMultiPart.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,KAAK;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2CD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAkBvE;AAED,wBAAsB,gBAAgB,CACpC,EACE,IAAI,EAAE,QAAQ,EACd,MAA2C,EAC3C,MAAM,GACP,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACpD,MAAM,MAAW,mBA+BlB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,GAAG,EACR,EACE,UAAU,EACV,GAAG,EACH,MAAM,EACN,gBAAwB,GACzB,GAAE;IACD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GACL,OAAO,CAAC,KAAK,CAAC,CAmHhB;AAED,eAAe,eAAe,CAAC"}
1
+ {"version":3,"file":"uploadMultiPart.d.ts","sourceRoot":"","sources":["../../../../server/plugins/file/uploadMultiPart.ts"],"names":[],"mappings":"AA6BA,MAAM,WAAW,KAAK;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AA2CD,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAkBvE;AAED,wBAAsB,gBAAgB,CACpC,EACE,IAAI,EAAE,QAAQ,EACd,MAA2C,EAC3C,MAAM,GACP,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EACpD,MAAM,MAAW,mBA+BlB;AAED,wBAAsB,eAAe,CACnC,GAAG,EAAE,GAAG,EACR,EACE,UAAU,EACV,GAAG,EACH,MAAM,EACN,gBAAwB,GACzB,GAAE;IACD,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CACvB,GACL,OAAO,CAAC,KAAK,CAAC,CAwHhB;AAED,eAAe,eAAe,CAAC"}
@@ -90,6 +90,10 @@ export async function uploadMultiPart(req, { extensions, raw, subdir, originalFi
90
90
  if (extensions && !extensions.includes(ext)) {
91
91
  throw new BadRequestError("file extension is not allowed");
92
92
  }
93
+ const dir = subdir != null ? subdir : req.params?.["*"] || "uploads";
94
+ if (dir.replace(/%2e/g, ".").replace(/%2E/g, ".").includes("..")) {
95
+ throw new ConflictError("path traversal is not allowed");
96
+ }
93
97
  // ! check extension by core list if custom not provided - from filename
94
98
  if (!extensions && !allowedExtensions.includes(ext.substring(1))) {
95
99
  throw new BadRequestError("file extension is not allowed");
@@ -119,7 +123,6 @@ export async function uploadMultiPart(req, { extensions, raw, subdir, originalFi
119
123
  if (fileExtension !== nameExt) {
120
124
  throw new ConflictError("file type spoofing attempt detected");
121
125
  }
122
- const dir = subdir != null ? subdir : req.params?.["*"] || "uploads";
123
126
  const yearMonthDay = subdir != null ? "" : new Date().toISOString().split("T")[0];
124
127
  const dbname = req.pg?.options?.database || req.pg?.database || config.pg?.database; // request / config params / default config params
125
128
  const rootDir = config.root || `/data/local/${dbname || ""}`;
@@ -1 +1 @@
1
- {"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAKhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,GAAG,QAmJlE"}
1
+ {"version":3,"file":"checkPolicy.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,eAAe,EAEhB,MAAM,wBAAwB,CAAC;AAKhC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,GAAG,QAkIlE"}
@@ -1,5 +1,5 @@
1
1
  import { config, logger } from "../../../../utils.js";
2
- import { ConflictError, ForbiddenError } from "../../../../errors.js";
2
+ import { ForbiddenError } from "../../../../errors.js";
3
3
  export default function checkPolicy(req, jwt) {
4
4
  const { originalUrl: path, hostname, query, params, headers, method, routeOptions, } = req;
5
5
  const user = req.user || req.session?.passport?.user;
@@ -12,7 +12,7 @@ export default function checkPolicy(req, jwt) {
12
12
  hostname.startsWith("admin");
13
13
  const { role, referer, policy = [], } = (routeOptions?.config || {});
14
14
  // role=admin|regular
15
- const isRole = (role && (!user?.user_type || !role?.includes?.(user?.user_type))) ||
15
+ const isRole = (role && (!user?.user_type || !user?.user_type?.includes?.(role))) ||
16
16
  (policy.includes("admin") && !user?.user_type?.includes?.("admin"));
17
17
  const allowExtPublic = [".png", ".jpg", ".svg"];
18
18
  const ext = path.toLowerCase().substr(-4);
@@ -47,20 +47,6 @@ export default function checkPolicy(req, jwt) {
47
47
  });
48
48
  throw ForbiddenError("access restricted: 0");
49
49
  }
50
- // ! file injection
51
- if (JSON.stringify(params || {})?.includes("../") ||
52
- JSON.stringify(query || {})?.includes("../") ||
53
- path?.includes("../")) {
54
- logger.file("injection/file", {
55
- path,
56
- method,
57
- params,
58
- query,
59
- body,
60
- uid: user?.uid,
61
- });
62
- throw ConflictError("access restricted: 1");
63
- }
64
50
  // ! invalid file extension
65
51
  if (path.includes("files/") && allowExtPublic.includes(ext)) {
66
52
  return null;
@@ -0,0 +1,2 @@
1
+ export default function checkTraversal(request: any): void;
2
+ //# sourceMappingURL=checkTraversal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checkTraversal.d.ts","sourceRoot":"","sources":["../../../../../server/plugins/policy/funcs/checkTraversal.ts"],"names":[],"mappings":"AAUA,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,OAAO,EAAE,GAAG,QAgBlD"}
@@ -0,0 +1,22 @@
1
+ import { logger } from "../../../../utils.js";
2
+ import { ConflictError } from "../../../../errors.js";
3
+ const decodeTraversal = (str) => str
4
+ .replace(/%2e/g, ".")
5
+ .replace(/%2E/g, ".")
6
+ .replace(/%2f/g, "/")
7
+ .replace(/%2F/g, "/");
8
+ export default function checkTraversal(request) {
9
+ const { method, originalUrl, query, params, user } = request;
10
+ if (decodeTraversal(JSON.stringify(params || {})).includes("../") ||
11
+ decodeTraversal(JSON.stringify(query || {})).includes("../") ||
12
+ decodeTraversal(originalUrl).includes("../")) {
13
+ logger.file("injection/file", {
14
+ path: originalUrl,
15
+ method,
16
+ params,
17
+ query,
18
+ uid: user?.uid,
19
+ });
20
+ throw ConflictError("path traversal detected");
21
+ }
22
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/policy/index.ts"],"names":[],"mappings":"AAMA,iBAAS,MAAM,CAAC,OAAO,EAAE,GAAG,QA6B3B;AAED,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/policy/index.ts"],"names":[],"mappings":"AAOA,iBAAS,MAAM,CAAC,OAAO,EAAE,GAAG,QA+B3B;AAED,eAAe,MAAM,CAAC"}
@@ -1,9 +1,11 @@
1
1
  import config from "../../../config.js";
2
2
  import checkPolicy from "./funcs/checkPolicy.js";
3
+ import checkTraversal from "./funcs/checkTraversal.js";
3
4
  import checkPermissions from "./funcs/checkPermissions.js";
4
5
  import checkJWT from "./funcs/checkJWT.js";
5
6
  function plugin(fastify) {
6
- fastify.addHook("preHandler", async (request, reply) => {
7
+ fastify.addHook("preHandler", async (request) => {
8
+ checkTraversal(request);
7
9
  // ! skip locally, skip tests
8
10
  if ((process.env.local === "true" || process.env.NODE_ENV === "test") &&
9
11
  !config.debugAuth &&
@@ -12,10 +12,10 @@ export default async function getSelect(name, pg = pgClients.client, nocache = f
12
12
  return loadCls[name];
13
13
  }
14
14
  const clsDataGIT = await getTemplate(["cls", "select"], name);
15
- const { type } = pg.pk?.["admin.user_cls"] && false
15
+ const { type } = pg.pk?.["admin.user_cls"]
16
16
  ? await pg
17
- .query("select type from admin.user_cls where parent is null and name=$1 union all select type from admin.cls where parent is null and name=$1 limit 1", [name])
18
- .then((el) => el.rows?.[0] || {})
17
+ .query("select type from admin.user_cls where parent is null and name=$1 and type<>'sql' union all select type from admin.cls where parent is null and name=$1 and type<>'sql' limit 1", [name])
18
+ .then((r) => r.rows?.[0] || {})
19
19
  : {};
20
20
  const clsDataDB = sqls[type || ""]
21
21
  ? await pg
@@ -1 +1 @@
1
- {"version":3,"file":"startUpload.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/startUpload.ts"],"names":[],"mappings":"AAoBA,wBAA8B,WAAW,CAAC,EACxC,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,gBAAwB,GACzB,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,gBA6FA"}
1
+ {"version":3,"file":"startUpload.d.ts","sourceRoot":"","sources":["../../../../server/plugins/upload/startUpload.ts"],"names":[],"mappings":"AAyBA,wBAA8B,WAAW,CAAC,EACxC,IAAI,EACJ,EAAE,EACF,QAAQ,EACR,IAAI,EACJ,MAAM,EACN,gBAAwB,GACzB,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,gBA2GA"}
@@ -4,20 +4,29 @@ import { mkdir, writeFile } from "node:fs/promises";
4
4
  import config from "../../../config.js";
5
5
  import getUploadStatus from "./getUploadStatus.js";
6
6
  import { prefix, fileDir, metaDir, uploadChunkDirectory, fetchTimeoutMs, } from "./index.js";
7
+ import { all } from "../file/utils/allowedExtensions.js";
7
8
  import mimes from "../file/providers/mime/mimes.js";
8
9
  import { startUpload as startUploadS3 } from "./s3.js";
9
- import { BadRequestError, NotImplementedError } from "../../../errors.js";
10
+ import { BadRequestError, ForbiddenError, NotImplementedError, } from "../../../errors.js";
10
11
  const { chunkSize = 5242880 } = config;
11
12
  export default async function startUpload({ host, id, fileName, size, subdir, originalFilename = false, }) {
12
- if (subdir && (typeof subdir !== "string" || subdir.includes(".."))) {
13
+ if (subdir &&
14
+ (typeof subdir !== "string" ||
15
+ subdir.replace(/%2e/g, ".").replace(/%2E/g, ".").includes(".."))) {
13
16
  throw BadRequestError("invalid params: subdir");
14
17
  }
15
18
  if (originalFilename) {
16
19
  throw NotImplementedError("currently not supported");
17
20
  }
21
+ if (!fileName) {
22
+ throw BadRequestError("not enough params: fileName");
23
+ }
24
+ const extension = path.extname(fileName).substring(1);
25
+ if (!all.includes(extension)) {
26
+ throw ForbiddenError("file extension is not allowed");
27
+ }
18
28
  if (!host) {
19
29
  const id1 = id || randomUUID();
20
- const extension = path.extname(fileName).substring(1);
21
30
  const yearMonthDay = subdir ? "" : new Date().toISOString().split("T")[0];
22
31
  const relativeDirpath = path
23
32
  .join(uploadChunkDirectory, subdir || "", yearMonthDay || "")
@@ -29,12 +29,11 @@ export declare function editUserCls({ name, alias, description, data, }: {
29
29
  alias?: string[];
30
30
  data: string | Record<string, any>[];
31
31
  }, pg?: any): Promise<string>;
32
- export declare function getUserClsList({ name, search, sql, custom, type, }: {
32
+ export declare function getUserClsList({ name, search, sql, custom, }: {
33
33
  name?: string;
34
34
  search?: string;
35
35
  sql?: any;
36
36
  custom?: string;
37
- type?: string;
38
37
  }, pg?: any): Promise<any>;
39
38
  export declare function getUserCls(name: string, pg?: any): Promise<{
40
39
  type: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/usercls/index.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,CAChC,EACE,IAAI,EACJ,WAAW,EACX,KAAK,EACL,KAAK,EACL,GAAG,EACH,IAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QACJ,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,EAAE,CAAC;CACL,EACD,EAAE,MAAmB,mBA8EtB;AAED,wBAAsB,aAAa,CACjC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/C,EAAE,MAAmB,mBAgBtB;AAED,wBAAsB,UAAU,CAC9B,EACE,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CACtC,EACD,EAAE,MAAmB,mBAqDtB;AAED,wBAAsB,WAAW,CAC/B,EACE,IAAI,EACJ,KAAK,EACL,WAAW,EACX,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CACtC,EACD,EAAE,MAAmB,mBAKtB;AAED,wBAAsB,cAAc,CAClC,EACE,IAAI,EACJ,MAAM,EACN,GAAG,EACH,MAAM,EACN,IAAI,GACL,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,EACD,EAAE,MAAmB,gBAgDtB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAmB;;;;;UAsBnE;;AAED,wBAAoB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../server/plugins/usercls/index.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,CAChC,EACE,IAAI,EACJ,WAAW,EACX,KAAK,EACL,KAAK,EACL,GAAG,EACH,IAAS,GACV,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE;QACJ,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,OAAO,CAAC;KAClB,EAAE,CAAC;CACL,EACD,EAAE,MAAmB,mBA8EtB;AAED,wBAAsB,aAAa,CACjC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EAC/C,EAAE,MAAmB,mBAgBtB;AAED,wBAAsB,UAAU,CAC9B,EACE,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,WAAW,GACZ,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CACtC,EACD,EAAE,MAAmB,mBAwDtB;AAED,wBAAsB,WAAW,CAC/B,EACE,IAAI,EACJ,KAAK,EACL,WAAW,EACX,IAAI,GACL,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;CACtC,EACD,EAAE,MAAmB,mBAKtB;AAED,wBAAsB,cAAc,CAClC,EACE,IAAI,EACJ,MAAM,EACN,GAAG,EACH,MAAM,GACP,EAAE;IACD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;CAEjB,EACD,EAAE,MAAmB,gBA0DtB;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,MAAmB;;;;;UAuBnE;;AAED,wBAAoB"}
@@ -1,4 +1,4 @@
1
- import { NotFoundError } from "../../../errors.js";
1
+ import { ForbiddenError, NotFoundError } from "../../../errors.js";
2
2
  import pgClients from "../pg/pgClients.js";
3
3
  import dataInsert from "../crud/funcs/dataInsert.js";
4
4
  import dataUpdate from "../crud/funcs/dataUpdate.js";
@@ -8,10 +8,10 @@ export async function addCustomCls({ name, description, alias, table, uid, data
8
8
  }
9
9
  const codes = await pg
10
10
  .query(`select array_agg(code) from ${table}`)
11
- .then((el) => el.rows?.[0]?.array_agg || []);
11
+ .then((r) => r.rows?.[0]?.array_agg || []);
12
12
  const ids = await pg
13
13
  .query(`select json_object_agg(code, id) from ${table}`)
14
- .then((el) => el.rows?.[0]?.json_object_agg || {});
14
+ .then((r) => r.rows?.[0]?.json_object_agg || {});
15
15
  const client = await pg.connect();
16
16
  try {
17
17
  await client.query("BEGIN");
@@ -88,6 +88,7 @@ export async function addUserCls({ name, alias, data, description, }, pg = pgCli
88
88
  try {
89
89
  await client.query("begin");
90
90
  if (type === "sql") {
91
+ throw ForbiddenError("access restricted: creation of custom selects is not allowed");
91
92
  await dataInsert({
92
93
  pg: client,
93
94
  table: "admin.user_cls",
@@ -126,23 +127,29 @@ export async function editUserCls({ name, alias, description, data, }, pg = pgCl
126
127
  await addUserCls({ name, alias, description, data }, pg);
127
128
  return "ok";
128
129
  }
129
- export async function getUserClsList({ name, search, sql, custom, type, }, pg = pgClients.client) {
130
- const args = [name ? name.split(",") : null, search].filter(Boolean);
131
- const typeStr = type ? { cls: "json", select: "sql" }[type] : null;
132
- const idx = search && name ? 2 : 1;
133
- const where = [
134
- name ? "name=any($1::text[])" : null,
135
- search
136
- ? `( name ilike '%'||$${idx}||'%' or name in (select parent from admin.user_cls where name ilike '%'||$${idx}||'%') )`
137
- : null,
138
- ]
139
- .filter(Boolean)
140
- .join(" and ") || "1=1";
141
- console.log(name, search, where);
130
+ export async function getUserClsList({ name, search, sql, custom, }, pg = pgClients.client) {
131
+ const args = [];
132
+ const where = [];
133
+ if (name) {
134
+ args.push(name.split(","));
135
+ where.push(`name=any($${args.length}::text[])`);
136
+ }
137
+ if (search) {
138
+ args.push(`%${search}%`);
139
+ where.push(`( name ilike $${args.length} or name in (select parent from admin.user_cls where name ilike $${args.length}) )`);
140
+ }
141
+ // const typeStr = type ? { cls: "json", select: "sql" }[type] : null;
142
+ const typeStr = "json";
143
+ if (typeStr) {
144
+ args.push(typeStr);
145
+ where.push(`type=$${args.length}`);
146
+ }
147
+ const whereQuery = where.join(" and ") || "1=1";
148
+ console.log(name, search, whereQuery);
142
149
  const customQuery = `select true as custom, name, type, description, alias, case when type = 'sql' then 1 else (select count(*) from admin.user_cls where parent=t.name limit 1) end as count
143
- from admin.user_cls t where parent is null and ${where} and ${typeStr ? `type='${typeStr}'` : "true"}`;
150
+ from admin.user_cls t where parent is null and ${whereQuery}`;
144
151
  const gitQuery = `select false as custom, name, type, null as description, null as alias, case when type = 'sql' then 1 else (select count(*) from admin.cls where parent=t.name limit 1) end as count
145
- from admin.cls t where parent is null and ${where.replace(/admin.user_cls/g, "admin.cls")} and ${typeStr ? `type='${typeStr}'` : "true"}`;
152
+ from admin.cls t where parent is null and ${whereQuery.replace(/admin.user_cls/g, "admin.cls")}`;
146
153
  const q = [
147
154
  custom !== "0" ? customQuery : null,
148
155
  custom !== "1" ? gitQuery : null,
@@ -152,7 +159,7 @@ export async function getUserClsList({ name, search, sql, custom, type, }, pg =
152
159
  .concat(" order by name");
153
160
  if (sql)
154
161
  return q;
155
- const rows = await pg.query(q, args).then((el) => el.rows || []);
162
+ const rows = await pg.query(q, args).then((r) => r.rows || []);
156
163
  const customRows = rows.filter((row) => row.custom);
157
164
  const customClsNames = customRows.map((row) => row.name);
158
165
  const filteredRows = rows.filter((row) => !customClsNames.includes(row.name));
@@ -161,14 +168,15 @@ export async function getUserClsList({ name, search, sql, custom, type, }, pg =
161
168
  export async function getUserCls(name, pg = pgClients.client) {
162
169
  const { type, data, description, alias } = await pg
163
170
  .query("select type, data, description, alias from admin.user_cls where parent is null and name=$1", [name])
164
- .then((el) => el.rows?.[0] || {});
171
+ .then((r) => r.rows?.[0] || {});
165
172
  if (type === "sql") {
173
+ throw ForbiddenError("custom selects not allowed");
166
174
  return { type, data, description, alias };
167
175
  }
168
176
  if (type === "json") {
169
177
  const options = await pg
170
178
  .query(`select json_agg(json_build_object('id', code, 'text', name, 'icon', icon, 'color', color)) from admin.user_cls where parent=$1`, [name])
171
- .then((el) => el.rows?.[0]?.json_agg || []);
179
+ .then((r) => r.rows?.[0]?.json_agg || []);
172
180
  return { type, data: options, description, alias };
173
181
  }
174
182
  return null;
@@ -13,5 +13,8 @@ export default function resize({ query, }: {
13
13
  format?: string;
14
14
  noimage?: any;
15
15
  };
16
- }, reply: FastifyReply): Promise<never>;
16
+ }, reply: FastifyReply): Promise<import("fastify").FastifyError & {
17
+ code: "NOT_FOUND_ERROR";
18
+ statusCode: 404;
19
+ }>;
17
20
  //# sourceMappingURL=resize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/resize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0C5C;;GAEG;AAEH,wBAA8B,MAAM,CAClC,EACE,KAAK,GACN,EAAE;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;CACH,EACD,KAAK,EAAE,YAAY,kBA2IpB"}
1
+ {"version":3,"file":"resize.d.ts","sourceRoot":"","sources":["../../../../../server/routes/file/controllers/resize.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AA0C5C;;GAEG;AAEH,wBAA8B,MAAM,CAClC,EACE,KAAK,GACN,EAAE;IACD,KAAK,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,CAAC,CAAC,EAAE,MAAM,CAAC;QACX,OAAO,CAAC,EAAE,GAAG,CAAC;QACd,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,OAAO,CAAC,EAAE,GAAG,CAAC;KACf,CAAC;CACH,EACD,KAAK,EAAE,YAAY;;;GAyJpB"}
@@ -8,7 +8,7 @@ isFileExists, getFolder, } from "../../../../utils.js";
8
8
  import grpc from "../../../plugins/grpc/grpc.js";
9
9
  import getMimeType from "../../../plugins/file/providers/mime/index.js";
10
10
  import { mkdir } from "node:fs/promises";
11
- import { BadRequestError } from "../../../../errors.js";
11
+ import { BadRequestError, NotFoundError } from "../../../../errors.js";
12
12
  const defaultWidth = 400;
13
13
  const defaultHeight = 240;
14
14
  const maxWidth = 2000;
@@ -38,6 +38,19 @@ export default async function resize({ query, }, reply) {
38
38
  if (!mimeType) {
39
39
  throw BadRequestError("invalid query params: filepath");
40
40
  }
41
+ // svg не підтримується
42
+ if (mimeType === "image/svg+xml") {
43
+ const fileData = await downloadFile(filepath, { buffer: true });
44
+ if (!fileData?.length) {
45
+ return NotFoundError(`Файл не знайдено - ${filepath}`);
46
+ }
47
+ return reply
48
+ .headers({
49
+ "Content-Type": "image/svg+xml",
50
+ "Cache-control": "max-age=604800",
51
+ })
52
+ .send(fileData);
53
+ }
41
54
  const resizePath1 = size
42
55
  ? filepath.replace(basename, `${size}_resized_${basename}`)
43
56
  : filepath.replace(basename, `${w || defaultWidth}_${h || (w ? "" : defaultHeight)}_resized_${basename}`);
@@ -1,6 +1,5 @@
1
1
  /* eslint-disable no-param-reassign */
2
2
  import path from "node:path";
3
- import config from "../../../../config.js";
4
3
  import { handlebars, handlebarsSync } from "../../../helpers/index.js";
5
4
  import getAccess from "../../../plugins/crud/funcs/getAccess.js";
6
5
  import setToken from "../../../plugins/crud/funcs/setToken.js";
@@ -80,8 +79,9 @@ export default async function getCardData(req, reply) {
80
79
  }
81
80
  // tokens result
82
81
  const tokens = {};
83
- if (!config.security?.disableToken &&
84
- index?.tokens &&
82
+ if (
83
+ // !config.security?.disableToken &&
84
+ index?.tokens &&
85
85
  typeof index?.tokens === "object" &&
86
86
  !Array.isArray(index?.tokens)) {
87
87
  Object.keys(index.tokens || {})
@@ -1 +1 @@
1
- {"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/suggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwBpD,wBAAsB,kBAAkB,CAAC,EACvC,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,EACH,EAAqB,GACtB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;;;;;UAwFA;AAED,wBAA8B,OAAO,CAAC,GAAG,EAAE,GAAG,gBAuY7C"}
1
+ {"version":3,"file":"suggest.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/controllers/suggest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAyBpD,wBAAsB,kBAAkB,CAAC,EACvC,KAAK,EACL,QAAQ,EACR,MAAM,EACN,UAAU,EACV,QAAQ,EACR,UAAU,EACV,GAAG,EACH,EAAqB,GACtB,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,UAAU,CAAC;CACjB;;;;;UAwFA;AAED,wBAA8B,OAAO,CAAC,GAAG,EAAE,GAAG,gBAoa7C"}
@@ -1,6 +1,6 @@
1
1
  import path from "node:path";
2
2
  import { existsSync, readFileSync } from "node:fs";
3
- import { config, getPGAsync, getTemplate, getSelectMeta, getMeta, applyHook, getSelectVal, logger, getSelect, metaFormat, getColumnCLS, pgClients, getFilter, } from "../../../../utils.js";
3
+ import { config, getPGAsync, getTemplate, getSelectMeta, getMeta, applyHook, getSelectVal, logger, getSelect, metaFormat, getColumnCLS, pgClients, getFilter, getUserClsList, } from "../../../../utils.js";
4
4
  import { BadRequestError, NotFoundError } from "../../../../errors.js";
5
5
  const defaultLimit = 50;
6
6
  export async function getTableColumnMeta({ table, template, column, selectName, filtered, startsWith, key, pg = pgClients.client, }) {
@@ -91,6 +91,22 @@ export default async function suggest(req) {
91
91
  table,
92
92
  })) || {}
93
93
  : {};
94
+ if (params.data === "list" &&
95
+ (user?.user_type === "admin" || process.platform === "win32")) {
96
+ const cls = await getTemplate("cls", "list");
97
+ const select = await getTemplate("select", "list");
98
+ const custom = await getUserClsList({ custom: "1" }).then((r) => (r || []).reduce((acc, curr) => ({
99
+ ...acc,
100
+ [curr.name]: curr.type,
101
+ }), {}));
102
+ return {
103
+ git: (cls || []).concat(select || []).reduce((acc, curr) => ({
104
+ ...acc,
105
+ [curr[0]]: curr[2],
106
+ }), {}),
107
+ custom,
108
+ };
109
+ }
94
110
  const body = await getTemplate("table", table);
95
111
  const tableName = hookBody?.table || body?.table || table;
96
112
  if (query.limit && query.limit < 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,KAAK,CAAC,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,GAAG,gBA64Bb"}
1
+ {"version":3,"file":"getData.d.ts","sourceRoot":"","sources":["../../../../../server/routes/table/functions/getData.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAwFzD,wBAA8B,OAAO,CACnC,EACE,EAAqB,EACrB,MAAM,EACN,KAAK,EACL,EAAE,EACF,OAAY,EACZ,KAAU,EACV,IAAS,EACT,YAAY,EACZ,YAAY,EACZ,KAAY,EACZ,UAAU,EACV,OAAO,EAAE,YAAY,EACrB,WAAW,EAAE,gBAAgB,EAC7B,OAAO,EAAE,YAAY,EACrB,QAAgB,GACjB,EAAE;IACD,EAAE,CAAC,EAAE,UAAU,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,EACD,KAAK,CAAC,EAAE,YAAY,EACpB,MAAM,CAAC,EAAE,GAAG,gBAw4Bb"}
@@ -209,14 +209,14 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
209
209
  !el.inline &&
210
210
  el?.sql?.replace &&
211
211
  !(isExport && el.export === false))
212
- .map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ${el.name || `t${i}`} on 1=1 `)
212
+ .map((el, i) => ` left join lateral (${el.sql}) ${el.name || `t${i}`} on 1=1 `)
213
213
  ?.join("") || "";
214
214
  const cardSqlFiltered = objectId
215
215
  ? cardSql?.filter?.((el) => !el?.disabled && el?.name && el?.sql?.replace) || []
216
216
  : [];
217
217
  const cardSqlTable = cardSqlFiltered.length
218
218
  ? cardSqlFiltered
219
- .map((el, i) => ` left join lateral (${el.sql.replace("{{uid}}", `$${idx.uid}`)}) ct${i} on 1=1 `)
219
+ .map((el, i) => ` left join lateral (${el.sql}) ct${i} on 1=1 `)
220
220
  .join("\n") || ""
221
221
  : "";
222
222
  const sqlInline = loadTable?.sql
@@ -385,7 +385,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
385
385
  timeArr.push(Date.now());
386
386
  if (uid &&
387
387
  rows.length &&
388
- !config.security?.disableToken &&
388
+ // !config.security?.disableToken &&
389
389
  (editable ||
390
390
  (tokenData?.actions || actionsParam)?.includes("edit") ||
391
391
  actions.includes("edit") ||
@@ -507,8 +507,9 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
507
507
  const tokens = {};
508
508
  if (template && objectId) {
509
509
  // tokens result
510
- if (!config.security?.disableToken &&
511
- index?.tokens &&
510
+ if (
511
+ // !config.security?.disableToken &&
512
+ index?.tokens &&
512
513
  typeof index?.tokens === "object" &&
513
514
  !Array.isArray(index?.tokens)) {
514
515
  Object.keys(index.tokens || {})
@@ -682,7 +683,7 @@ export default async function dataAPI({ pg = pgClients.client, params, table, id
682
683
  });
683
684
  }
684
685
  if (uid &&
685
- !config.security?.disableToken &&
686
+ // !config.security?.disableToken &&
686
687
  actions.includes("add") &&
687
688
  !objectId) {
688
689
  const addTokens = setToken({
@@ -1,2 +1,9 @@
1
- export default function addUserClsApi({ pg, body, user }: any, reply: any): Promise<any>;
1
+ export default function addUserClsApi({ pg, body, user, }: any): Promise<{
2
+ type?: any;
3
+ data?: any;
4
+ description?: any;
5
+ alias?: any;
6
+ time: number;
7
+ name: any;
8
+ }>;
2
9
  //# sourceMappingURL=addUserCls.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"addUserCls.d.ts","sourceRoot":"","sources":["../../../../../server/routes/usercls/controllers/addUserCls.ts"],"names":[],"mappings":"AAWA,wBAA8B,aAAa,CACzC,EAAE,EAAqB,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,EAC1C,KAAK,EAAE,GAAG,gBAqCX"}
1
+ {"version":3,"file":"addUserCls.d.ts","sourceRoot":"","sources":["../../../../../server/routes/usercls/controllers/addUserCls.ts"],"names":[],"mappings":"AAWA,wBAA8B,aAAa,CAAC,EAC1C,EAAqB,EACrB,IAAI,EACJ,IAAI,GACL,EAAE,GAAG;;;;;;;GAkCL"}
@@ -2,7 +2,7 @@ import { UnauthorizedError } from "../../../../errors.js";
2
2
  import pgClients from "../../../plugins/pg/pgClients.js";
3
3
  import getSelectMeta from "../../../plugins/table/funcs/getSelectMeta.js";
4
4
  import { addUserCls, addCustomCls, editUserCls, getUserCls, } from "../../../plugins/usercls/index.js";
5
- export default async function addUserClsApi({ pg = pgClients.client, body, user }, reply) {
5
+ export default async function addUserClsApi({ pg = pgClients.client, body, user, }) {
6
6
  const { name, description, alias, data, table } = body;
7
7
  const t1 = Date.now();
8
8
  if (!user?.uid) {
@@ -10,9 +10,7 @@ export default async function addUserClsApi({ pg = pgClients.client, body, user
10
10
  }
11
11
  if (table) {
12
12
  await addCustomCls({ name, description, alias, table, uid: user.uid, data }, pg);
13
- return reply
14
- .status(200)
15
- .send({ time: Date.now() - t1, name, type: "custom" });
13
+ return { time: Date.now() - t1, name, type: "custom" };
16
14
  }
17
15
  const exists = await getUserCls(name, pg);
18
16
  if (exists) {
@@ -28,5 +26,5 @@ export default async function addUserClsApi({ pg = pgClients.client, body, user
28
26
  nocache: 1,
29
27
  });
30
28
  const result = await getUserCls(name, pg);
31
- return reply.status(200).send({ time: Date.now() - t1, name, ...result });
29
+ return { time: Date.now() - t1, name, ...result };
32
30
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getUserCls.d.ts","sourceRoot":"","sources":["../../../../../server/routes/usercls/controllers/getUserCls.ts"],"names":[],"mappings":"AASA,wBAA8B,iBAAiB,CAAC,EAC9C,KAAK,EACL,IAAI,EACJ,EAAqB,GACtB,EAAE,GAAG,gBAyBL"}
1
+ {"version":3,"file":"getUserCls.d.ts","sourceRoot":"","sources":["../../../../../server/routes/usercls/controllers/getUserCls.ts"],"names":[],"mappings":"AAaA,wBAA8B,iBAAiB,CAAC,EAC9C,KAAK,EACL,IAAI,EACJ,EAAqB,GACtB,EAAE,GAAG,gBA2CL"}
@@ -2,6 +2,8 @@ import config from "../../../../config.js";
2
2
  import { UnauthorizedError } from "../../../../errors.js";
3
3
  import pgClients from "../../../plugins/pg/pgClients.js";
4
4
  import { getUserClsList } from "../../../plugins/usercls/index.js";
5
+ const customQueryCount = "select count(*)from admin.user_cls t where parent is null and type<>'sql'";
6
+ const gitQueryCount = "select count(*)from admin.cls t where parent is null";
5
7
  // query.name = cls1,cls2,cls3
6
8
  // query.search = substring of cls name
7
9
  // data[idx].count - should not depend on either query.name or query.search
@@ -16,11 +18,25 @@ export default async function getUserClsListApi({ query, user, pg = pgClients.cl
16
18
  const result = await getUserClsList({
17
19
  name: query.name,
18
20
  search: query.search,
19
- type: query.type,
21
+ // type: query.type,
20
22
  custom: query.custom,
21
23
  sql: query.sql,
22
24
  }, pg);
23
25
  if (query.sql)
24
26
  return result;
25
- return { time: Date.now() - t1, filtered: result.length, data: result };
27
+ const promises = [
28
+ query.custom === "0" || !query.custom
29
+ ? pg.query(gitQueryCount).then((r) => r.rows?.[0]?.count || 0)
30
+ : null,
31
+ query.custom === "1" || !query.custom
32
+ ? pg.query(customQueryCount).then((r) => r.rows?.[0]?.count || 0)
33
+ : null,
34
+ ];
35
+ const total = await Promise.all(promises).then((r) => r.reduce((a, b) => +a + +b, 0));
36
+ return {
37
+ time: Date.now() - t1,
38
+ total,
39
+ filtered: result.length,
40
+ data: result,
41
+ };
26
42
  }
package/package.json CHANGED
@@ -1,99 +1,99 @@
1
- {
2
- "name": "@opengis/fastify-table",
3
- "version": "2.5.18",
4
- "type": "module",
5
- "description": "core-plugins",
6
- "keywords": [
7
- "fastify",
8
- "table",
9
- "crud",
10
- "auth",
11
- "pg",
12
- "backend"
13
- ],
14
- "main": "dist/index.js",
15
- "exports": {
16
- ".": "./dist/index.js",
17
- "./index.js": "./dist/index.js",
18
- "./errors.js": "./dist/errors.js",
19
- "./utils.js": "./dist/utils.js",
20
- "./package.json": "./package.json"
21
- },
22
- "files": [
23
- "dist/*"
24
- ],
25
- "scripts": {
26
- "dump": "bun ./script/dump.ts",
27
- "migrate": "bun ./script/migrate.ts",
28
- "dump1": "bun ./dist/script/dump.js",
29
- "migrate1": "bun ./dist/script/migrate.js",
30
- "prepublishOnly": "npm run build",
31
- "clean": "tsc -b --clean",
32
- "build": "tsc -b --clean && tsc && copyfiles server/plugins/grpc/utils/*.proto dist && copyfiles server/migrations/*.sql dist && copyfiles server/templates/**/*.html dist && copyfiles server/templates/**/*.hbs dist && copyfiles script/* dist && copyfiles -u 2 module/core/*/* dist/module/core",
33
- "prod": "NODE_ENV=production bun dist/server",
34
- "patch": "npm version patch && git push && npm publish",
35
- "minor": "npm version minor && git push && npm publish",
36
- "major": "npm version major && git push && npm publish",
37
- "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
38
- "test": "npx vitest run",
39
- "compress": "node compress.js",
40
- "dev1": "bun --hot dist/server",
41
- "dev": "NODE_ENV=development bun start",
42
- "start": "LOG_LEVEL=trace bun server",
43
- "start1": "npx tsx server"
44
- },
45
- "dependencies": {
46
- "@aws-sdk/client-s3": "3.1079.0",
47
- "@aws-sdk/lib-storage": "3.1079.0",
48
- "@fastify/cookie": "11.0.2",
49
- "@fastify/http-proxy": "11.5.0",
50
- "@fastify/multipart": "10.0.0",
51
- "@fastify/passport": "3.0.2",
52
- "@fastify/rate-limit": "11.1.0",
53
- "@fastify/session": "11.1.1",
54
- "@grpc/grpc-js": "1.14.4",
55
- "@grpc/proto-loader": "0.8.1",
56
- "apache-crypt": "1.2.6",
57
- "dotenv": "17.4.2",
58
- "fastify": "5.9.0",
59
- "fastify-plugin": "6.0.0",
60
- "fastify-session-redis-store": "7.1.2",
61
- "file-type": "^22.0.1",
62
- "handlebars": "4.7.9",
63
- "image-size": "2.0.2",
64
- "ioredis": "5.11.1",
65
- "js-yaml": "5.2.1",
66
- "markdown-it": "14.3.0",
67
- "minio": "^8.0.7",
68
- "nodemailer": "9.0.3",
69
- "otplib": "13.4.1",
70
- "pg": "8.22.0",
71
- "pino": "10.3.1",
72
- "pino-abstract-transport": "3.0.0",
73
- "promised-handlebars": "2.0.1",
74
- "qrcode": "1.5.4",
75
- "sharp": "0.35.3",
76
- "uglify-js": "3.19.3",
77
- "undici": "8.6.0"
78
- },
79
- "devDependencies": {
80
- "@stylistic/eslint-plugin": "^5.10.0",
81
- "@types/bun": "^1.3.5",
82
- "@types/js-yaml": "^4.0.9",
83
- "@types/markdown-it": "^14.1.2",
84
- "@types/node": "^26.1.0",
85
- "@types/nodemailer": "^8.0.1",
86
- "@types/passport": "^1.0.17",
87
- "@types/passport-local": "^1.0.38",
88
- "@types/pg": "^8.20.0",
89
- "@types/qrcode": "^1.5.6",
90
- "copyfiles": "^2.4.1",
91
- "eslint": "^10.6.0",
92
- "eslint-stylistic-airbnb": "^3.2.0",
93
- "ts-migrate": "^0.1.35",
94
- "typescript": "^6.0.2",
95
- "vitest": "^4.1.2"
96
- },
97
- "author": "Softpro",
98
- "license": "ISC"
99
- }
1
+ {
2
+ "name": "@opengis/fastify-table",
3
+ "version": "2.5.21",
4
+ "type": "module",
5
+ "description": "core-plugins",
6
+ "keywords": [
7
+ "fastify",
8
+ "table",
9
+ "crud",
10
+ "auth",
11
+ "pg",
12
+ "backend"
13
+ ],
14
+ "main": "dist/index.js",
15
+ "exports": {
16
+ ".": "./dist/index.js",
17
+ "./index.js": "./dist/index.js",
18
+ "./errors.js": "./dist/errors.js",
19
+ "./utils.js": "./dist/utils.js",
20
+ "./package.json": "./package.json"
21
+ },
22
+ "files": [
23
+ "dist/*"
24
+ ],
25
+ "scripts": {
26
+ "dump": "bun ./script/dump.ts",
27
+ "migrate": "bun ./script/migrate.ts",
28
+ "dump1": "bun ./dist/script/dump.js",
29
+ "migrate1": "bun ./dist/script/migrate.js",
30
+ "prepublishOnly": "npm run build",
31
+ "clean": "tsc -b --clean",
32
+ "build": "tsc -b --clean && tsc && copyfiles server/plugins/grpc/utils/*.proto dist && copyfiles server/migrations/*.sql dist && copyfiles server/templates/**/*.html dist && copyfiles server/templates/**/*.hbs dist && copyfiles script/* dist && copyfiles -u 2 module/core/*/* dist/module/core",
33
+ "prod": "NODE_ENV=production bun dist/server",
34
+ "patch": "npm version patch && git push && npm publish",
35
+ "minor": "npm version minor && git push && npm publish",
36
+ "major": "npm version major && git push && npm publish",
37
+ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
38
+ "test": "npx vitest run",
39
+ "compress": "node compress.js",
40
+ "dev1": "bun --hot dist/server",
41
+ "dev": "NODE_ENV=development bun start",
42
+ "start": "LOG_LEVEL=trace bun server",
43
+ "start1": "npx tsx server"
44
+ },
45
+ "dependencies": {
46
+ "@aws-sdk/client-s3": "3.1079.0",
47
+ "@aws-sdk/lib-storage": "3.1079.0",
48
+ "@fastify/cookie": "11.0.2",
49
+ "@fastify/http-proxy": "11.5.0",
50
+ "@fastify/multipart": "10.0.0",
51
+ "@fastify/passport": "3.0.2",
52
+ "@fastify/rate-limit": "11.1.0",
53
+ "@fastify/session": "11.1.1",
54
+ "@grpc/grpc-js": "1.14.4",
55
+ "@grpc/proto-loader": "0.8.1",
56
+ "apache-crypt": "1.2.6",
57
+ "dotenv": "17.4.2",
58
+ "fastify": "5.9.0",
59
+ "fastify-plugin": "6.0.0",
60
+ "fastify-session-redis-store": "7.1.2",
61
+ "file-type": "^22.0.1",
62
+ "handlebars": "4.7.9",
63
+ "image-size": "2.0.2",
64
+ "ioredis": "5.11.1",
65
+ "js-yaml": "5.2.1",
66
+ "markdown-it": "14.3.0",
67
+ "minio": "^8.0.7",
68
+ "nodemailer": "9.0.3",
69
+ "otplib": "13.4.1",
70
+ "pg": "8.22.0",
71
+ "pino": "10.3.1",
72
+ "pino-abstract-transport": "3.0.0",
73
+ "promised-handlebars": "2.0.1",
74
+ "qrcode": "1.5.4",
75
+ "sharp": "0.35.3",
76
+ "uglify-js": "3.19.3",
77
+ "undici": "8.6.0"
78
+ },
79
+ "devDependencies": {
80
+ "@stylistic/eslint-plugin": "^5.10.0",
81
+ "@types/bun": "^1.3.5",
82
+ "@types/js-yaml": "^4.0.9",
83
+ "@types/markdown-it": "^14.1.2",
84
+ "@types/node": "^26.1.0",
85
+ "@types/nodemailer": "^8.0.1",
86
+ "@types/passport": "^1.0.17",
87
+ "@types/passport-local": "^1.0.38",
88
+ "@types/pg": "^8.20.0",
89
+ "@types/qrcode": "^1.5.6",
90
+ "copyfiles": "^2.4.1",
91
+ "eslint": "^10.6.0",
92
+ "eslint-stylistic-airbnb": "^3.2.0",
93
+ "ts-migrate": "^0.1.35",
94
+ "typescript": "^6.0.2",
95
+ "vitest": "^4.1.2"
96
+ },
97
+ "author": "Softpro",
98
+ "license": "ISC"
99
+ }