@nocobase/server 2.2.0-beta.13 → 2.2.0-beta.15

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.
@@ -944,6 +944,7 @@ const _Application = class _Application extends import_koa.default {
944
944
  }
945
945
  });
946
946
  this._dataSourceManager.use(this._authManager.middleware(), { tag: "auth", before: "default" });
947
+ this._dataSourceManager.use(import_auth.csrfMiddleware, { tag: "csrf", after: "auth", before: "default" });
947
948
  this._dataSourceManager.use(import_validate_filter_params.default, { tag: "validate-filter-params", before: ["auth"] });
948
949
  this._dataSourceManager.use(import_middlewares.parseVariables, {
949
950
  group: "parseVariables",
@@ -78,6 +78,17 @@ function normalizeBasePath(path = "") {
78
78
  return normalized || "/";
79
79
  }
80
80
  __name(normalizeBasePath, "normalizeBasePath");
81
+ function getFilesPathPrefixes(appPublicPath = "/") {
82
+ const normalizedPublicPath = normalizeBasePath(appPublicPath);
83
+ const canonicalPrefix = `${normalizedPublicPath === "/" ? "" : normalizedPublicPath}/files/`;
84
+ return canonicalPrefix === "/files/" ? ["/files/"] : [canonicalPrefix, "/files/"];
85
+ }
86
+ __name(getFilesPathPrefixes, "getFilesPathPrefixes");
87
+ function getFileAccessRestPath(pathname, appPublicPath = "/") {
88
+ const prefix = getFilesPathPrefixes(appPublicPath).find((prefix2) => pathname.startsWith(prefix2));
89
+ return prefix ? pathname.slice(prefix.length) : null;
90
+ }
91
+ __name(getFileAccessRestPath, "getFileAccessRestPath");
81
92
  function getSocketPath() {
82
93
  const socketPath = import_node_process.default.env.SOCKET_PATH;
83
94
  if (socketPath) {
@@ -202,6 +213,17 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
202
213
  req.url = rewrittenUrl;
203
214
  }
204
215
  }
216
+ const fileAccessRestPath = parsedUrl.pathname ? getFileAccessRestPath(parsedUrl.pathname, import_node_process.default.env.APP_PUBLIC_PATH || "/") : null;
217
+ if (fileAccessRestPath) {
218
+ const restPath = fileAccessRestPath;
219
+ const [pathAppName] = restPath.split("/");
220
+ if (pathAppName) {
221
+ try {
222
+ ctx.resolvedAppName = decodeURIComponent(pathAppName);
223
+ } catch (error) {
224
+ }
225
+ }
226
+ }
205
227
  await next();
206
228
  },
207
229
  {
@@ -337,7 +359,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
337
359
  return (0, import_utils3.injectRuntimeScript)(html, this.getV2RuntimeConfigScript());
338
360
  }
339
361
  async requestHandler(req, res) {
340
- const { pathname } = (0, import_url.parse)(req.url);
362
+ const { pathname, search } = (0, import_url.parse)(req.url);
341
363
  const { PLUGIN_STATICS_PATH } = import_node_process.default.env;
342
364
  const APP_PUBLIC_PATH = this.getAppPublicPath();
343
365
  if (pathname.endsWith("/__umi/api/bundle-status")) {
@@ -345,6 +367,12 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
345
367
  res.end("ok");
346
368
  return;
347
369
  }
370
+ if (APP_PUBLIC_PATH !== "/" && pathname.startsWith("/files/")) {
371
+ res.statusCode = 302;
372
+ res.setHeader("Location", `${APP_PUBLIC_PATH.replace(/\/$/, "")}${pathname}${search || ""}`);
373
+ res.end();
374
+ return;
375
+ }
348
376
  const supervisor = import_app_supervisor.AppSupervisor.getInstance();
349
377
  let handleApp = "main";
350
378
  try {
@@ -361,7 +389,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
361
389
  return;
362
390
  }
363
391
  }
364
- const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(pathname);
392
+ const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(`${pathname}${search || ""}`);
365
393
  for (const [key, value] of Object.entries(headers)) {
366
394
  res.setHeader(key, value);
367
395
  }
@@ -407,7 +435,8 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
407
435
  ]
