@nocobase/server 2.4.0-alpha.3 → 2.4.0-alpha.5
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/lib/app-supervisor/index.js +3 -0
- package/lib/gateway/index.js +2 -23
- package/lib/gateway/static-file-security.js +1 -0
- package/lib/helper.js +57 -2
- package/package.json +17 -17
|
@@ -389,6 +389,9 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
389
389
|
if (!appOptions) {
|
|
390
390
|
return;
|
|
391
391
|
}
|
|
392
|
+
if (appModel.environments && !appModel.environments.includes(this.environmentName)) {
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
392
395
|
const newApp = this.registerApp({ appModel, mainApp: app2 });
|
|
393
396
|
newApp.runCommand("start", "--quickstart");
|
|
394
397
|
}
|
package/lib/gateway/index.js
CHANGED
|
@@ -66,7 +66,6 @@ var import_plugin_manager = require("../plugin-manager");
|
|
|
66
66
|
var import_errors = require("./errors");
|
|
67
67
|
var import_ipc_socket_client = require("./ipc-socket-client");
|
|
68
68
|
var import_ipc_socket_server = require("./ipc-socket-server");
|
|
69
|
-
var import_static_file_security = require("./static-file-security");
|
|
70
69
|
var import_utils3 = require("./utils");
|
|
71
70
|
var import_ws_server = require("./ws-server");
|
|
72
71
|
var import_node_worker_threads = require("node:worker_threads");
|
|
@@ -608,27 +607,6 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
|
|
|
608
607
|
this.responseErrorWithCode("APP_INITIALIZING", res, { appName: handleApp });
|
|
609
608
|
return;
|
|
610
609
|
}
|
|
611
|
-
if (pathname.startsWith(APP_PUBLIC_PATH + "storage/uploads/")) {
|
|
612
|
-
if (handleApp !== "main") {
|
|
613
|
-
const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
|
|
614
|
-
if (isProxy) {
|
|
615
|
-
return;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(`${pathname}${search || ""}`);
|
|
619
|
-
req.url = req.url.substring(APP_PUBLIC_PATH.length + "storage".length);
|
|
620
|
-
await compress(req, res);
|
|
621
|
-
return (0, import_serve_handler.default)(req, res, {
|
|
622
|
-
public: (0, import_utils.resolveStorageRoot)(),
|
|
623
|
-
directoryListing: false,
|
|
624
|
-
headers: [
|
|
625
|
-
{
|
|
626
|
-
source: "**/*",
|
|
627
|
-
headers: Object.entries(headers).map(([key, value]) => ({ key, value }))
|
|
628
|
-
}
|
|
629
|
-
]
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
610
|
if (pathname.startsWith(APP_PUBLIC_PATH + "dist/")) {
|
|
633
611
|
if (handleApp !== "main") {
|
|
634
612
|
const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
|
|
@@ -665,7 +643,8 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
|
|
|
665
643
|
});
|
|
666
644
|
}
|
|
667
645
|
const isFilesRequest = Boolean(getFileAccessRestPath(pathname, APP_PUBLIC_PATH));
|
|
668
|
-
|
|
646
|
+
const isLegacyUploadRequest = pathname.startsWith(APP_PUBLIC_PATH + "storage/uploads/");
|
|
647
|
+
if (!pathname.startsWith(import_node_process.default.env.API_BASE_PATH) && !isFilesRequest && !isLegacyUploadRequest) {
|
|
669
648
|
if (this.isSettingsRequest(pathname)) {
|
|
670
649
|
if (handleApp !== "main") {
|
|
671
650
|
const isProxy = await this.proxyRequestToSubApp(supervisor, handleApp, req, res);
|
|
@@ -74,6 +74,7 @@ function hasActiveContentExtension(pathname = "") {
|
|
|
74
74
|
__name(hasActiveContentExtension, "hasActiveContentExtension");
|
|
75
75
|
function getStorageUploadSecurityHeaders(pathname = "") {
|
|
76
76
|
const headers = {
|
|
77
|
+
"Cache-Control": "private, no-store",
|
|
77
78
|
"Content-Security-Policy": "sandbox",
|
|
78
79
|
"X-Content-Type-Options": "nosniff"
|
|
79
80
|
};
|
package/lib/helper.js
CHANGED
|
@@ -57,10 +57,24 @@ var import_crypto = require("crypto");
|
|
|
57
57
|
var import_fs = __toESM(require("fs"));
|
|
58
58
|
var import_i18next = __toESM(require("i18next"));
|
|
59
59
|
var import_koa_bodyparser = __toESM(require("koa-bodyparser"));
|
|
60
|
+
var import_koa_send = __toESM(require("koa-send"));
|
|
60
61
|
var import_perf_hooks = require("perf_hooks");
|
|
61
62
|
var import_data_wrapping = require("./middlewares/data-wrapping");
|
|
62
63
|
var import_extract_client_ip = require("./middlewares/extract-client-ip");
|
|
64
|
+
var import_static_file_security = require("./gateway/static-file-security");
|
|
63
65
|
var import_i18n = require("./middlewares/i18n");
|
|
66
|
+
function resolveAppPublicPath(value = "/") {
|
|
67
|
+
const normalized = String(value || "/").trim() || "/";
|
|
68
|
+
const withLeadingSlash = normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
69
|
+
return withLeadingSlash.endsWith("/") ? withLeadingSlash : `${withLeadingSlash}/`;
|
|
70
|
+
}
|
|
71
|
+
__name(resolveAppPublicPath, "resolveAppPublicPath");
|
|
72
|
+
function resolveApiBasePath(value = "/api") {
|
|
73
|
+
const normalized = String(value || "/api").trim() || "/api";
|
|
74
|
+
const withLeadingSlash = normalized.startsWith("/") ? normalized : `/${normalized}`;
|
|
75
|
+
return withLeadingSlash.replace(/\/+$/g, "") || "/";
|
|
76
|
+
}
|
|
77
|
+
__name(resolveApiBasePath, "resolveApiBasePath");
|
|
64
78
|
function createI18n(options) {
|
|
65
79
|
const instance = import_i18next.default.createInstance();
|
|
66
80
|
instance.init({
|
|
@@ -138,7 +152,7 @@ function registerMiddlewares(app, options) {
|
|
|
138
152
|
}
|
|
139
153
|
app.use(/* @__PURE__ */ __name(async function getBearerToken(ctx, next) {
|
|
140
154
|
ctx.getBearerToken = () => {
|
|
141
|
-
var _a2;
|
|
155
|
+
var _a2, _b;
|
|
142
156
|
const authorization = ctx.get("Authorization");
|
|
143
157
|
if (authorization) {
|
|
144
158
|
ctx.state.pendingAuthTokenSource = "authorization";
|
|
@@ -148,7 +162,7 @@ function registerMiddlewares(app, options) {
|
|
|
148
162
|
ctx.state.pendingAuthTokenSource = "query";
|
|
149
163
|
return ctx.query.token;
|
|
150
164
|
}
|
|
151
|
-
const canUseAuthCookie = Boolean((_a2 = ctx.state) == null ? void 0 : _a2.fileAccess) && ["GET", "HEAD"].includes(ctx.method);
|
|
165
|
+
const canUseAuthCookie = Boolean(((_a2 = ctx.state) == null ? void 0 : _a2.fileAccess) || ((_b = ctx.state) == null ? void 0 : _b.legacyFileAccess)) && ["GET", "HEAD"].includes(ctx.method);
|
|
152
166
|
const cookieToken = canUseAuthCookie ? ctx.cookies.get((0, import_utils.getAuthCookieName)("authToken", app.name)) : void 0;
|
|
153
167
|
ctx.state.pendingAuthTokenSource = cookieToken ? "cookie" : void 0;
|
|
154
168
|
return cookieToken;
|
|
@@ -159,6 +173,47 @@ function registerMiddlewares(app, options) {
|
|
|
159
173
|
if (options.dataWrapping !== false) {
|
|
160
174
|
app.use((0, import_data_wrapping.dataWrapping)(), { tag: "dataWrapping", after: "cors" });
|
|
161
175
|
}
|
|
176
|
+
app.use(
|
|
177
|
+
/* @__PURE__ */ __name(async function legacyFileAccess(ctx, next) {
|
|
178
|
+
const publicPath = resolveAppPublicPath(process.env.APP_PUBLIC_PATH);
|
|
179
|
+
const uploadsPrefix = `${publicPath}storage/uploads/`;
|
|
180
|
+
const authCheckPath = `${resolveApiBasePath(process.env.API_BASE_PATH)}/auth:checkLegacyFileAccess`;
|
|
181
|
+
const isUploadRequest = ctx.path.startsWith(uploadsPrefix);
|
|
182
|
+
const isAuthCheckRequest = ctx.path === authCheckPath || ctx.path === "/auth:checkLegacyFileAccess";
|
|
183
|
+
if (!isUploadRequest && !isAuthCheckRequest) {
|
|
184
|
+
return next();
|
|
185
|
+
}
|
|
186
|
+
if (!["GET", "HEAD"].includes(ctx.method)) {
|
|
187
|
+
return ctx.throw(405);
|
|
188
|
+
}
|
|
189
|
+
ctx.state.legacyFileAccess = true;
|
|
190
|
+
ctx.state.legacyLocalStoragePublicAccess = process.env.LEGACY_LOCAL_STORAGE_PUBLIC_ACCESS === "true";
|
|
191
|
+
if (ctx.state.legacyLocalStoragePublicAccess) {
|
|
192
|
+
ctx.skipAuthCheck = true;
|
|
193
|
+
}
|
|
194
|
+
if (isAuthCheckRequest) {
|
|
195
|
+
return next();
|
|
196
|
+
}
|
|
197
|
+
const originalPath = ctx.path;
|
|
198
|
+
ctx.path = authCheckPath;
|
|
199
|
+
try {
|
|
200
|
+
await next();
|
|
201
|
+
} finally {
|
|
202
|
+
ctx.path = originalPath;
|
|
203
|
+
}
|
|
204
|
+
const relativePath = `uploads/${originalPath.slice(uploadsPrefix.length)}`;
|
|
205
|
+
const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(`${originalPath}${ctx.search || ""}`);
|
|
206
|
+
if (!headers["Content-Disposition"]) {
|
|
207
|
+
headers["Content-Disposition"] = "inline";
|
|
208
|
+
}
|
|
209
|
+
for (const [name, value] of Object.entries(headers)) {
|
|
210
|
+
ctx.set(name, value);
|
|
211
|
+
}
|
|
212
|
+
ctx.status = 200;
|
|
213
|
+
await (0, import_koa_send.default)(ctx, relativePath, { root: (0, import_utils.resolveStorageRoot)() });
|
|
214
|
+
}, "legacyFileAccess"),
|
|
215
|
+
{ tag: "legacyFileAccess", before: "dataSource", after: "dataWrapping" }
|
|
216
|
+
);
|
|
162
217
|
app.use(app.dataSourceManager.middleware(), { tag: "dataSource", after: "dataWrapping" });
|
|
163
218
|
app.use((0, import_extract_client_ip.extractClientIp)(), { tag: "extractClientIp", before: "cors" });
|
|
164
219
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/server",
|
|
3
|
-
"version": "2.4.0-alpha.
|
|
3
|
+
"version": "2.4.0-alpha.5",
|
|
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.4.0-alpha.
|
|
14
|
-
"@nocobase/actions": "2.4.0-alpha.
|
|
15
|
-
"@nocobase/ai": "2.4.0-alpha.
|
|
16
|
-
"@nocobase/auth": "2.4.0-alpha.
|
|
17
|
-
"@nocobase/cache": "2.4.0-alpha.
|
|
18
|
-
"@nocobase/data-source-manager": "2.4.0-alpha.
|
|
19
|
-
"@nocobase/database": "2.4.0-alpha.
|
|
20
|
-
"@nocobase/evaluators": "2.4.0-alpha.
|
|
21
|
-
"@nocobase/lock-manager": "2.4.0-alpha.
|
|
22
|
-
"@nocobase/logger": "2.4.0-alpha.
|
|
23
|
-
"@nocobase/resourcer": "2.4.0-alpha.
|
|
24
|
-
"@nocobase/sdk": "2.4.0-alpha.
|
|
25
|
-
"@nocobase/snowflake-id": "2.4.0-alpha.
|
|
26
|
-
"@nocobase/telemetry": "2.4.0-alpha.
|
|
27
|
-
"@nocobase/utils": "2.4.0-alpha.
|
|
13
|
+
"@nocobase/acl": "2.4.0-alpha.5",
|
|
14
|
+
"@nocobase/actions": "2.4.0-alpha.5",
|
|
15
|
+
"@nocobase/ai": "2.4.0-alpha.5",
|
|
16
|
+
"@nocobase/auth": "2.4.0-alpha.5",
|
|
17
|
+
"@nocobase/cache": "2.4.0-alpha.5",
|
|
18
|
+
"@nocobase/data-source-manager": "2.4.0-alpha.5",
|
|
19
|
+
"@nocobase/database": "2.4.0-alpha.5",
|
|
20
|
+
"@nocobase/evaluators": "2.4.0-alpha.5",
|
|
21
|
+
"@nocobase/lock-manager": "2.4.0-alpha.5",
|
|
22
|
+
"@nocobase/logger": "2.4.0-alpha.5",
|
|
23
|
+
"@nocobase/resourcer": "2.4.0-alpha.5",
|
|
24
|
+
"@nocobase/sdk": "2.4.0-alpha.5",
|
|
25
|
+
"@nocobase/snowflake-id": "2.4.0-alpha.5",
|
|
26
|
+
"@nocobase/telemetry": "2.4.0-alpha.5",
|
|
27
|
+
"@nocobase/utils": "2.4.0-alpha.5",
|
|
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": "
|
|
64
|
+
"gitHead": "ce4b0948641b13d2964c44905cb30bebe877a657"
|
|
65
65
|
}
|