mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 20:05:46 -06:00
improve(nextcloud-talk): avoid room credential reads on sends (#128344)
* perf(nextcloud-talk): skip room credentials on sends * fix(nextcloud-talk): use account inspection hook --------- Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
committed by
GitHub
parent
bd7fb1d597
commit
323a0efdd0
@@ -120,20 +120,6 @@ export function resolveNextcloudTalkAccount(params: {
|
||||
const accountEnabled = merged.enabled !== false;
|
||||
const enabled = baseEnabled && accountEnabled;
|
||||
const secretResolution = resolveNextcloudTalkSecret(accountId, merged);
|
||||
const apiCredentialResolution = resolveNextcloudTalkApiCredentialsResult({
|
||||
apiUser: merged.apiUser,
|
||||
apiPassword: merged.apiPassword,
|
||||
apiPasswordFile: merged.apiPasswordFile,
|
||||
configPath: `channels.nextcloud-talk.accounts.${accountId}.apiPasswordFile`,
|
||||
});
|
||||
const diagnostics = [
|
||||
secretResolution.diagnostic,
|
||||
apiCredentialResolution.status === "configured_unavailable"
|
||||
? apiCredentialResolution.diagnostic
|
||||
: undefined,
|
||||
].filter((diagnostic): diagnostic is NextcloudTalkCredentialUnavailableDiagnostic =>
|
||||
Boolean(diagnostic),
|
||||
);
|
||||
const baseUrl = merged.baseUrl?.trim()?.replace(/\/$/, "") ?? "";
|
||||
|
||||
debugAccounts("resolve", {
|
||||
@@ -151,8 +137,9 @@ export function resolveNextcloudTalkAccount(params: {
|
||||
secret: secretResolution.secret,
|
||||
secretSource: secretResolution.source,
|
||||
tokenStatus: secretResolution.status,
|
||||
apiCredentialStatus: apiCredentialResolution.status,
|
||||
...(diagnostics.length > 0 ? { credentialDiagnostics: diagnostics } : {}),
|
||||
...(secretResolution.diagnostic
|
||||
? { credentialDiagnostics: [secretResolution.diagnostic] }
|
||||
: {}),
|
||||
config: merged,
|
||||
} satisfies ResolvedNextcloudTalkAccount;
|
||||
};
|
||||
@@ -165,3 +152,27 @@ export function resolveNextcloudTalkAccount(params: {
|
||||
resolveDefaultAccountId: () => resolveDefaultNextcloudTalkAccountId(params.cfg),
|
||||
});
|
||||
}
|
||||
|
||||
export function inspectNextcloudTalkAccount(params: {
|
||||
cfg: CoreConfig;
|
||||
accountId?: string | null;
|
||||
}): ResolvedNextcloudTalkAccount {
|
||||
const account = resolveNextcloudTalkAccount(params);
|
||||
const apiCredentialResolution = resolveNextcloudTalkApiCredentialsResult({
|
||||
apiUser: account.config.apiUser,
|
||||
apiPassword: account.config.apiPassword,
|
||||
apiPasswordFile: account.config.apiPasswordFile,
|
||||
configPath: `channels.nextcloud-talk.accounts.${account.accountId}.apiPasswordFile`,
|
||||
});
|
||||
const credentialDiagnostics = [
|
||||
...(account.credentialDiagnostics ?? []),
|
||||
...(apiCredentialResolution.status === "configured_unavailable"
|
||||
? [apiCredentialResolution.diagnostic]
|
||||
: []),
|
||||
];
|
||||
return {
|
||||
...account,
|
||||
apiCredentialStatus: apiCredentialResolution.status,
|
||||
...(credentialDiagnostics.length > 0 ? { credentialDiagnostics } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import { createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
|
||||
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/string-coerce-runtime";
|
||||
import {
|
||||
inspectNextcloudTalkAccount,
|
||||
listNextcloudTalkAccountIds,
|
||||
resolveDefaultNextcloudTalkAccountId,
|
||||
resolveNextcloudTalkAccount,
|
||||
@@ -23,6 +24,7 @@ export const nextcloudTalkConfigAdapter = createScopedChannelConfigAdapter<
|
||||
sectionKey: "nextcloud-talk",
|
||||
listAccountIds: listNextcloudTalkAccountIds,
|
||||
resolveAccount: adaptScopedAccountAccessor(resolveNextcloudTalkAccount),
|
||||
inspectAccount: adaptScopedAccountAccessor(inspectNextcloudTalkAccount),
|
||||
defaultAccountId: resolveDefaultNextcloudTalkAccountId,
|
||||
clearBaseFields: ["botSecret", "botSecretFile", "baseUrl", "name"],
|
||||
resolveAllowFrom: (account) => account.config.allowFrom,
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
// Nextcloud Talk tests cover channel.status plugin behavior.
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { nextcloudTalkPlugin } from "./channel.js";
|
||||
import type { CoreConfig } from "./types.js";
|
||||
|
||||
describe("nextcloud-talk channel status", () => {
|
||||
it("classifies room tokens as groups", () => {
|
||||
@@ -32,4 +36,37 @@ describe("nextcloud-talk channel status", () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("keeps API credential inspection off runtime resolution", async () => {
|
||||
const directory = fs.mkdtempSync(path.join(os.tmpdir(), "nextcloud-talk-status-"));
|
||||
const apiPasswordFile = path.join(directory, "api-password");
|
||||
const cfg = {
|
||||
channels: {
|
||||
"nextcloud-talk": {
|
||||
baseUrl: "https://cloud.example.com",
|
||||
botSecret: "bot-secret",
|
||||
apiUser: "bot",
|
||||
apiPasswordFile,
|
||||
},
|
||||
},
|
||||
} satisfies CoreConfig;
|
||||
|
||||
try {
|
||||
const account = nextcloudTalkPlugin.config.resolveAccount(cfg, "default");
|
||||
expect(account.apiCredentialStatus).toBeUndefined();
|
||||
expect(account.credentialDiagnostics).toBeUndefined();
|
||||
|
||||
fs.writeFileSync(apiPasswordFile, "api-password\n", "utf8");
|
||||
const inspected = (await nextcloudTalkPlugin.config.inspectAccount?.(
|
||||
cfg,
|
||||
"default",
|
||||
)) as typeof account;
|
||||
expect(nextcloudTalkPlugin.config.describeAccount?.(inspected, cfg)).toMatchObject({
|
||||
configured: true,
|
||||
apiCredentialStatus: "available",
|
||||
});
|
||||
} finally {
|
||||
fs.rmSync(directory, { recursive: true, force: true });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user