home-hosted 0.7.5 → 0.7.7
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/dist/cli.js +41 -6
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/uis/stock/dist/ui.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2437,6 +2437,11 @@ function createAuthRoute(deps) {
|
|
|
2437
2437
|
statusCode: 400,
|
|
2438
2438
|
code: "EXPOSED_WITHOUT_PASSWORD"
|
|
2439
2439
|
});
|
|
2440
|
+
const proxyExposure = checkProxyExposure(deps.proxy.config, false, false, false);
|
|
2441
|
+
if (proxyExposure !== null) throw new DetailedError(proxyExposure, {
|
|
2442
|
+
statusCode: 400,
|
|
2443
|
+
code: "PROXY_EXPOSURE_BLOCKED"
|
|
2444
|
+
});
|
|
2440
2445
|
deps.auth.clearPassword();
|
|
2441
2446
|
deps.panel.settings.updateControl({ auth: { enabled: false } });
|
|
2442
2447
|
return c.json({ ok: true });
|
|
@@ -9736,6 +9741,11 @@ function createSettingsRoute(deps) {
|
|
|
9736
9741
|
statusCode: 400,
|
|
9737
9742
|
code: "EXPOSURE_BLOCKED"
|
|
9738
9743
|
});
|
|
9744
|
+
const proxyExposure = checkProxyExposure(deps.proxy.config, patch.control?.auth?.enabled ?? current.auth.enabled, deps.auth.passwordSet, deps.auth.usingDefaultPassword);
|
|
9745
|
+
if (proxyExposure !== null) throw new DetailedError(proxyExposure, {
|
|
9746
|
+
statusCode: 400,
|
|
9747
|
+
code: "PROXY_EXPOSURE_BLOCKED"
|
|
9748
|
+
});
|
|
9739
9749
|
const previous = {
|
|
9740
9750
|
trustProxy: current.auth.trustProxy,
|
|
9741
9751
|
tlsEnabled: current.tls.enabled
|
|
@@ -10300,6 +10310,26 @@ function readJson(file) {
|
|
|
10300
10310
|
return null;
|
|
10301
10311
|
}
|
|
10302
10312
|
}
|
|
10313
|
+
/**
|
|
10314
|
+
* A legacy file, with "absent" told apart from "present but unreadable".
|
|
10315
|
+
*
|
|
10316
|
+
* `readJson` collapses both into `null`, and a split that is skipped reads exactly like
|
|
10317
|
+
* one with nothing to do — so a corrupt legacy config used to be abandoned silently
|
|
10318
|
+
* while `workspaces.json` was still created, after which `hasLegacyLayout()` is false
|
|
10319
|
+
* and no later run ever looks at that file again. The definitions would sit unread
|
|
10320
|
+
* beside a panel supervising nothing.
|
|
10321
|
+
*/
|
|
10322
|
+
function readLegacy(file) {
|
|
10323
|
+
if (!fs.existsSync(file)) return {
|
|
10324
|
+
parsed: null,
|
|
10325
|
+
unreadable: false
|
|
10326
|
+
};
|
|
10327
|
+
const parsed = readJson(file);
|
|
10328
|
+
return {
|
|
10329
|
+
parsed,
|
|
10330
|
+
unreadable: parsed === null
|
|
10331
|
+
};
|
|
10332
|
+
}
|
|
10303
10333
|
function writeJson(file, value, mode) {
|
|
10304
10334
|
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
10305
10335
|
fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`, mode === void 0 ? {} : { mode });
|
|
@@ -10397,10 +10427,11 @@ function migrateLayout() {
|
|
|
10397
10427
|
const moved = [];
|
|
10398
10428
|
const warnings = [];
|
|
10399
10429
|
fs.mkdirSync(hhDir, { recursive: true });
|
|
10400
|
-
const legacyConfig =
|
|
10430
|
+
const legacyConfig = readLegacy(legacy.configPath);
|
|
10401
10431
|
let configSplit = false;
|
|
10402
|
-
if (legacyConfig
|
|
10403
|
-
|
|
10432
|
+
if (legacyConfig.unreadable) warnings.push(`${legacy.configPath} could not be read — it was NOT migrated and is still there; fix or remove it, then move the file in by hand`);
|
|
10433
|
+
if (legacyConfig.parsed !== null) {
|
|
10434
|
+
const split = splitConfig(legacyConfig.parsed);
|
|
10404
10435
|
const destinations = [
|
|
10405
10436
|
path.join(hhDir, "settings.json"),
|
|
10406
10437
|
path.join(hhDir, "default", "settings.json"),
|
|
@@ -10417,10 +10448,11 @@ function migrateLayout() {
|
|
|
10417
10448
|
configSplit = true;
|
|
10418
10449
|
}
|
|
10419
10450
|
}
|
|
10420
|
-
const legacySecrets =
|
|
10451
|
+
const legacySecrets = readLegacy(legacy.secretsPath);
|
|
10421
10452
|
let secretsSplit = false;
|
|
10422
|
-
if (legacySecrets
|
|
10423
|
-
|
|
10453
|
+
if (legacySecrets.unreadable) warnings.push(`${legacy.secretsPath} could not be read — it was NOT migrated and is still there; a panel without it starts on the default password`);
|
|
10454
|
+
if (legacySecrets.parsed !== null) {
|
|
10455
|
+
const split = splitSecrets(legacySecrets.parsed);
|
|
10424
10456
|
const destinations = [path.join(hhDir, ".control-secrets.json"), path.join(hhDir, "default", ".secrets.json")];
|
|
10425
10457
|
const taken = destinations.filter((file) => fs.existsSync(file));
|
|
10426
10458
|
if (taken.length > 0) warnings.push(`${legacy.secretsPath} could not be split — ${taken.map((file) => path.relative(hhDir, file)).join(", ")} already exist(s); left it in place`);
|
|
@@ -10600,6 +10632,8 @@ function localCall(runtime, path, method, token, timeoutMs) {
|
|
|
10600
10632
|
status: response.statusCode ?? 0,
|
|
10601
10633
|
body
|
|
10602
10634
|
}));
|
|
10635
|
+
response.once("aborted", () => resolve(null));
|
|
10636
|
+
response.once("error", () => resolve(null));
|
|
10603
10637
|
});
|
|
10604
10638
|
request.once("error", () => resolve(null));
|
|
10605
10639
|
request.once("timeout", () => {
|
|
@@ -17087,6 +17121,7 @@ state/.hh/*
|
|
|
17087
17121
|
!state/.hh/settings.json
|
|
17088
17122
|
!state/.hh/workspaces.json
|
|
17089
17123
|
state/.hh/*/*
|
|
17124
|
+
!state/.hh/*/
|
|
17090
17125
|
!state/.hh/*/settings.json
|
|
17091
17126
|
!state/.hh/*/servers.config.json
|
|
17092
17127
|
data/
|