feat: add dm allowlist match metadata logs
Co-authored-by: thewilloftheshadow <thewilloftheshadow@users.noreply.github.com>
This commit is contained in:
@@ -14,22 +14,48 @@ export function normalizeAllowListLower(list?: Array<string | number>) {
|
||||
return normalizeAllowList(list).map((entry) => entry.toLowerCase());
|
||||
}
|
||||
|
||||
export function allowListMatches(params: { allowList: string[]; id?: string; name?: string }) {
|
||||
export type SlackAllowListMatch = {
|
||||
allowed: boolean;
|
||||
matchKey?: string;
|
||||
matchSource?: "wildcard" | "id" | "prefixed-id" | "prefixed-user" | "name" | "prefixed-name" | "slug";
|
||||
};
|
||||
|
||||
export function resolveSlackAllowListMatch(params: {
|
||||
allowList: string[];
|
||||
id?: string;
|
||||
name?: string;
|
||||
}): SlackAllowListMatch {
|
||||
const allowList = params.allowList;
|
||||
if (allowList.length === 0) return false;
|
||||
if (allowList.includes("*")) return true;
|
||||
if (allowList.length === 0) return { allowed: false };
|
||||
if (allowList.includes("*")) {
|
||||
return { allowed: true, matchKey: "*", matchSource: "wildcard" };
|
||||
}
|
||||
const id = params.id?.toLowerCase();
|
||||
const name = params.name?.toLowerCase();
|
||||
const slug = normalizeSlackSlug(name);
|
||||
const candidates = [
|
||||
id,
|
||||
id ? `slack:${id}` : undefined,
|
||||
id ? `user:${id}` : undefined,
|
||||
name,
|
||||
name ? `slack:${name}` : undefined,
|
||||
slug,
|
||||
].filter(Boolean) as string[];
|
||||
return candidates.some((value) => allowList.includes(value));
|
||||
const candidates: Array<{ value?: string; source: SlackAllowListMatch["matchSource"] }> = [
|
||||
{ value: id, source: "id" },
|
||||
{ value: id ? `slack:${id}` : undefined, source: "prefixed-id" },
|
||||
{ value: id ? `user:${id}` : undefined, source: "prefixed-user" },
|
||||
{ value: name, source: "name" },
|
||||
{ value: name ? `slack:${name}` : undefined, source: "prefixed-name" },
|
||||
{ value: slug, source: "slug" },
|
||||
];
|
||||
for (const candidate of candidates) {
|
||||
if (!candidate.value) continue;
|
||||
if (allowList.includes(candidate.value)) {
|
||||
return {
|
||||
allowed: true,
|
||||
matchKey: candidate.value,
|
||||
matchSource: candidate.source,
|
||||
};
|
||||
}
|
||||
}
|
||||
return { allowed: false };
|
||||
}
|
||||
|
||||
export function allowListMatches(params: { allowList: string[]; id?: string; name?: string }) {
|
||||
return resolveSlackAllowListMatch(params).allowed;
|
||||
}
|
||||
|
||||
export function resolveSlackUserAllowed(params: {
|
||||
|
||||
@@ -27,7 +27,7 @@ import { reactSlackMessage } from "../../actions.js";
|
||||
import { sendMessageSlack } from "../../send.js";
|
||||
import type { SlackMessageEvent } from "../../types.js";
|
||||
|
||||
import { allowListMatches, resolveSlackUserAllowed } from "../allow-list.js";
|
||||
import { resolveSlackAllowListMatch, resolveSlackUserAllowed } from "../allow-list.js";
|
||||
import { resolveSlackEffectiveAllowFrom } from "../auth.js";
|
||||
import { resolveSlackChannelConfig } from "../channel-config.js";
|
||||
import { normalizeSlackChannelType, type SlackMonitorContext } from "../context.js";
|
||||
@@ -121,11 +121,14 @@ export async function prepareSlackMessage(params: {
|
||||
return null;
|
||||
}
|
||||
if (ctx.dmPolicy !== "open") {
|
||||
const permitted = allowListMatches({
|
||||
const allowMatch = resolveSlackAllowListMatch({
|
||||
allowList: allowFromLower,
|
||||
id: directUserId,
|
||||
});
|
||||
if (!permitted) {
|
||||
const allowMatchMeta = `matchKey=${allowMatch.matchKey ?? "none"} matchSource=${
|
||||
allowMatch.matchSource ?? "none"
|
||||
}`;
|
||||
if (!allowMatch.allowed) {
|
||||
if (ctx.dmPolicy === "pairing") {
|
||||
const sender = await ctx.resolveUserName(directUserId);
|
||||
const senderName = sender?.name ?? undefined;
|
||||
@@ -136,7 +139,9 @@ export async function prepareSlackMessage(params: {
|
||||
});
|
||||
if (created) {
|
||||
logVerbose(
|
||||
`slack pairing request sender=${directUserId} name=${senderName ?? "unknown"}`,
|
||||
`slack pairing request sender=${directUserId} name=${
|
||||
senderName ?? "unknown"
|
||||
} (${allowMatchMeta})`,
|
||||
);
|
||||
try {
|
||||
await sendMessageSlack(
|
||||
@@ -158,7 +163,7 @@ export async function prepareSlackMessage(params: {
|
||||
}
|
||||
} else {
|
||||
logVerbose(
|
||||
`Blocked unauthorized slack sender ${message.user} (dmPolicy=${ctx.dmPolicy})`,
|
||||
`Blocked unauthorized slack sender ${message.user} (dmPolicy=${ctx.dmPolicy}, ${allowMatchMeta})`,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
@@ -225,11 +230,11 @@ export async function prepareSlackMessage(params: {
|
||||
surface: "slack",
|
||||
});
|
||||
|
||||
const ownerAuthorized = allowListMatches({
|
||||
const ownerAuthorized = resolveSlackAllowListMatch({
|
||||
allowList: allowFromLower,
|
||||
id: senderId,
|
||||
name: senderName,
|
||||
});
|
||||
}).allowed;
|
||||
const channelUsersAllowlistConfigured =
|
||||
isRoom && Array.isArray(channelConfig?.users) && channelConfig.users.length > 0;
|
||||
const channelCommandAuthorized =
|
||||
|
||||
Reference in New Issue
Block a user