mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-19 05:27:26 +00:00
fix: enforce explicit group auth boundaries across channels
This commit is contained in:
@@ -5,7 +5,7 @@ import {
|
||||
formatTextWithAttachmentLinks,
|
||||
logInboundDrop,
|
||||
readStoreAllowFromForDmPolicy,
|
||||
resolveControlCommandGate,
|
||||
resolveDmGroupAccessWithCommandGate,
|
||||
resolveOutboundMediaUrls,
|
||||
resolveAllowlistProviderRuntimeGroupPolicy,
|
||||
resolveDefaultGroupPolicy,
|
||||
@@ -120,11 +120,6 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
}
|
||||
|
||||
const roomAllowFrom = normalizeNextcloudTalkAllowlist(roomConfig?.allowFrom);
|
||||
const baseGroupAllowFrom =
|
||||
configGroupAllowFrom.length > 0 ? configGroupAllowFrom : configAllowFrom;
|
||||
|
||||
const effectiveAllowFrom = [...configAllowFrom, ...storeAllowList].filter(Boolean);
|
||||
const effectiveGroupAllowFrom = [...baseGroupAllowFrom].filter(Boolean);
|
||||
|
||||
const allowTextCommands = core.channel.commands.shouldHandleTextCommands({
|
||||
cfg: config as OpenClawConfig,
|
||||
@@ -132,25 +127,33 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
});
|
||||
const useAccessGroups =
|
||||
(config.commands as Record<string, unknown> | undefined)?.useAccessGroups !== false;
|
||||
const senderAllowedForCommands = resolveNextcloudTalkAllowlistMatch({
|
||||
allowFrom: isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom,
|
||||
senderId,
|
||||
}).allowed;
|
||||
const hasControlCommand = core.channel.text.hasControlCommand(rawBody, config as OpenClawConfig);
|
||||
const commandGate = resolveControlCommandGate({
|
||||
useAccessGroups,
|
||||
authorizers: [
|
||||
{
|
||||
configured: (isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom).length > 0,
|
||||
allowed: senderAllowedForCommands,
|
||||
},
|
||||
],
|
||||
allowTextCommands,
|
||||
hasControlCommand,
|
||||
const access = resolveDmGroupAccessWithCommandGate({
|
||||
isGroup,
|
||||
dmPolicy,
|
||||
groupPolicy,
|
||||
allowFrom: configAllowFrom,
|
||||
groupAllowFrom: configGroupAllowFrom,
|
||||
storeAllowFrom: storeAllowList,
|
||||
isSenderAllowed: (allowFrom) =>
|
||||
resolveNextcloudTalkAllowlistMatch({
|
||||
allowFrom,
|
||||
senderId,
|
||||
}).allowed,
|
||||
command: {
|
||||
useAccessGroups,
|
||||
allowTextCommands,
|
||||
hasControlCommand,
|
||||
},
|
||||
});
|
||||
const commandAuthorized = commandGate.commandAuthorized;
|
||||
const commandAuthorized = access.commandAuthorized;
|
||||
const effectiveGroupAllowFrom = access.effectiveGroupAllowFrom;
|
||||
|
||||
if (isGroup) {
|
||||
if (access.decision !== "allow") {
|
||||
runtime.log?.(`nextcloud-talk: drop group sender ${senderId} (reason=${access.reason})`);
|
||||
return;
|
||||
}
|
||||
const groupAllow = resolveNextcloudTalkGroupAllow({
|
||||
groupPolicy,
|
||||
outerAllowFrom: effectiveGroupAllowFrom,
|
||||
@@ -162,48 +165,36 @@ export async function handleNextcloudTalkInbound(params: {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (dmPolicy === "disabled") {
|
||||
runtime.log?.(`nextcloud-talk: drop DM sender=${senderId} (dmPolicy=disabled)`);
|
||||
return;
|
||||
}
|
||||
if (dmPolicy !== "open") {
|
||||
const dmAllowed = resolveNextcloudTalkAllowlistMatch({
|
||||
allowFrom: effectiveAllowFrom,
|
||||
senderId,
|
||||
}).allowed;
|
||||
if (!dmAllowed) {
|
||||
if (dmPolicy === "pairing") {
|
||||
const { code, created } = await core.channel.pairing.upsertPairingRequest({
|
||||
channel: CHANNEL_ID,
|
||||
id: senderId,
|
||||
meta: { name: senderName || undefined },
|
||||
});
|
||||
if (created) {
|
||||
try {
|
||||
await sendMessageNextcloudTalk(
|
||||
roomToken,
|
||||
core.channel.pairing.buildPairingReply({
|
||||
channel: CHANNEL_ID,
|
||||
idLine: `Your Nextcloud user id: ${senderId}`,
|
||||
code,
|
||||
}),
|
||||
{ accountId: account.accountId },
|
||||
);
|
||||
statusSink?.({ lastOutboundAt: Date.now() });
|
||||
} catch (err) {
|
||||
runtime.error?.(
|
||||
`nextcloud-talk: pairing reply failed for ${senderId}: ${String(err)}`,
|
||||
);
|
||||
}
|
||||
if (access.decision !== "allow") {
|
||||
if (access.decision === "pairing") {
|
||||
const { code, created } = await core.channel.pairing.upsertPairingRequest({
|
||||
channel: CHANNEL_ID,
|
||||
id: senderId,
|
||||
meta: { name: senderName || undefined },
|
||||
});
|
||||
if (created) {
|
||||
try {
|
||||
await sendMessageNextcloudTalk(
|
||||
roomToken,
|
||||
core.channel.pairing.buildPairingReply({
|
||||
channel: CHANNEL_ID,
|
||||
idLine: `Your Nextcloud user id: ${senderId}`,
|
||||
code,
|
||||
}),
|
||||
{ accountId: account.accountId },
|
||||
);
|
||||
statusSink?.({ lastOutboundAt: Date.now() });
|
||||
} catch (err) {
|
||||
runtime.error?.(`nextcloud-talk: pairing reply failed for ${senderId}: ${String(err)}`);
|
||||
}
|
||||
}
|
||||
runtime.log?.(`nextcloud-talk: drop DM sender ${senderId} (dmPolicy=${dmPolicy})`);
|
||||
return;
|
||||
}
|
||||
runtime.log?.(`nextcloud-talk: drop DM sender ${senderId} (reason=${access.reason})`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isGroup && commandGate.shouldBlock) {
|
||||
if (access.shouldBlockControlCommand) {
|
||||
logInboundDrop({
|
||||
log: (message) => runtime.log?.(message),
|
||||
channel: CHANNEL_ID,
|
||||
|
||||
Reference in New Issue
Block a user