408
436
  });
409
437
  }
410
- if (!pathname.startsWith(import_node_process.default.env.API_BASE_PATH)) {
438
+ const isFilesRequest = Boolean(getFileAccessRestPath(pathname, APP_PUBLIC_PATH));
439
+ if (!pathname.startsWith(import_node_process.default.env.API_BASE_PATH) && !isFilesRequest) {
411
440
  if (this.isV2Request(pathname)) {
412
441
  if (handleApp !== "main") {
413
442
  const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
@@ -47,6 +47,15 @@ function stripQueryAndHash(pathname = "") {
47
47
  return pathname.split("?")[0].split("#")[0];
48
48
  }
49
49
  __name(stripQueryAndHash, "stripQueryAndHash");
50
+ function shouldDownload(pathname = "") {
51
+ var _a;
52
+ const query = (_a = pathname.split("?")[1]) == null ? void 0 : _a.split("#")[0];
53
+ if (!query) {
54
+ return false;
55
+ }
56
+ return new URLSearchParams(query).get("download") === "1";
57
+ }
58
+ __name(shouldDownload, "shouldDownload");
50
59
  function hasActiveContentExtension(pathname = "") {
51
60
  const ext = import_node_path.default.extname(stripQueryAndHash(pathname)).toLowerCase();
52
61
  return ACTIVE_CONTENT_EXTENSIONS.has(ext);
@@ -56,7 +65,7 @@ function getStorageUploadSecurityHeaders(pathname = "") {
56
65
  const headers = {
57
66
  "X-Content-Type-Options": "nosniff"
58
67
  };
59
- if (hasActiveContentExtension(pathname)) {
68
+ if (hasActiveContentExtension(pathname) || shouldDownload(pathname)) {
60
69
  headers["Content-Disposition"] = "attachment";
61
70
  }
62
71
  return headers;
package/lib/helper.js CHANGED
@@ -76,23 +76,28 @@ function createResourcer(options) {
76
76
  return new import_resourcer.Resourcer({ ...options.resourcer });
77
77
  }
78
78
  __name(createResourcer, "createResourcer");
79
+ function isWhitelistedCorsOrigin(ctx) {
80
+ const origin = ctx.get("origin");
81
+ const whitelist = (0, import_utils.getCorsWhitelist)();
82
+ if (!origin) {
83
+ return false;
84
+ }
85
+ if (!whitelist) {
86
+ return (0, import_utils.isTrustedOrigin)(ctx, origin);
87
+ }
88
+ return whitelist.has(origin);
89
+ }
90
+ __name(isWhitelistedCorsOrigin, "isWhitelistedCorsOrigin");
79
91
  function resolveCorsOrigin(ctx) {
80
92
  const origin = ctx.get("origin");
81
93
  const disallowNoOrigin = process.env.CORS_DISALLOW_NO_ORIGIN === "true";
82
- const whitelistString = process.env.CORS_ORIGIN_WHITELIST;
83
94
  if (!origin && disallowNoOrigin) {
84
95
  return false;
85
96
  }
86
- if (!whitelistString) {
97
+ if (isWhitelistedCorsOrigin(ctx)) {
87
98
  return origin;
88
99
  }
89
- const whitelist = new Set(
90
- whitelistString.split(",").map((item) => item.trim()).filter(Boolean)
91
- );
92
- if (whitelist.has(origin)) {
93
- return origin;
94
- }
95
- return false;
100
+ return (0, import_utils.getCorsWhitelist)() ? false : origin;
96
101
  }
97
102
  __name(resolveCorsOrigin, "resolveCorsOrigin");
98
103
  function registerMiddlewares(app, options) {
@@ -108,6 +113,7 @@ function registerMiddlewares(app, options) {
108
113
  app.use((0, import_logger.requestLogger)(app.name, app.requestLogger, (_a = options.logger) == null ? void 0 : _a.request), { tag: "logger" });
109
114
  app.use(
110
115
  (0, import_cors.default)({
116
+ credentials: isWhitelistedCorsOrigin,
111
117
  exposeHeaders: ["content-disposition"],
112
118
  origin: resolveCorsOrigin,
113
119
  ...options.cors
@@ -134,8 +140,18 @@ function registerMiddlewares(app, options) {
134
140
  }
135
141
  app.use(/* @__PURE__ */ __name(async function getBearerToken(ctx, next) {
136
142
  ctx.getBearerToken = () => {
137
- const token = ctx.get("Authorization").replace(/^Bearer\s+/gi, "");
138
- return token || ctx.query.token;
143
+ const authorization = ctx.get("Authorization");
144
+ if (authorization) {
145
+ ctx.state.pendingAuthTokenSource = "authorization";
146
+ return authorization.replace(/^Bearer\s+/gi, "");
147
+ }
148
+ if (ctx.query.token) {
149
+ ctx.state.pendingAuthTokenSource = "query";
150
+ return ctx.query.token;
151
+ }
152
+ const cookieToken = ctx.cookies.get((0, import_utils.getAuthCookieName)("authToken", app.name));
153
+ ctx.state.pendingAuthTokenSource = cookieToken ? "cookie" : void 0;
154
+ return cookieToken;
139
155
  };
140
156
  await next();
141
157
  }, "getBearerToken"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "2.2.0-beta.13",
3
+ "version": "2.2.0-beta.15",
4
4
  "main": "lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -10,21 +10,21 @@
10
10
  "@koa/cors": "^5.0.0",
11
11
  "@koa/multer": "^3.1.0",
12
12
  "@koa/router": "^13.1.0",
13
- "@nocobase/acl": "2.2.0-beta.13",
14
- "@nocobase/actions": "2.2.0-beta.13",
15
- "@nocobase/ai": "2.2.0-beta.13",
16
- "@nocobase/auth": "2.2.0-beta.13",
17
- "@nocobase/cache": "2.2.0-beta.13",
18
- "@nocobase/data-source-manager": "2.2.0-beta.13",
19
- "@nocobase/database": "2.2.0-beta.13",
20
- "@nocobase/evaluators": "2.2.0-beta.13",
21
- "@nocobase/lock-manager": "2.2.0-beta.13",
22
- "@nocobase/logger": "2.2.0-beta.13",
23
- "@nocobase/resourcer": "2.2.0-beta.13",
24
- "@nocobase/sdk": "2.2.0-beta.13",
25
- "@nocobase/snowflake-id": "2.2.0-beta.13",
26
- "@nocobase/telemetry": "2.2.0-beta.13",
27
- "@nocobase/utils": "2.2.0-beta.13",
13
+ "@nocobase/acl": "2.2.0-beta.15",
14
+ "@nocobase/actions": "2.2.0-beta.15",
15
+ "@nocobase/ai": "2.2.0-beta.15",
16
+ "@nocobase/auth": "2.2.0-beta.15",
17
+ "@nocobase/cache": "2.2.0-beta.15",
18
+ "@nocobase/data-source-manager": "2.2.0-beta.15",
19
+ "@nocobase/database": "2.2.0-beta.15",
20
+ "@nocobase/evaluators": "2.2.0-beta.15",
21
+ "@nocobase/lock-manager": "2.2.0-beta.15",
22
+ "@nocobase/logger": "2.2.0-beta.15",
23
+ "@nocobase/resourcer": "2.2.0-beta.15",
24
+ "@nocobase/sdk": "2.2.0-beta.15",
25
+ "@nocobase/snowflake-id": "2.2.0-beta.15",
26
+ "@nocobase/telemetry": "2.2.0-beta.15",
27
+ "@nocobase/utils": "2.2.0-beta.15",
28
28
  "@types/decompress": "4.2.7",
29
29
  "@types/ini": "^1.3.31",
30
30
  "@types/koa-send": "^4.1.3",
@@ -61,5 +61,5 @@
61
61
  "@types/serve-handler": "^6.1.1",
62
62
  "@types/ws": "^8.5.5"
63
63
  },
64
- "gitHead": "8fff12b34f41f4336075cdafcc700ec694f9b78a"
64
+ "gitHead": "4c471f6b7d26adc412b2cc1d91264572296ca873"
65
65
  }