mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 22:54:33 +00:00
Auto-reply: scope allowlist store writes by account (#39015)
* Auto-reply: scope allowlist store writes * Tests: cover allowlist store account scoping * Changelog: note allowlist store scoping hardening
This commit is contained in:
@@ -196,6 +196,31 @@ function extractConfigAllowlist(account: {
|
||||
};
|
||||
}
|
||||
|
||||
async function updatePairingStoreAllowlist(params: {
|
||||
action: "add" | "remove";
|
||||
channelId: ChannelId;
|
||||
accountId?: string;
|
||||
entry: string;
|
||||
}) {
|
||||
const storeEntry = {
|
||||
channel: params.channelId,
|
||||
entry: params.entry,
|
||||
accountId: params.accountId,
|
||||
};
|
||||
if (params.action === "add") {
|
||||
await addChannelAllowFromStoreEntry(storeEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
await removeChannelAllowFromStoreEntry(storeEntry);
|
||||
if (params.accountId === DEFAULT_ACCOUNT_ID) {
|
||||
await removeChannelAllowFromStoreEntry({
|
||||
channel: params.channelId,
|
||||
entry: params.entry,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function resolveAccountTarget(
|
||||
parsed: Record<string, unknown>,
|
||||
channelId: ChannelId,
|
||||
@@ -695,11 +720,12 @@ export const handleAllowlistCommand: CommandHandler = async (params, allowTextCo
|
||||
}
|
||||
|
||||
if (shouldTouchStore) {
|
||||
if (parsed.action === "add") {
|
||||
await addChannelAllowFromStoreEntry({ channel: channelId, entry: parsed.entry });
|
||||
} else if (parsed.action === "remove") {
|
||||
await removeChannelAllowFromStoreEntry({ channel: channelId, entry: parsed.entry });
|
||||
}
|
||||
await updatePairingStoreAllowlist({
|
||||
action: parsed.action,
|
||||
channelId,
|
||||
accountId,
|
||||
entry: parsed.entry,
|
||||
});
|
||||
}
|
||||
|
||||
const actionLabel = parsed.action === "add" ? "added" : "removed";
|
||||
@@ -727,11 +753,12 @@ export const handleAllowlistCommand: CommandHandler = async (params, allowTextCo
|
||||
};
|
||||
}
|
||||
|
||||
if (parsed.action === "add") {
|
||||
await addChannelAllowFromStoreEntry({ channel: channelId, entry: parsed.entry });
|
||||
} else if (parsed.action === "remove") {
|
||||
await removeChannelAllowFromStoreEntry({ channel: channelId, entry: parsed.entry });
|
||||
}
|
||||
await updatePairingStoreAllowlist({
|
||||
action: parsed.action,
|
||||
channelId,
|
||||
accountId,
|
||||
entry: parsed.entry,
|
||||
});
|
||||
|
||||
const actionLabel = parsed.action === "add" ? "added" : "removed";
|
||||
const scopeLabel = scope === "dm" ? "DM" : "group";
|
||||
|
||||
@@ -704,10 +704,74 @@ describe("handleCommands /allowlist", () => {
|
||||
expect(addChannelAllowFromStoreEntryMock).toHaveBeenCalledWith({
|
||||
channel: "telegram",
|
||||
entry: "789",
|
||||
accountId: "default",
|
||||
});
|
||||
expect(result.reply?.text).toContain("DM allowlist added");
|
||||
});
|
||||
|
||||
it("writes store entries to the selected account scope", async () => {
|
||||
readConfigFileSnapshotMock.mockResolvedValueOnce({
|
||||
valid: true,
|
||||
parsed: {
|
||||
channels: { telegram: { accounts: { work: { allowFrom: ["123"] } } } },
|
||||
},
|
||||
});
|
||||
validateConfigObjectWithPluginsMock.mockImplementation((config: unknown) => ({
|
||||
ok: true,
|
||||
config,
|
||||
}));
|
||||
addChannelAllowFromStoreEntryMock.mockResolvedValueOnce({
|
||||
changed: true,
|
||||
allowFrom: ["123", "789"],
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
commands: { text: true, config: true },
|
||||
channels: { telegram: { accounts: { work: { allowFrom: ["123"] } } } },
|
||||
} as OpenClawConfig;
|
||||
const params = buildPolicyParams("/allowlist add dm --account work 789", cfg, {
|
||||
AccountId: "work",
|
||||
});
|
||||
const result = await handleCommands(params);
|
||||
|
||||
expect(result.shouldContinue).toBe(false);
|
||||
expect(addChannelAllowFromStoreEntryMock).toHaveBeenCalledWith({
|
||||
channel: "telegram",
|
||||
entry: "789",
|
||||
accountId: "work",
|
||||
});
|
||||
});
|
||||
|
||||
it("removes default-account entries from scoped and legacy pairing stores", async () => {
|
||||
removeChannelAllowFromStoreEntryMock
|
||||
.mockResolvedValueOnce({
|
||||
changed: true,
|
||||
allowFrom: [],
|
||||
})
|
||||
.mockResolvedValueOnce({
|
||||
changed: true,
|
||||
allowFrom: [],
|
||||
});
|
||||
|
||||
const cfg = {
|
||||
commands: { text: true, config: true },
|
||||
channels: { telegram: { allowFrom: ["123"] } },
|
||||
} as OpenClawConfig;
|
||||
const params = buildPolicyParams("/allowlist remove dm --store 789", cfg);
|
||||
const result = await handleCommands(params);
|
||||
|
||||
expect(result.shouldContinue).toBe(false);
|
||||
expect(removeChannelAllowFromStoreEntryMock).toHaveBeenNthCalledWith(1, {
|
||||
channel: "telegram",
|
||||
entry: "789",
|
||||
accountId: "default",
|
||||
});
|
||||
expect(removeChannelAllowFromStoreEntryMock).toHaveBeenNthCalledWith(2, {
|
||||
channel: "telegram",
|
||||
entry: "789",
|
||||
});
|
||||
});
|
||||
|
||||
it("rejects blocked account ids and keeps Object.prototype clean", async () => {
|
||||
delete (Object.prototype as Record<string, unknown>).allowFrom;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user