mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-22 06:32:00 +00:00
108 lines
3.2 KiB
TypeScript
108 lines
3.2 KiB
TypeScript
import {
|
|
compileAllowlist,
|
|
resolveCompiledAllowlistMatch,
|
|
type AllowlistMatch,
|
|
} from "openclaw/plugin-sdk/allow-from";
|
|
import {
|
|
normalizeHyphenSlug,
|
|
normalizeStringEntries,
|
|
normalizeStringEntriesLower,
|
|
} from "openclaw/plugin-sdk/text-runtime";
|
|
|
|
const SLACK_SLUG_CACHE_MAX = 512;
|
|
const slackSlugCache = new Map<string, string>();
|
|
|
|
export function normalizeSlackSlug(raw?: string) {
|
|
const key = raw ?? "";
|
|
const cached = slackSlugCache.get(key);
|
|
if (cached !== undefined) {
|
|
return cached;
|
|
}
|
|
const normalized = normalizeHyphenSlug(raw);
|
|
slackSlugCache.set(key, normalized);
|
|
if (slackSlugCache.size > SLACK_SLUG_CACHE_MAX) {
|
|
const oldest = slackSlugCache.keys().next();
|
|
if (!oldest.done) {
|
|
slackSlugCache.delete(oldest.value);
|
|
}
|
|
}
|
|
return normalized;
|
|
}
|
|
|
|
export function normalizeAllowList(list?: Array<string | number>) {
|
|
return normalizeStringEntries(list);
|
|
}
|
|
|
|
export function normalizeAllowListLower(list?: Array<string | number>) {
|
|
return normalizeStringEntriesLower(list);
|
|
}
|
|
|
|
export function normalizeSlackAllowOwnerEntry(entry: string): string | undefined {
|
|
const trimmed = entry.trim().toLowerCase();
|
|
if (!trimmed || trimmed === "*") {
|
|
return undefined;
|
|
}
|
|
const withoutPrefix = trimmed.replace(/^(slack:|user:)/, "");
|
|
return /^u[a-z0-9]+$/.test(withoutPrefix) ? withoutPrefix : undefined;
|
|
}
|
|
|
|
export type SlackAllowListMatch = AllowlistMatch<
|
|
"wildcard" | "id" | "prefixed-id" | "prefixed-user" | "name" | "prefixed-name" | "slug"
|
|
>;
|
|
type SlackAllowListSource = Exclude<SlackAllowListMatch["matchSource"], undefined>;
|
|
|
|
export function resolveSlackAllowListMatch(params: {
|
|
allowList: string[];
|
|
id?: string;
|
|
name?: string;
|
|
allowNameMatching?: boolean;
|
|
}): SlackAllowListMatch {
|
|
const compiledAllowList = compileAllowlist(params.allowList);
|
|
const id = params.id?.toLowerCase();
|
|
const name = params.name?.toLowerCase();
|
|
const slug = normalizeSlackSlug(name);
|
|
const candidates: Array<{ value?: string; source: SlackAllowListSource }> = [
|
|
{ value: id, source: "id" },
|
|
{ value: id ? `slack:${id}` : undefined, source: "prefixed-id" },
|
|
{ value: id ? `user:${id}` : undefined, source: "prefixed-user" },
|
|
...(params.allowNameMatching === true
|
|
? ([
|
|
{ value: name, source: "name" as const },
|
|
{ value: name ? `slack:${name}` : undefined, source: "prefixed-name" as const },
|
|
{ value: slug, source: "slug" as const },
|
|
] satisfies Array<{ value?: string; source: SlackAllowListSource }>)
|
|
: []),
|
|
];
|
|
return resolveCompiledAllowlistMatch({
|
|
compiledAllowlist: compiledAllowList,
|
|
candidates,
|
|
});
|
|
}
|
|
|
|
export function allowListMatches(params: {
|
|
allowList: string[];
|
|
id?: string;
|
|
name?: string;
|
|
allowNameMatching?: boolean;
|
|
}) {
|
|
return resolveSlackAllowListMatch(params).allowed;
|
|
}
|
|
|
|
export function resolveSlackUserAllowed(params: {
|
|
allowList?: Array<string | number>;
|
|
userId?: string;
|
|
userName?: string;
|
|
allowNameMatching?: boolean;
|
|
}) {
|
|
const allowList = normalizeAllowListLower(params.allowList);
|
|
if (allowList.length === 0) {
|
|
return true;
|
|
}
|
|
return allowListMatches({
|
|
allowList,
|
|
id: params.userId,
|
|
name: params.userName,
|
|
allowNameMatching: params.allowNameMatching,
|
|
});
|
|
}
|