refactor: normalize runtime group sender gating decisions

This commit is contained in:
Peter Steinberger
2026-03-07 21:50:19 +00:00
parent 5eba663c38
commit 27dad962fe
8 changed files with 190 additions and 109 deletions

View File

@@ -1,5 +1,6 @@
import type { OpenClawConfig } from "openclaw/plugin-sdk/mattermost";
import {
evaluateSenderGroupAccessForPolicy,
isDangerousNameMatchingEnabled,
resolveAllowlistMatchSimple,
resolveControlCommandGate,
@@ -231,7 +232,20 @@ export function authorizeMattermostCommandInvocation(params: {
};
}
} else {
if (groupPolicy === "disabled") {
const senderGroupAccess = evaluateSenderGroupAccessForPolicy({
groupPolicy,
groupAllowFrom: effectiveGroupAllowFrom,
senderId,
isSenderAllowed: (_senderId, allowFrom) =>
isMattermostSenderAllowed({
senderId,
senderName,
allowFrom,
allowNameMatching,
}),
});
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "disabled") {
return {
ok: false,
denyReason: "channels-disabled",
@@ -245,33 +259,32 @@ export function authorizeMattermostCommandInvocation(params: {
};
}
if (groupPolicy === "allowlist") {
if (effectiveGroupAllowFrom.length === 0) {
return {
ok: false,
denyReason: "channel-no-allowlist",
commandAuthorized: false,
channelInfo,
kind,
chatType,
channelName,
channelDisplay,
roomLabel,
};
}
if (!groupAllowedForCommands) {
return {
ok: false,
denyReason: "unauthorized",
commandAuthorized: false,
channelInfo,
kind,
chatType,
channelName,
channelDisplay,
roomLabel,
};
}
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "empty_allowlist") {
return {
ok: false,
denyReason: "channel-no-allowlist",
commandAuthorized: false,
channelInfo,
kind,
chatType,
channelName,
channelDisplay,
roomLabel,
};
}
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "sender_not_allowlisted") {
return {
ok: false,
denyReason: "unauthorized",
commandAuthorized: false,
channelInfo,
kind,
chatType,
channelName,
channelDisplay,
roomLabel,
};
}
if (commandGate.shouldBlock) {

View File

@@ -6,6 +6,7 @@ import {
DEFAULT_GROUP_HISTORY_LIMIT,
createScopedPairingAccess,
logInboundDrop,
evaluateSenderGroupAccessForPolicy,
recordPendingHistoryEntryIfEnabled,
resolveControlCommandGate,
resolveDefaultGroupPolicy,
@@ -230,46 +231,57 @@ export function createMSTeamsMessageHandler(deps: MSTeamsMessageHandlerDeps) {
}
if (!isDirectMessage && msteamsCfg) {
if (groupPolicy === "disabled") {
if (channelGate.allowlistConfigured && !channelGate.allowed) {
log.debug?.("dropping group message (not in team/channel allowlist)", {
conversationId,
teamKey: channelGate.teamKey ?? "none",
channelKey: channelGate.channelKey ?? "none",
channelMatchKey: channelGate.channelMatchKey ?? "none",
channelMatchSource: channelGate.channelMatchSource ?? "none",
});
return;
}
const senderGroupAccess = evaluateSenderGroupAccessForPolicy({
groupPolicy,
groupAllowFrom:
effectiveGroupAllowFrom.length > 0 || !channelGate.allowlistConfigured
? effectiveGroupAllowFrom
: ["*"],
senderId,
isSenderAllowed: (_senderId, allowFrom) =>
resolveMSTeamsAllowlistMatch({
allowFrom,
senderId,
senderName,
allowNameMatching: isDangerousNameMatchingEnabled(msteamsCfg),
}).allowed,
});
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "disabled") {
log.debug?.("dropping group message (groupPolicy: disabled)", {
conversationId,
});
return;
}
if (groupPolicy === "allowlist") {
if (channelGate.allowlistConfigured && !channelGate.allowed) {
log.debug?.("dropping group message (not in team/channel allowlist)", {
conversationId,
teamKey: channelGate.teamKey ?? "none",
channelKey: channelGate.channelKey ?? "none",
channelMatchKey: channelGate.channelMatchKey ?? "none",
channelMatchSource: channelGate.channelMatchSource ?? "none",
});
return;
}
if (effectiveGroupAllowFrom.length === 0 && !channelGate.allowlistConfigured) {
log.debug?.("dropping group message (groupPolicy: allowlist, no allowlist)", {
conversationId,
});
return;
}
if (effectiveGroupAllowFrom.length > 0 && access.decision !== "allow") {
const allowMatch = resolveMSTeamsAllowlistMatch({
allowFrom: effectiveGroupAllowFrom,
senderId,
senderName,
allowNameMatching: isDangerousNameMatchingEnabled(msteamsCfg),
});
if (!allowMatch.allowed) {
log.debug?.("dropping group message (not in groupAllowFrom)", {
sender: senderId,
label: senderName,
allowlistMatch: formatAllowlistMatchMeta(allowMatch),
});
return;
}
}
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "empty_allowlist") {
log.debug?.("dropping group message (groupPolicy: allowlist, no allowlist)", {
conversationId,
});
return;
}
if (!senderGroupAccess.allowed && senderGroupAccess.reason === "sender_not_allowlisted") {
const allowMatch = resolveMSTeamsAllowlistMatch({
allowFrom: effectiveGroupAllowFrom,
senderId,
senderName,
allowNameMatching: isDangerousNameMatchingEnabled(msteamsCfg),
});
log.debug?.("dropping group message (not in groupAllowFrom)", {
sender: senderId,
label: senderName,
allowlistMatch: formatAllowlistMatchMeta(allowMatch),
});
return;
}
}