mirror of https://github.com/openclaw/openclaw.git
fix(zalouser): stop inheriting dm allowlist for groups (#46663)
This commit is contained in:
parent
f4aff83c51
commit
774b40467b
|
|
@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
|
||||||
- Zalo/plugin runtime: export `resolveClientIp` from `openclaw/plugin-sdk/zalo` so installed builds no longer crash on startup when the webhook monitor loads from the packaged extension instead of the monorepo source tree. (#46549) Thanks @No898.
|
- Zalo/plugin runtime: export `resolveClientIp` from `openclaw/plugin-sdk/zalo` so installed builds no longer crash on startup when the webhook monitor loads from the packaged extension instead of the monorepo source tree. (#46549) Thanks @No898.
|
||||||
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) thanks @luzhidong.
|
- Control UI/chat sessions: show human-readable labels in the grouped session dropdown again, keep unique scoped fallbacks when metadata is missing, and disambiguate duplicate labels only when needed. (#45130) thanks @luzhidong.
|
||||||
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) thanks @scoootscooob.
|
- Configure/startup: move outbound send-deps resolution into a lightweight helper so `openclaw configure` no longer stalls after the banner while eagerly loading channel plugins. (#46301) thanks @scoootscooob.
|
||||||
|
- Zalo Personal/group gating: stop reapplying `dmPolicy.allowFrom` as a sender gate for already-allowlisted groups when `groupAllowFrom` is unset, so any member of an allowed group can trigger replies while DMs stay restricted. (#40146)
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,37 @@ describe("zalouser monitor group mention gating", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("blocks group messages when sender is not in groupAllowFrom/allowFrom", async () => {
|
it("allows allowlisted group replies without inheriting the DM allowlist", async () => {
|
||||||
|
const { dispatchReplyWithBufferedBlockDispatcher } = installRuntime({
|
||||||
|
commandAuthorized: false,
|
||||||
|
replyPayload: { text: "ok" },
|
||||||
|
});
|
||||||
|
await __testing.processMessage({
|
||||||
|
message: createGroupMessage({
|
||||||
|
content: "ping @bot",
|
||||||
|
hasAnyMention: true,
|
||||||
|
wasExplicitlyMentioned: true,
|
||||||
|
senderId: "456",
|
||||||
|
}),
|
||||||
|
account: {
|
||||||
|
...createAccount(),
|
||||||
|
config: {
|
||||||
|
...createAccount().config,
|
||||||
|
groupPolicy: "allowlist",
|
||||||
|
allowFrom: ["123"],
|
||||||
|
groups: {
|
||||||
|
"group:g-1": { allow: true, requireMention: true },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
config: createConfig(),
|
||||||
|
runtime: createRuntimeEnv(),
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(dispatchReplyWithBufferedBlockDispatcher).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("blocks group messages when sender is not in groupAllowFrom", async () => {
|
||||||
const { dispatchReplyWithBufferedBlockDispatcher } = installRuntime({
|
const { dispatchReplyWithBufferedBlockDispatcher } = installRuntime({
|
||||||
commandAuthorized: false,
|
commandAuthorized: false,
|
||||||
});
|
});
|
||||||
|
|
@ -493,6 +523,7 @@ describe("zalouser monitor group mention gating", () => {
|
||||||
...createAccount().config,
|
...createAccount().config,
|
||||||
groupPolicy: "allowlist",
|
groupPolicy: "allowlist",
|
||||||
allowFrom: ["999"],
|
allowFrom: ["999"],
|
||||||
|
groupAllowFrom: ["999"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
config: createConfig(),
|
config: createConfig(),
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ import {
|
||||||
resolveOpenProviderRuntimeGroupPolicy,
|
resolveOpenProviderRuntimeGroupPolicy,
|
||||||
resolveDefaultGroupPolicy,
|
resolveDefaultGroupPolicy,
|
||||||
resolveSenderCommandAuthorization,
|
resolveSenderCommandAuthorization,
|
||||||
|
resolveSenderScopedGroupPolicy,
|
||||||
sendMediaWithLeadingCaption,
|
sendMediaWithLeadingCaption,
|
||||||
summarizeMapping,
|
summarizeMapping,
|
||||||
warnMissingProviderGroupPolicyFallbackOnce,
|
warnMissingProviderGroupPolicyFallbackOnce,
|
||||||
|
|
@ -349,6 +350,10 @@ async function processMessage(
|
||||||
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
const dmPolicy = account.config.dmPolicy ?? "pairing";
|
||||||
const configAllowFrom = (account.config.allowFrom ?? []).map((v) => String(v));
|
const configAllowFrom = (account.config.allowFrom ?? []).map((v) => String(v));
|
||||||
const configGroupAllowFrom = (account.config.groupAllowFrom ?? []).map((v) => String(v));
|
const configGroupAllowFrom = (account.config.groupAllowFrom ?? []).map((v) => String(v));
|
||||||
|
const senderGroupPolicy = resolveSenderScopedGroupPolicy({
|
||||||
|
groupPolicy,
|
||||||
|
groupAllowFrom: configGroupAllowFrom,
|
||||||
|
});
|
||||||
const shouldComputeCommandAuth = core.channel.commands.shouldComputeCommandAuthorized(
|
const shouldComputeCommandAuth = core.channel.commands.shouldComputeCommandAuthorized(
|
||||||
commandBody,
|
commandBody,
|
||||||
config,
|
config,
|
||||||
|
|
@ -360,10 +365,11 @@ async function processMessage(
|
||||||
const accessDecision = resolveDmGroupAccessWithLists({
|
const accessDecision = resolveDmGroupAccessWithLists({
|
||||||
isGroup,
|
isGroup,
|
||||||
dmPolicy,
|
dmPolicy,
|
||||||
groupPolicy,
|
groupPolicy: senderGroupPolicy,
|
||||||
allowFrom: configAllowFrom,
|
allowFrom: configAllowFrom,
|
||||||
groupAllowFrom: configGroupAllowFrom,
|
groupAllowFrom: configGroupAllowFrom,
|
||||||
storeAllowFrom,
|
storeAllowFrom,
|
||||||
|
groupAllowFromFallbackToAllowFrom: false,
|
||||||
isSenderAllowed: (allowFrom) => isSenderAllowed(senderId, allowFrom),
|
isSenderAllowed: (allowFrom) => isSenderAllowed(senderId, allowFrom),
|
||||||
});
|
});
|
||||||
if (isGroup && accessDecision.decision !== "allow") {
|
if (isGroup && accessDecision.decision !== "allow") {
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,10 @@ export type { WizardPrompter } from "../wizard/prompts.js";
|
||||||
export { formatAllowFromLowercase } from "./allow-from.js";
|
export { formatAllowFromLowercase } from "./allow-from.js";
|
||||||
export { resolveSenderCommandAuthorization } from "./command-auth.js";
|
export { resolveSenderCommandAuthorization } from "./command-auth.js";
|
||||||
export { resolveChannelAccountConfigBasePath } from "./config-paths.js";
|
export { resolveChannelAccountConfigBasePath } from "./config-paths.js";
|
||||||
export { evaluateGroupRouteAccessForPolicy } from "./group-access.js";
|
export {
|
||||||
|
evaluateGroupRouteAccessForPolicy,
|
||||||
|
resolveSenderScopedGroupPolicy,
|
||||||
|
} from "./group-access.js";
|
||||||
export { loadOutboundMediaFromUrl } from "./outbound-media.js";
|
export { loadOutboundMediaFromUrl } from "./outbound-media.js";
|
||||||
export { createScopedPairingAccess } from "./pairing-access.js";
|
export { createScopedPairingAccess } from "./pairing-access.js";
|
||||||
export { issuePairingChallenge } from "../pairing/pairing-challenge.js";
|
export { issuePairingChallenge } from "../pairing/pairing-challenge.js";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue