openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
158 lines (157 loc) • 6.87 kB
JavaScript
import { c as normalizeOptionalLowercaseString, l as normalizeOptionalString, o as normalizeLowercaseStringOrEmpty } from "./string-coerce-1VuiLaaR.mjs";
import { d as normalizeStringEntries, y as uniqueStrings } from "./string-normalization-D6DKCpwE.mjs";
import { t as dedupeByKey } from "./dedupe-by-key-DnqEVrst.mjs";
import { t as summarizeStringEntries } from "./string-sample-BIw5642L.mjs";
import "./chat-target-prefixes-CkuKSHyK.mjs";
//#region src/channels/allowlists/resolve-utils.ts
function dedupeAllowlistEntries(entries, entryKey = normalizeLowercaseStringOrEmpty) {
return dedupeByKey(entries.map((entry) => entry.trim()).filter(Boolean), entryKey);
}
function mergeAllowlist(params) {
return dedupeAllowlistEntries([...(params.existing ?? []).map(String), ...params.additions]);
}
function buildAllowlistResolutionSummary(resolvedUsers, opts) {
const resolvedMap = new Map(resolvedUsers.map((entry) => [entry.input, entry]));
const resolvedOk = (entry) => Boolean(entry.resolved && entry.id);
const formatResolved = opts?.formatResolved ?? ((entry) => entry.id === entry.input ? null : `${entry.input}→${entry.id}`);
const formatUnresolved = opts?.formatUnresolved ?? ((entry) => entry.input);
const mapping = resolvedUsers.filter(resolvedOk).map(formatResolved).filter((label) => label !== null);
const additions = resolvedUsers.filter(resolvedOk).map((entry) => entry.id).filter((entry) => Boolean(entry));
return {
resolvedMap,
mapping,
unresolved: resolvedUsers.filter((entry) => !resolvedOk(entry)).map(formatUnresolved),
additions
};
}
function resolveAllowlistIdAdditions(params) {
const additions = [];
for (const entry of params.existing) {
const trimmed = normalizeOptionalString(entry) ?? "";
const resolved = params.resolvedMap.get(trimmed);
if (resolved?.resolved && resolved.id) additions.push(resolved.id);
}
return additions;
}
/** Replaces resolvable user entries with canonical ids while preserving unresolved entries and `*`. */
function canonicalizeAllowlistWithResolvedIds(params) {
const canonicalized = [];
for (const entry of params.existing ?? []) {
const trimmed = normalizeOptionalString(entry) ?? "";
if (!trimmed) continue;
if (trimmed === "*") {
canonicalized.push(trimmed);
continue;
}
const resolved = params.resolvedMap.get(trimmed);
canonicalized.push(resolved?.resolved && resolved.id ? resolved.id : trimmed);
}
return dedupeAllowlistEntries(canonicalized, params.entryKey);
}
function patchAllowlistUsersInConfigEntries(params) {
const nextEntries = { ...params.entries };
for (const [entryKey, entryConfig] of Object.entries(params.entries)) {
if (!entryConfig || typeof entryConfig !== "object") continue;
const users = entryConfig.users;
if (!Array.isArray(users) || users.length === 0) continue;
const resolvedUsers = params.strategy === "canonicalize" ? canonicalizeAllowlistWithResolvedIds({
existing: users,
resolvedMap: params.resolvedMap,
entryKey: params.entryKey
}) : mergeAllowlist({
existing: users,
additions: resolveAllowlistIdAdditions({
existing: users,
resolvedMap: params.resolvedMap
})
});
nextEntries[entryKey] = {
...entryConfig,
users: resolvedUsers
};
}
return nextEntries;
}
/** Collects concrete user lookup targets from one config entry, excluding wildcard policy entries. */
function addAllowlistUserEntriesFromConfigEntry(target, entry) {
if (!entry || typeof entry !== "object") return;
const users = entry.users;
if (!Array.isArray(users)) return;
for (const value of users) {
const trimmed = normalizeOptionalString(value) ?? "";
if (trimmed && trimmed !== "*") target.add(trimmed);
}
}
function summarizeMapping(label, mapping, unresolved, runtime) {
if (mapping.length > 0) runtime.log?.(`${label} resolved: ${summarizeStringEntries({
entries: mapping,
limit: 6
})}`);
if (unresolved.length > 0) runtime.log?.(`${label} unresolved: ${summarizeStringEntries({
entries: unresolved,
limit: 6
})}`);
}
//#endregion
//#region src/plugin-sdk/allow-from.ts
/** Lowercase and optionally strip prefixes from allowlist entries before sender comparisons. */
function formatAllowFromLowercase(params) {
return normalizeStringEntries(params.allowFrom).map((entry) => params.stripPrefixRe ? entry.replace(params.stripPrefixRe, "") : entry).map((entry) => normalizeOptionalLowercaseString(entry)).filter((entry) => Boolean(entry));
}
/** Normalize allowlist entries through a channel-provided parser or canonicalizer. */
function formatNormalizedAllowFromEntries(params) {
return normalizeStringEntries(params.allowFrom).map((entry) => params.normalizeEntry(entry)).filter((entry) => Boolean(entry));
}
/** Parse, validate, and deduplicate setup allow-from entries with wildcard support. */
function parseAllowFromEntries(raw, parseEntry) {
const entries = [];
for (const entry of normalizeStringEntries(raw.split(/[\n,;]+/g))) {
if (entry === "*") {
entries.push(entry);
continue;
}
const parsed = parseEntry(entry);
if ("error" in parsed) return {
entries: [],
error: parsed.error
};
entries.push(parsed.value);
}
return { entries: uniqueStrings(normalizeStringEntries(entries)) };
}
/** Resolve basic setup allow-from entries when a channel token is available. */
async function resolveBasicAllowFromEntries(params) {
const token = params.token?.trim();
if (!token) return params.entries.map((input) => ({
input,
resolved: false,
id: null
}));
return (await params.resolveEntries({
token,
entries: params.entries
})).map((entry) => ({
input: entry.input,
resolved: entry.resolved,
id: entry.id ?? null
}));
}
/** Check whether a sender id matches a simple normalized allowlist with wildcard support. */
function isNormalizedSenderAllowed(params) {
const normalizedAllow = formatAllowFromLowercase({
allowFrom: params.allowFrom,
stripPrefixRe: params.stripPrefixRe
});
if (normalizedAllow.length === 0) return false;
if (normalizedAllow.includes("*")) return true;
const sender = normalizeOptionalLowercaseString(String(params.senderId));
return sender ? normalizedAllow.includes(sender) : false;
}
/** Map allowlist inputs sequentially so resolver side effects stay ordered and predictable. */
async function mapAllowlistResolutionInputs(params) {
const results = [];
for (const input of params.inputs) results.push(await params.mapInput(input));
return results;
}
//#endregion
export { parseAllowFromEntries as a, buildAllowlistResolutionSummary as c, patchAllowlistUsersInConfigEntries as d, summarizeMapping as f, mapAllowlistResolutionInputs as i, canonicalizeAllowlistWithResolvedIds as l, formatNormalizedAllowFromEntries as n, resolveBasicAllowFromEntries as o, isNormalizedSenderAllowed as r, addAllowlistUserEntriesFromConfigEntry as s, formatAllowFromLowercase as t, mergeAllowlist as u };