mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-25 03:45:46 -06:00
fix(nextcloud-talk): reject reactions for disabled or unconfigured accounts (#112675)
The react message-action handler dispatched straight to the sender without checking the resolved account, so a disabled Nextcloud Talk account (`enabled:false`) that still had a baseUrl/botSecret in config could keep emitting reactions. `describeMessageTool` already hides the tool for unconfigured accounts, but an explicit accountId can reach `handleAction` directly. Enforce the same enabled+configured gate at dispatch, mirroring the Signal reaction fix (#112607). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -144,6 +144,41 @@ describe("nextcloudTalkMessageActions", () => {
|
||||
describe("handleAction", () => {
|
||||
const cfg = {} as CoreConfig;
|
||||
|
||||
beforeEach(() => {
|
||||
// Dispatch now resolves the account and enforces the same enabled+configured
|
||||
// gate as describeMessageTool, so react tests need a configured account.
|
||||
hoisted.resolveNextcloudTalkAccount.mockReturnValue(configuredAccount);
|
||||
});
|
||||
|
||||
it("rejects a disabled account before reaching the sender", async () => {
|
||||
hoisted.resolveNextcloudTalkAccount.mockReturnValue(disabledAccount);
|
||||
|
||||
await expect(
|
||||
nextcloudTalkMessageActions.handleAction?.({
|
||||
channel: "nextcloud-talk",
|
||||
action: "react",
|
||||
params: { to: "room:abc123", messageId: "1", emoji: "👍" },
|
||||
cfg,
|
||||
accountId: "work",
|
||||
}),
|
||||
).rejects.toThrow(/is disabled or not configured/);
|
||||
expect(hoisted.sendReactionNextcloudTalk).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("rejects an unconfigured account before reaching the sender", async () => {
|
||||
hoisted.resolveNextcloudTalkAccount.mockReturnValue(unconfiguredAccount);
|
||||
|
||||
await expect(
|
||||
nextcloudTalkMessageActions.handleAction?.({
|
||||
channel: "nextcloud-talk",
|
||||
action: "react",
|
||||
params: { to: "room:abc123", messageId: "1", emoji: "👍" },
|
||||
cfg,
|
||||
}),
|
||||
).rejects.toThrow(/is disabled or not configured/);
|
||||
expect(hoisted.sendReactionNextcloudTalk).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("invokes sendReactionNextcloudTalk with normalized params for the react action", async () => {
|
||||
const result = await nextcloudTalkMessageActions.handleAction?.({
|
||||
channel: "nextcloud-talk",
|
||||
|
||||
@@ -49,6 +49,18 @@ export const nextcloudTalkMessageActions: ChannelMessageActionAdapter = {
|
||||
}
|
||||
|
||||
if (action === "react") {
|
||||
// describeMessageTool only offers `react` for enabled, configured accounts.
|
||||
// An explicit accountId can still target a disabled or uncredentialed
|
||||
// account, so enforce the same gate at dispatch before it reaches the
|
||||
// sender — otherwise a disabled account with leftover credentials still
|
||||
// emits reactions.
|
||||
const account = resolveNextcloudTalkAccount({ cfg: cfg as CoreConfig, accountId });
|
||||
if (!isAccountConfigured(account)) {
|
||||
throw new Error(
|
||||
`Nextcloud Talk account "${account.accountId}" is disabled or not configured.`,
|
||||
);
|
||||
}
|
||||
|
||||
const target = readStringParam(params, "to", {
|
||||
required: true,
|
||||
label: "to (room token)",
|
||||
|
||||
Reference in New Issue
Block a user