Apply only-office's bound address and secret to onlyoffice settings every tick (issue 1830)

This commit is contained in:
jochen
2026-10-22 11:30:26 +02:00
parent d3ebaf72eb
commit 2d2e831659
3 changed files with 221 additions and 1 deletions
+68
View File
@@ -43,6 +43,24 @@ function ignoreSecretSetting(cfg: Record<string, unknown>, key: string): void {
console.error(`the setting ${key} is ignored: it comes from the vault`);
}
/** What applyOnlyOffice changed and whether it checked the connection (novox/hq issue 1830). */
export interface OnlyOfficeResult {
/** The onlyoffice occ keys that were set this call — key names only, never a value. */
changed: string[];
/** Whether `onlyoffice:documentserver --check` ran, and passed; absent when nothing changed. */
checkOk?: boolean;
}
// occ's config key, and the mesh-delivered config.json key it comes from (files/config.json).
const ONLYOFFICE_KEYS: ReadonlyArray<readonly [occKey: string, configKey: string]> = [
["DocumentServerUrl", "onlyofficeUrl"],
["DocumentServerInternalUrl", "onlyofficeInternalUrl"],
["StorageUrl", "onlyofficeStorageUrl"],
["jwt_secret", "onlyofficeSecret"],
];
let saidOnlyOfficeNotGiven = false;
export class NextcloudClient {
constructor(
private readonly container: string,
@@ -86,6 +104,56 @@ export class NextcloudClient {
}
}
/**
* Applies OnlyOffice's settings from the mesh-delivered config (novox/hq issue 1830), read fresh
* from the config file on every call. Sets only the occ keys that differ from Nextcloud's current
* ones, then runs the connection check once something changed. When any of the four values is not
* given yet (document-server not bound, or its secret not given), changes nothing and says so once
* — never on every call. Never logs, returns or emits the secret's value: `changed` holds key names
* only, `jwt_secret` among them, never jwt_secret's value.
*/
applyOnlyOffice(configFile: string | undefined = process.env.MESH_NEXTCLOUD_CONFIG_FILE): OnlyOfficeResult {
const cfg = meshConfig(configFile);
const desired = ONLYOFFICE_KEYS.map(([occKey, configKey]) => [occKey, cfg[configKey] ?? ""] as const);
if (desired.some(([, value]) => !value)) {
if (!saidOnlyOfficeNotGiven) {
saidOnlyOfficeNotGiven = true;
console.error("onlyoffice: document-server is not bound yet, or its secret is not given yet — nothing applied");
}
return { changed: [] };
}
const changed: string[] = [];
for (const [occKey, value] of desired) {
if (this.currentAppConfig(occKey) !== value) {
this.occ(["config:app:set", "onlyoffice", occKey, `--value=${value}`]);
changed.push(occKey);
}
}
if (changed.length === 0) return { changed };
let checkOk = true;
try {
this.occ(["onlyoffice:documentserver", "--check"]);
} catch {
checkOk = false;
}
return { changed, checkOk };
}
/**
* config:app:get of a key onlyoffice never set can throw occ's own "produced no output" error
* (occ above) rather than answer an empty string; read either as unset, so a first run sets it
* rather than aborting the loop.
*/
private currentAppConfig(key: string): string {
try {
return this.occ(["config:app:get", "onlyoffice", key]);
} catch {
return "";
}
}
listUsers(): NextcloudUser[] {
// user:list --output=json answers an object of uid → display name.
const raw = this.occ(["user:list", "--output=json"]);