mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-01 12:40:22 +00:00
116 lines
3.2 KiB
TypeScript
116 lines
3.2 KiB
TypeScript
export type AllowlistMatchSource =
|
|
| "wildcard"
|
|
| "id"
|
|
| "name"
|
|
| "tag"
|
|
| "username"
|
|
| "prefixed-id"
|
|
| "prefixed-user"
|
|
| "prefixed-name"
|
|
| "slug"
|
|
| "localpart";
|
|
|
|
export type AllowlistMatch<TSource extends string = AllowlistMatchSource> = {
|
|
allowed: boolean;
|
|
matchKey?: string;
|
|
matchSource?: TSource;
|
|
};
|
|
|
|
export type CompiledAllowlist = {
|
|
set: ReadonlySet<string>;
|
|
wildcard: boolean;
|
|
};
|
|
|
|
export function formatAllowlistMatchMeta(
|
|
match?: { matchKey?: string; matchSource?: string } | null,
|
|
): string {
|
|
return `matchKey=${match?.matchKey ?? "none"} matchSource=${match?.matchSource ?? "none"}`;
|
|
}
|
|
|
|
export function compileAllowlist(entries: ReadonlyArray<string>): CompiledAllowlist {
|
|
const set = new Set(entries.filter(Boolean));
|
|
return {
|
|
set,
|
|
wildcard: set.has("*"),
|
|
};
|
|
}
|
|
|
|
function compileSimpleAllowlist(entries: ReadonlyArray<string | number>): CompiledAllowlist {
|
|
return compileAllowlist(
|
|
entries.map((entry) => String(entry).trim().toLowerCase()).filter(Boolean),
|
|
);
|
|
}
|
|
|
|
export function resolveAllowlistCandidates<TSource extends string>(params: {
|
|
compiledAllowlist: CompiledAllowlist;
|
|
candidates: Array<{ value?: string; source: TSource }>;
|
|
}): AllowlistMatch<TSource> {
|
|
for (const candidate of params.candidates) {
|
|
if (!candidate.value) {
|
|
continue;
|
|
}
|
|
if (params.compiledAllowlist.set.has(candidate.value)) {
|
|
return {
|
|
allowed: true,
|
|
matchKey: candidate.value,
|
|
matchSource: candidate.source,
|
|
};
|
|
}
|
|
}
|
|
return { allowed: false };
|
|
}
|
|
|
|
export function resolveCompiledAllowlistMatch<TSource extends string>(params: {
|
|
compiledAllowlist: CompiledAllowlist;
|
|
candidates: Array<{ value?: string; source: TSource }>;
|
|
}): AllowlistMatch<TSource> {
|
|
if (params.compiledAllowlist.set.size === 0) {
|
|
return { allowed: false };
|
|
}
|
|
if (params.compiledAllowlist.wildcard) {
|
|
return { allowed: true, matchKey: "*", matchSource: "wildcard" as TSource };
|
|
}
|
|
return resolveAllowlistCandidates(params);
|
|
}
|
|
|
|
export function resolveAllowlistMatchByCandidates<TSource extends string>(params: {
|
|
allowList: ReadonlyArray<string>;
|
|
candidates: Array<{ value?: string; source: TSource }>;
|
|
}): AllowlistMatch<TSource> {
|
|
return resolveCompiledAllowlistMatch({
|
|
compiledAllowlist: compileAllowlist(params.allowList),
|
|
candidates: params.candidates,
|
|
});
|
|
}
|
|
|
|
export function resolveAllowlistMatchSimple(params: {
|
|
allowFrom: ReadonlyArray<string | number>;
|
|
senderId: string;
|
|
senderName?: string | null;
|
|
allowNameMatching?: boolean;
|
|
}): AllowlistMatch<"wildcard" | "id" | "name"> {
|
|
const allowFrom = compileSimpleAllowlist(params.allowFrom);
|
|
|
|
if (allowFrom.set.size === 0) {
|
|
return { allowed: false };
|
|
}
|
|
if (allowFrom.wildcard) {
|
|
return { allowed: true, matchKey: "*", matchSource: "wildcard" };
|
|
}
|
|
|
|
const senderId = params.senderId.toLowerCase();
|
|
const senderName = params.senderName?.toLowerCase();
|
|
return resolveAllowlistCandidates({
|
|
compiledAllowlist: allowFrom,
|
|
candidates: [
|
|
{ value: senderId, source: "id" },
|
|
...(params.allowNameMatching === true && senderName
|
|
? ([{ value: senderName, source: "name" as const }] satisfies Array<{
|
|
value?: string;
|
|
source: "id" | "name";
|
|
}>)
|
|
: []),
|
|
],
|
|
});
|
|
}
|