refactor(discord): share component allowlist check

This commit is contained in:
Peter Steinberger
2026-02-15 17:17:03 +00:00
parent b2c42697dd
commit ac3db098ab

View File

@@ -205,6 +205,40 @@ async function ensureGuildComponentMemberAllowed(params: {
return false;
}
async function ensureAgentComponentInteractionAllowed(params: {
ctx: AgentComponentContext;
interaction: AgentComponentInteraction;
channelId: string;
rawGuildId: string | undefined;
memberRoleIds: string[];
user: DiscordUser;
replyOpts: { ephemeral?: boolean };
componentLabel: string;
unauthorizedReply: string;
}): Promise<{ parentId: string | undefined } | null> {
const guildInfo = resolveDiscordGuildEntry({
guild: params.interaction.guild ?? undefined,
guildEntries: params.ctx.guildEntries,
});
const channelCtx = resolveDiscordChannelContext(params.interaction);
const memberAllowed = await ensureGuildComponentMemberAllowed({
interaction: params.interaction,
guildInfo,
channelId: params.channelId,
rawGuildId: params.rawGuildId,
channelCtx,
memberRoleIds: params.memberRoleIds,
user: params.user,
replyOpts: params.replyOpts,
componentLabel: params.componentLabel,
unauthorizedReply: params.unauthorizedReply,
});
if (!memberAllowed) {
return null;
}
return { parentId: channelCtx.parentId };
}
export type AgentComponentContext = {
cfg: OpenClawConfig;
accountId: string;
@@ -430,29 +464,23 @@ export class AgentComponentButton extends Button {
memberRoleIds,
} = interactionCtx;
// P2 FIX: Check user allowlist before processing component interaction
// This prevents unauthorized users from injecting system events
const guildInfo = resolveDiscordGuildEntry({
guild: interaction.guild ?? undefined,
guildEntries: this.ctx.guildEntries,
});
const channelCtx = resolveDiscordChannelContext(interaction);
const { parentId } = channelCtx;
const memberAllowed = await ensureGuildComponentMemberAllowed({
// Check user allowlist before processing component interaction
// This prevents unauthorized users from injecting system events.
const allowed = await ensureAgentComponentInteractionAllowed({
ctx: this.ctx,
interaction,
guildInfo,
channelId,
rawGuildId,
channelCtx,
memberRoleIds,
user,
replyOpts,
componentLabel: "button",
unauthorizedReply: "You are not authorized to use this button.",
});
if (!memberAllowed) {
if (!allowed) {
return;
}
const { parentId } = allowed;
// Resolve route with full context (guildId, proper peer kind, parentPeer)
const route = resolveAgentRoute({
@@ -537,28 +565,22 @@ export class AgentSelectMenu extends StringSelectMenu {
memberRoleIds,
} = interactionCtx;
// Check user allowlist before processing component interaction
const guildInfo = resolveDiscordGuildEntry({
guild: interaction.guild ?? undefined,
guildEntries: this.ctx.guildEntries,
});
const channelCtx = resolveDiscordChannelContext(interaction);
const { parentId } = channelCtx;
const memberAllowed = await ensureGuildComponentMemberAllowed({
// Check user allowlist before processing component interaction.
const allowed = await ensureAgentComponentInteractionAllowed({
ctx: this.ctx,
interaction,
guildInfo,
channelId,
rawGuildId,
channelCtx,
memberRoleIds,
user,
replyOpts,
componentLabel: "select",
unauthorizedReply: "You are not authorized to use this select menu.",
});
if (!memberAllowed) {
if (!allowed) {
return;
}
const { parentId } = allowed;
// Extract selected values
const values = interaction.values ?? [];