mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 14:40:43 +00:00
fix(matrix): hot-reload dm.allowFrom and groupAllowFrom on each inbound message (#68546)
Merged via squash.
Prepared head SHA: ab369851c8
Co-authored-by: johnlanni <6763318+johnlanni@users.noreply.github.com>
Co-authored-by: gumadeiras <5599352+gumadeiras@users.noreply.github.com>
Reviewed-by: @gumadeiras
This commit is contained in:
@@ -21,6 +21,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Cron/gateway: reject ambiguous announce delivery config at add/update time so invalid multi-channel or target-id provider settings fail early instead of persisting broken cron jobs. (#69015) Thanks @obviyus.
|
||||
- Cron/main-session delivery: preserve `heartbeat.target="last"` through deferred wake queuing, gateway wake forwarding, and same-target wake coalescing so queued cron replies still return to the last active chat. (#69021) Thanks @obviyus.
|
||||
- Cron/gateway: ignore disabled channels when announce delivery ambiguity is checked, and validate main-session delivery patches against the live cron service default agent so hot-reloaded agent config does not falsely reject valid updates. (#69040) Thanks @obviyus.
|
||||
- Matrix/allowlists: hot-reload `dm.allowFrom` and `groupAllowFrom` entries on inbound messages while keeping config removals authoritative, so Matrix allowlist changes no longer require a channel restart to add or revoke a sender. (#68546) Thanks @johnlanni.
|
||||
|
||||
## 2026.4.19-beta.2
|
||||
|
||||
|
||||
@@ -148,3 +148,28 @@ export function resolveMatrixAccountConfig(params: {
|
||||
...(rooms ? { rooms } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function resolveMatrixAccountAllowlistConfig(params: {
|
||||
cfg: CoreConfig;
|
||||
accountId?: string | null;
|
||||
}): {
|
||||
dmAllowFrom?: NonNullable<MatrixConfig["dm"]>["allowFrom"];
|
||||
groupAllowFrom?: MatrixConfig["groupAllowFrom"];
|
||||
} {
|
||||
const accountId = normalizeAccountId(params.accountId);
|
||||
const base = resolveMatrixBaseConfig(params.cfg);
|
||||
const accountConfig = findMatrixAccountConfig(params.cfg, accountId);
|
||||
const accountDm = accountConfig?.dm;
|
||||
|
||||
let dmAllowFrom = base.dm?.allowFrom;
|
||||
if (accountDm && Object.hasOwn(accountDm, "allowFrom")) {
|
||||
dmAllowFrom = accountDm.allowFrom;
|
||||
}
|
||||
|
||||
let groupAllowFrom = base.groupAllowFrom;
|
||||
if (accountConfig && Object.hasOwn(accountConfig, "groupAllowFrom")) {
|
||||
groupAllowFrom = accountConfig.groupAllowFrom;
|
||||
}
|
||||
|
||||
return { dmAllowFrom, groupAllowFrom };
|
||||
}
|
||||
|
||||
@@ -14,6 +14,16 @@ import {
|
||||
type MatrixRoomsConfig = Record<string, MatrixRoomConfig>;
|
||||
type ResolveMatrixTargetsFn = typeof resolveMatrixTargets;
|
||||
|
||||
export type MatrixResolvedAllowlistEntry = {
|
||||
input: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
type MatrixResolvedUserAllowlist = {
|
||||
entries: string[];
|
||||
resolvedEntries: MatrixResolvedAllowlistEntry[];
|
||||
};
|
||||
|
||||
function normalizeMatrixUserLookupEntry(raw: string): string {
|
||||
return raw
|
||||
.replace(/^matrix:/i, "")
|
||||
@@ -41,6 +51,30 @@ function filterResolvedMatrixAllowlistEntries(entries: string[]): string[] {
|
||||
});
|
||||
}
|
||||
|
||||
function listResolvedMatrixAllowlistEntries(params: {
|
||||
entries: Array<string | number>;
|
||||
resolvedMap: Map<string, { resolved: boolean; id?: string }>;
|
||||
}): MatrixResolvedAllowlistEntry[] {
|
||||
const resolvedEntries: MatrixResolvedAllowlistEntry[] = [];
|
||||
const seen = new Set<string>();
|
||||
for (const entry of params.entries) {
|
||||
const input = String(entry).trim();
|
||||
if (!input || seen.has(input)) {
|
||||
continue;
|
||||
}
|
||||
seen.add(input);
|
||||
const resolved = params.resolvedMap.get(input);
|
||||
if (!resolved?.resolved || !resolved.id) {
|
||||
continue;
|
||||
}
|
||||
const id = normalizeMatrixUserId(resolved.id);
|
||||
if (isMatrixQualifiedUserId(id)) {
|
||||
resolvedEntries.push({ input, id });
|
||||
}
|
||||
}
|
||||
return resolvedEntries;
|
||||
}
|
||||
|
||||
function sanitizeMatrixRoomUserAllowlists(entries: MatrixRoomsConfig): MatrixRoomsConfig {
|
||||
const nextEntries: MatrixRoomsConfig = { ...entries };
|
||||
for (const [roomKey, roomConfig] of Object.entries(entries)) {
|
||||
@@ -119,10 +153,10 @@ async function resolveMatrixMonitorUserAllowlist(params: {
|
||||
list?: Array<string | number>;
|
||||
runtime: RuntimeEnv;
|
||||
resolveTargets: ResolveMatrixTargetsFn;
|
||||
}): Promise<string[]> {
|
||||
}): Promise<MatrixResolvedUserAllowlist> {
|
||||
const allowList = (params.list ?? []).map(String);
|
||||
if (allowList.length === 0) {
|
||||
return allowList;
|
||||
return { entries: allowList, resolvedEntries: [] };
|
||||
}
|
||||
|
||||
const resolution = await resolveMatrixMonitorUserEntries({
|
||||
@@ -144,7 +178,13 @@ async function resolveMatrixMonitorUserAllowlist(params: {
|
||||
);
|
||||
}
|
||||
|
||||
return filterResolvedMatrixAllowlistEntries(canonicalized);
|
||||
return {
|
||||
entries: filterResolvedMatrixAllowlistEntries(canonicalized),
|
||||
resolvedEntries: listResolvedMatrixAllowlistEntries({
|
||||
entries: allowList,
|
||||
resolvedMap: resolution.resolvedMap,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
async function resolveMatrixMonitorRoomsConfig(params: {
|
||||
@@ -264,7 +304,9 @@ export async function resolveMatrixMonitorConfig(params: {
|
||||
resolveTargets?: ResolveMatrixTargetsFn;
|
||||
}): Promise<{
|
||||
allowFrom: string[];
|
||||
allowFromResolvedEntries: MatrixResolvedAllowlistEntry[];
|
||||
groupAllowFrom: string[];
|
||||
groupAllowFromResolvedEntries: MatrixResolvedAllowlistEntry[];
|
||||
roomsConfig?: MatrixRoomsConfig;
|
||||
}> {
|
||||
const resolveTargets = params.resolveTargets ?? resolveMatrixTargets;
|
||||
@@ -296,8 +338,10 @@ export async function resolveMatrixMonitorConfig(params: {
|
||||
]);
|
||||
|
||||
return {
|
||||
allowFrom,
|
||||
groupAllowFrom,
|
||||
allowFrom: allowFrom.entries,
|
||||
allowFromResolvedEntries: allowFrom.resolvedEntries,
|
||||
groupAllowFrom: groupAllowFrom.entries,
|
||||
groupAllowFromResolvedEntries: groupAllowFrom.resolvedEntries,
|
||||
roomsConfig,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,9 @@ type MatrixHandlerTestHarnessOptions = {
|
||||
logger?: RuntimeLogger;
|
||||
logVerboseMessage?: (message: string) => void;
|
||||
allowFrom?: string[];
|
||||
allowFromResolvedEntries?: MatrixMonitorHandlerParams["allowFromResolvedEntries"];
|
||||
groupAllowFrom?: string[];
|
||||
groupAllowFromResolvedEntries?: MatrixMonitorHandlerParams["groupAllowFromResolvedEntries"];
|
||||
roomsConfig?: Record<string, MatrixRoomConfig>;
|
||||
accountAllowBots?: boolean | "mentions";
|
||||
configuredBotUserIds?: Set<string>;
|
||||
@@ -115,6 +117,7 @@ export function createMatrixHandlerTestHarness(
|
||||
counts: { final: 0, block: 0, tool: 0 },
|
||||
}));
|
||||
const enqueueSystemEvent = options.enqueueSystemEvent ?? vi.fn();
|
||||
const cfgForHandler = options.cfg ?? {};
|
||||
|
||||
const handler = createMatrixRoomMessageHandler({
|
||||
client: {
|
||||
@@ -123,6 +126,9 @@ export function createMatrixHandlerTestHarness(
|
||||
...options.client,
|
||||
} as never,
|
||||
core: {
|
||||
config: {
|
||||
loadConfig: () => cfgForHandler,
|
||||
},
|
||||
channel: {
|
||||
pairing: {
|
||||
readAllowFromStore,
|
||||
@@ -193,7 +199,7 @@ export function createMatrixHandlerTestHarness(
|
||||
enqueueSystemEvent,
|
||||
},
|
||||
} as never,
|
||||
cfg: (options.cfg ?? {}) as never,
|
||||
cfg: cfgForHandler as never,
|
||||
accountId: options.accountId ?? "ops",
|
||||
runtime:
|
||||
options.runtime ??
|
||||
@@ -209,7 +215,9 @@ export function createMatrixHandlerTestHarness(
|
||||
} as RuntimeLogger),
|
||||
logVerboseMessage: options.logVerboseMessage ?? (() => {}),
|
||||
allowFrom: options.allowFrom ?? [],
|
||||
allowFromResolvedEntries: options.allowFromResolvedEntries,
|
||||
groupAllowFrom: options.groupAllowFrom ?? [],
|
||||
groupAllowFromResolvedEntries: options.groupAllowFromResolvedEntries,
|
||||
roomsConfig: options.roomsConfig,
|
||||
accountAllowBots: options.accountAllowBots,
|
||||
configuredBotUserIds: options.configuredBotUserIds,
|
||||
|
||||
@@ -1741,6 +1741,261 @@ describe("matrix monitor handler pairing account scope", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("matrix monitor handler live allowlist reload", () => {
|
||||
type MatrixHandler = ReturnType<typeof createMatrixHandlerTestHarness>["handler"];
|
||||
|
||||
const createDispatchReplyFromConfig = () =>
|
||||
vi.fn(async () => ({
|
||||
queuedFinal: false,
|
||||
counts: { final: 0, block: 0, tool: 0 },
|
||||
}));
|
||||
|
||||
const sendLiveAllowlistMessage = async (
|
||||
handler: MatrixHandler,
|
||||
params: {
|
||||
eventId: string;
|
||||
sender: string;
|
||||
body: string;
|
||||
roomId?: string;
|
||||
mentions?: MatrixRawEvent["content"]["m.mentions"];
|
||||
},
|
||||
) => {
|
||||
await handler(
|
||||
params.roomId ?? "!dm:example.org",
|
||||
createMatrixTextMessageEvent({
|
||||
eventId: params.eventId,
|
||||
sender: params.sender,
|
||||
body: params.body,
|
||||
...(params.mentions ? { mentions: params.mentions } : {}),
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
it("accepts a DM sender added to live dm.allowFrom", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: { allowFrom: [] as string[] },
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
dmPolicy: "allowlist",
|
||||
isDirectMessage: true,
|
||||
allowFrom: [],
|
||||
allowFromResolvedEntries: [],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-add-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello",
|
||||
});
|
||||
expect(dispatchReplyFromConfig).not.toHaveBeenCalled();
|
||||
|
||||
cfg.channels.matrix.dm.allowFrom = ["@alice:example.org"];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-add-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello again",
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("blocks a DM sender removed from live dm.allowFrom", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: { allowFrom: ["@alice:example.org"] },
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
dmPolicy: "allowlist",
|
||||
isDirectMessage: true,
|
||||
allowFrom: ["@alice:example.org"],
|
||||
allowFromResolvedEntries: [{ input: "@alice:example.org", id: "@alice:example.org" }],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-remove-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello",
|
||||
});
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
cfg.channels.matrix.dm.allowFrom = [];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-remove-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello again",
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("blocks a DM sender after live wildcard removal", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: { allowFrom: ["*"] },
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
dmPolicy: "allowlist",
|
||||
isDirectMessage: true,
|
||||
allowFrom: ["*"],
|
||||
allowFromResolvedEntries: [],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-wildcard-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello",
|
||||
});
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
cfg.channels.matrix.dm.allowFrom = [];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-wildcard-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello again",
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("uses account-scoped live dm.allowFrom overrides", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: { allowFrom: ["@base:example.org"] },
|
||||
accounts: {
|
||||
ops: {
|
||||
dm: { allowFrom: ["@alice:example.org"] },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
accountId: "ops",
|
||||
dmPolicy: "allowlist",
|
||||
isDirectMessage: true,
|
||||
allowFrom: ["@alice:example.org"],
|
||||
allowFromResolvedEntries: [{ input: "@alice:example.org", id: "@alice:example.org" }],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-account-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello",
|
||||
});
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
cfg.channels.matrix.accounts.ops.dm.allowFrom = [];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-account-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello again",
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("keeps startup-resolved display names only while the raw input remains configured", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
dm: { allowFrom: ["Alice"] },
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
dmPolicy: "allowlist",
|
||||
isDirectMessage: true,
|
||||
allowFrom: ["@alice:example.org"],
|
||||
allowFromResolvedEntries: [{ input: "Alice", id: "@alice:example.org" }],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-name-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello",
|
||||
});
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
cfg.channels.matrix.dm.allowFrom = [];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
eventId: "$dm-name-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "hello again",
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("blocks a room sender removed from live groupAllowFrom while the group list remains configured", async () => {
|
||||
const dispatchReplyFromConfig = createDispatchReplyFromConfig();
|
||||
const cfg = {
|
||||
channels: {
|
||||
matrix: {
|
||||
groupAllowFrom: ["@alice:example.org", "@bob:example.org"],
|
||||
},
|
||||
},
|
||||
};
|
||||
const { handler } = createMatrixHandlerTestHarness({
|
||||
cfg,
|
||||
isDirectMessage: false,
|
||||
groupPolicy: "allowlist",
|
||||
roomsConfig: { "*": {} },
|
||||
groupAllowFrom: ["@alice:example.org", "@bob:example.org"],
|
||||
groupAllowFromResolvedEntries: [
|
||||
{ input: "@alice:example.org", id: "@alice:example.org" },
|
||||
{ input: "@bob:example.org", id: "@bob:example.org" },
|
||||
],
|
||||
dispatchReplyFromConfig,
|
||||
});
|
||||
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
roomId: "!room:example.org",
|
||||
eventId: "$group-remove-before",
|
||||
sender: "@alice:example.org",
|
||||
body: "@room hello",
|
||||
mentions: { room: true },
|
||||
});
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
|
||||
cfg.channels.matrix.groupAllowFrom = ["@bob:example.org"];
|
||||
await sendLiveAllowlistMessage(handler, {
|
||||
roomId: "!room:example.org",
|
||||
eventId: "$group-remove-after",
|
||||
sender: "@alice:example.org",
|
||||
body: "@room hello again",
|
||||
mentions: { room: true },
|
||||
});
|
||||
|
||||
expect(dispatchReplyFromConfig).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
||||
describe("matrix monitor handler durable inbound dedupe", () => {
|
||||
it("skips replayed inbound events before session recording", async () => {
|
||||
const inboundDeduper = {
|
||||
|
||||
@@ -14,6 +14,7 @@ import type {
|
||||
MatrixStreamingMode,
|
||||
ReplyToMode,
|
||||
} from "../../types.js";
|
||||
import { resolveMatrixAccountAllowlistConfig } from "../account-config.js";
|
||||
import { formatMatrixErrorMessage } from "../errors.js";
|
||||
import { isMatrixMediaSizeLimitError } from "../media-errors.js";
|
||||
import {
|
||||
@@ -33,9 +34,11 @@ import {
|
||||
import type { LocationMessageEventContent, MatrixClient } from "../sdk.js";
|
||||
import { MATRIX_OPENCLAW_FINALIZED_PREVIEW_KEY } from "../send/types.js";
|
||||
import { resolveMatrixStoredSessionMeta } from "../session-store-metadata.js";
|
||||
import { isMatrixQualifiedUserId } from "../target-ids.js";
|
||||
import { resolveMatrixMonitorAccessState } from "./access-state.js";
|
||||
import { resolveMatrixAckReactionConfig } from "./ack-config.js";
|
||||
import { resolveMatrixAllowListMatch } from "./allowlist.js";
|
||||
import { normalizeMatrixUserId, resolveMatrixAllowListMatch } from "./allowlist.js";
|
||||
import type { MatrixResolvedAllowlistEntry } from "./config.js";
|
||||
import type { MatrixInboundEventDeduper } from "./inbound-dedupe.js";
|
||||
import { resolveMatrixLocation, type MatrixLocationPayload } from "./location.js";
|
||||
import { downloadMatrixMedia } from "./media.js";
|
||||
@@ -151,7 +154,9 @@ export type MatrixMonitorHandlerParams = {
|
||||
logger: RuntimeLogger;
|
||||
logVerboseMessage: (message: string) => void;
|
||||
allowFrom: string[];
|
||||
allowFromResolvedEntries?: readonly MatrixResolvedAllowlistEntry[];
|
||||
groupAllowFrom?: string[];
|
||||
groupAllowFromResolvedEntries?: readonly MatrixResolvedAllowlistEntry[];
|
||||
roomsConfig?: Record<string, MatrixRoomConfig>;
|
||||
accountAllowBots?: boolean | "mentions";
|
||||
configuredBotUserIds?: ReadonlySet<string>;
|
||||
@@ -188,6 +193,61 @@ export type MatrixMonitorHandlerParams = {
|
||||
needsRoomAliasesForConfig: boolean;
|
||||
};
|
||||
|
||||
function normalizeConfiguredMatrixAllowlistEntries(
|
||||
entries?: ReadonlyArray<string | number>,
|
||||
): string[] {
|
||||
const normalized: string[] = [];
|
||||
for (const entry of entries ?? []) {
|
||||
const trimmed = String(entry).trim();
|
||||
if (trimmed) {
|
||||
normalized.push(trimmed);
|
||||
}
|
||||
}
|
||||
return normalized;
|
||||
}
|
||||
|
||||
function isMatrixHotReloadAllowlistEntry(entry: string): boolean {
|
||||
if (entry === "*") {
|
||||
return true;
|
||||
}
|
||||
return isMatrixQualifiedUserId(normalizeMatrixUserId(entry));
|
||||
}
|
||||
|
||||
function resolveEffectiveMatrixLiveAllowlist(params: {
|
||||
liveEntries?: ReadonlyArray<string | number>;
|
||||
startupResolvedEntries?: readonly MatrixResolvedAllowlistEntry[];
|
||||
}): string[] {
|
||||
const liveEntries = normalizeConfiguredMatrixAllowlistEntries(params.liveEntries);
|
||||
const liveInputs = new Set(liveEntries);
|
||||
const effective: string[] = [];
|
||||
const seen = new Set<string>();
|
||||
const add = (entry: string) => {
|
||||
const trimmed = entry.trim();
|
||||
if (!trimmed) {
|
||||
return;
|
||||
}
|
||||
const key = trimmed.toLowerCase();
|
||||
if (seen.has(key)) {
|
||||
return;
|
||||
}
|
||||
seen.add(key);
|
||||
effective.push(trimmed);
|
||||
};
|
||||
|
||||
for (const entry of liveEntries) {
|
||||
if (isMatrixHotReloadAllowlistEntry(entry)) {
|
||||
add(entry);
|
||||
}
|
||||
}
|
||||
for (const entry of params.startupResolvedEntries ?? []) {
|
||||
if (liveInputs.has(entry.input)) {
|
||||
add(entry.id);
|
||||
}
|
||||
}
|
||||
|
||||
return effective;
|
||||
}
|
||||
|
||||
function resolveMatrixMentionPrecheckText(params: {
|
||||
eventType: string;
|
||||
content: RoomMessageEventContent;
|
||||
@@ -354,8 +414,8 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
runtime,
|
||||
logger,
|
||||
logVerboseMessage,
|
||||
allowFrom,
|
||||
groupAllowFrom = [],
|
||||
allowFromResolvedEntries = [],
|
||||
groupAllowFromResolvedEntries = [],
|
||||
roomsConfig,
|
||||
accountAllowBots,
|
||||
configuredBotUserIds = new Set<string>(),
|
||||
@@ -638,10 +698,22 @@ export function createMatrixRoomMessageHandler(params: MatrixMonitorHandlerParam
|
||||
};
|
||||
const storeAllowFrom = isDirectMessage ? await readStoreAllowFrom() : [];
|
||||
const roomUsers = roomConfig?.users ?? [];
|
||||
const liveAccountAllowlists = resolveMatrixAccountAllowlistConfig({
|
||||
cfg: core.config.loadConfig() as CoreConfig,
|
||||
accountId,
|
||||
});
|
||||
const liveDmAllowFrom = resolveEffectiveMatrixLiveAllowlist({
|
||||
liveEntries: liveAccountAllowlists.dmAllowFrom,
|
||||
startupResolvedEntries: allowFromResolvedEntries,
|
||||
});
|
||||
const liveGroupAllowFrom = resolveEffectiveMatrixLiveAllowlist({
|
||||
liveEntries: liveAccountAllowlists.groupAllowFrom,
|
||||
startupResolvedEntries: groupAllowFromResolvedEntries,
|
||||
});
|
||||
const accessState = resolveMatrixMonitorAccessState({
|
||||
allowFrom,
|
||||
allowFrom: liveDmAllowFrom,
|
||||
storeAllowFrom,
|
||||
groupAllowFrom,
|
||||
groupAllowFrom: liveGroupAllowFrom,
|
||||
roomUsers,
|
||||
senderId,
|
||||
isRoom,
|
||||
|
||||
@@ -34,7 +34,7 @@ import {
|
||||
} from "../sync-state.js";
|
||||
import { createMatrixThreadBindingManager } from "../thread-bindings.js";
|
||||
import { registerMatrixAutoJoin } from "./auto-join.js";
|
||||
import { resolveMatrixMonitorConfig } from "./config.js";
|
||||
import { resolveMatrixMonitorConfig, type MatrixResolvedAllowlistEntry } from "./config.js";
|
||||
import { createDirectRoomTracker } from "./direct.js";
|
||||
import { registerMatrixMonitorEvents } from "./events.js";
|
||||
import { createMatrixRoomMessageHandler } from "./handler.js";
|
||||
@@ -112,6 +112,8 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
||||
const accountAllowBots = accountConfig.allowBots;
|
||||
let allowFrom: string[] = (accountConfig.dm?.allowFrom ?? []).map(String);
|
||||
let groupAllowFrom: string[] = (accountConfig.groupAllowFrom ?? []).map(String);
|
||||
let allowFromResolvedEntries: MatrixResolvedAllowlistEntry[] = [];
|
||||
let groupAllowFromResolvedEntries: MatrixResolvedAllowlistEntry[] = [];
|
||||
let roomsConfig = accountConfig.groups ?? accountConfig.rooms;
|
||||
let needsRoomAliasesForConfig = false;
|
||||
const configuredBotUserIds = resolveConfiguredMatrixBotUserIds({
|
||||
@@ -119,7 +121,13 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
||||
accountId: effectiveAccountId,
|
||||
});
|
||||
|
||||
({ allowFrom, groupAllowFrom, roomsConfig } = await resolveMatrixMonitorConfig({
|
||||
({
|
||||
allowFrom,
|
||||
allowFromResolvedEntries,
|
||||
groupAllowFrom,
|
||||
groupAllowFromResolvedEntries,
|
||||
roomsConfig,
|
||||
} = await resolveMatrixMonitorConfig({
|
||||
cfg,
|
||||
accountId: effectiveAccountId,
|
||||
allowFrom,
|
||||
@@ -320,7 +328,9 @@ export async function monitorMatrixProvider(opts: MonitorMatrixOpts = {}): Promi
|
||||
logger,
|
||||
logVerboseMessage,
|
||||
allowFrom,
|
||||
allowFromResolvedEntries,
|
||||
groupAllowFrom,
|
||||
groupAllowFromResolvedEntries,
|
||||
roomsConfig,
|
||||
accountAllowBots,
|
||||
configuredBotUserIds,
|
||||
|
||||
Reference in New Issue
Block a user