import type { OpenClawConfig } from "../config/config.js"; import { resolveDmGroupAccessWithLists } from "../security/dm-policy-shared.js"; export type ResolveSenderCommandAuthorizationParams = { cfg: OpenClawConfig; rawBody: string; isGroup: boolean; dmPolicy: string; configuredAllowFrom: string[]; configuredGroupAllowFrom?: string[]; senderId: string; isSenderAllowed: (senderId: string, allowFrom: string[]) => boolean; readAllowFromStore: () => Promise; shouldComputeCommandAuthorized: (rawBody: string, cfg: OpenClawConfig) => boolean; resolveCommandAuthorizedFromAuthorizers: (params: { useAccessGroups: boolean; authorizers: Array<{ configured: boolean; allowed: boolean }>; }) => boolean; }; export type CommandAuthorizationRuntime = { shouldComputeCommandAuthorized: (rawBody: string, cfg: OpenClawConfig) => boolean; resolveCommandAuthorizedFromAuthorizers: (params: { useAccessGroups: boolean; authorizers: Array<{ configured: boolean; allowed: boolean }>; }) => boolean; }; export type ResolveSenderCommandAuthorizationWithRuntimeParams = Omit< ResolveSenderCommandAuthorizationParams, "shouldComputeCommandAuthorized" | "resolveCommandAuthorizedFromAuthorizers" > & { runtime: CommandAuthorizationRuntime; }; export function resolveDirectDmAuthorizationOutcome(params: { isGroup: boolean; dmPolicy: string; senderAllowedForCommands: boolean; }): "disabled" | "unauthorized" | "allowed" { if (params.isGroup) { return "allowed"; } if (params.dmPolicy === "disabled") { return "disabled"; } if (params.dmPolicy !== "open" && !params.senderAllowedForCommands) { return "unauthorized"; } return "allowed"; } export async function resolveSenderCommandAuthorizationWithRuntime( params: ResolveSenderCommandAuthorizationWithRuntimeParams, ): ReturnType { return resolveSenderCommandAuthorization({ ...params, shouldComputeCommandAuthorized: params.runtime.shouldComputeCommandAuthorized, resolveCommandAuthorizedFromAuthorizers: params.runtime.resolveCommandAuthorizedFromAuthorizers, }); } export async function resolveSenderCommandAuthorization( params: ResolveSenderCommandAuthorizationParams, ): Promise<{ shouldComputeAuth: boolean; effectiveAllowFrom: string[]; effectiveGroupAllowFrom: string[]; senderAllowedForCommands: boolean; commandAuthorized: boolean | undefined; }> { const shouldComputeAuth = params.shouldComputeCommandAuthorized(params.rawBody, params.cfg); const storeAllowFrom = !params.isGroup && params.dmPolicy !== "allowlist" && (params.dmPolicy !== "open" || shouldComputeAuth) ? await params.readAllowFromStore().catch(() => []) : []; const access = resolveDmGroupAccessWithLists({ isGroup: params.isGroup, dmPolicy: params.dmPolicy, groupPolicy: "allowlist", allowFrom: params.configuredAllowFrom, groupAllowFrom: params.configuredGroupAllowFrom ?? [], storeAllowFrom, isSenderAllowed: (allowFrom) => params.isSenderAllowed(params.senderId, allowFrom), }); const effectiveAllowFrom = access.effectiveAllowFrom; const effectiveGroupAllowFrom = access.effectiveGroupAllowFrom; const useAccessGroups = params.cfg.commands?.useAccessGroups !== false; const senderAllowedForCommands = params.isSenderAllowed( params.senderId, params.isGroup ? effectiveGroupAllowFrom : effectiveAllowFrom, ); const ownerAllowedForCommands = params.isSenderAllowed(params.senderId, effectiveAllowFrom); const groupAllowedForCommands = params.isSenderAllowed(params.senderId, effectiveGroupAllowFrom); const commandAuthorized = shouldComputeAuth ? params.resolveCommandAuthorizedFromAuthorizers({ useAccessGroups, authorizers: [ { configured: effectiveAllowFrom.length > 0, allowed: ownerAllowedForCommands }, { configured: effectiveGroupAllowFrom.length > 0, allowed: groupAllowedForCommands }, ], }) : undefined; return { shouldComputeAuth, effectiveAllowFrom, effectiveGroupAllowFrom, senderAllowedForCommands, commandAuthorized, }; }