@opengis/fastify-table 2.5.20 → 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.
@@ -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":"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 &&
@@ -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 || "")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengis/fastify-table",
3
- "version": "2.5.20",
3
+ "version": "2.5.21",
4
4
  "type": "module",
5
5
  "description": "core-plugins",
6
6
  "keywords": [