mirror of
https://github.com/openclaw/openclaw.git
synced 2026-10-03 01:29:56 +00:00
* refactor(plugins): deslop long-tail extensions second pass Reuse existing SDK parsing and result owners, simplify private projections, and remove redundant state, forwarding helpers and test-only exports across 25 small plugins. Preserve registered descriptors and existing wire contracts. Require both Canvas renderer dialects when falling back to prebuilt bundles without build dependencies. Keep the regression at the build script entrypoint. * build(firecrawl): drop unused zod dependency
108 lines
3.5 KiB
TypeScript
108 lines
3.5 KiB
TypeScript
import type { OpenClawPluginApi } from "openclaw/plugin-sdk/plugin-entry";
|
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
|
|
type ResolveAuthLabelResult = {
|
|
label?: "token" | "password" | "trusted-proxy";
|
|
error?: string;
|
|
};
|
|
|
|
type PairingCommandAuthParams = {
|
|
channel: string;
|
|
gatewayClientScopes?: readonly string[] | null;
|
|
senderIsOwner?: boolean;
|
|
};
|
|
|
|
type PairingCommandAuthState = {
|
|
isInternalGatewayCaller: boolean;
|
|
isMissingPairingPrivilege: boolean;
|
|
isMissingSetupHandoffPrivilege: boolean;
|
|
canIssueFullAccessSetup: boolean;
|
|
approvalCallerScopes?: readonly string[];
|
|
};
|
|
|
|
const COMMAND_OWNER_PAIRING_SCOPES = ["operator.pairing"] as const;
|
|
const PAIRING_SCOPE = "operator.pairing";
|
|
const ADMIN_SCOPE = "operator.admin";
|
|
const TALK_SECRETS_SCOPE = "operator.talk.secrets";
|
|
|
|
export function resolveAuthLabel(cfg: OpenClawPluginApi["config"]): ResolveAuthLabelResult {
|
|
const mode = cfg.gateway?.auth?.mode;
|
|
const token =
|
|
normalizeOptionalString(process.env.OPENCLAW_GATEWAY_TOKEN) ??
|
|
normalizeOptionalString(cfg.gateway?.auth?.token);
|
|
const password =
|
|
normalizeOptionalString(process.env.OPENCLAW_GATEWAY_PASSWORD) ??
|
|
normalizeOptionalString(cfg.gateway?.auth?.password);
|
|
|
|
if (mode === "token" || mode === "password") {
|
|
return resolveRequiredAuthLabel(mode, { token, password });
|
|
}
|
|
if (token) {
|
|
return { label: "token" };
|
|
}
|
|
if (password) {
|
|
return { label: "password" };
|
|
}
|
|
// Issuer authorization and bootstrap grants stay separate from ingress auth.
|
|
if (mode === "trusted-proxy") {
|
|
return { label: "trusted-proxy" };
|
|
}
|
|
return { error: "Gateway auth is not configured (no token or password)." };
|
|
}
|
|
|
|
function resolveRequiredAuthLabel(
|
|
mode: "token" | "password",
|
|
values: { token?: string; password?: string },
|
|
): ResolveAuthLabelResult {
|
|
return values[mode]
|
|
? { label: mode }
|
|
: { error: `Gateway auth is set to ${mode}, but no ${mode} is configured.` };
|
|
}
|
|
|
|
function isInternalGatewayPairingCaller(params: PairingCommandAuthParams): boolean {
|
|
return params.channel === "webchat" || Array.isArray(params.gatewayClientScopes);
|
|
}
|
|
|
|
function hasPairingPrivilege(scopes: readonly string[]): boolean {
|
|
return scopes.includes(PAIRING_SCOPE) || scopes.includes(ADMIN_SCOPE);
|
|
}
|
|
|
|
function hasSetupHandoffPrivilege(scopes: readonly string[]): boolean {
|
|
return scopes.includes(TALK_SECRETS_SCOPE) || scopes.includes(ADMIN_SCOPE);
|
|
}
|
|
|
|
export function resolvePairingCommandAuthState(
|
|
params: PairingCommandAuthParams,
|
|
): PairingCommandAuthState {
|
|
const isInternalGatewayCaller = isInternalGatewayPairingCaller(params);
|
|
if (isInternalGatewayCaller) {
|
|
const approvalCallerScopes = Array.isArray(params.gatewayClientScopes)
|
|
? params.gatewayClientScopes
|
|
: [];
|
|
return {
|
|
isInternalGatewayCaller,
|
|
isMissingPairingPrivilege: !hasPairingPrivilege(approvalCallerScopes),
|
|
isMissingSetupHandoffPrivilege: !hasSetupHandoffPrivilege(approvalCallerScopes),
|
|
canIssueFullAccessSetup: approvalCallerScopes.includes(ADMIN_SCOPE),
|
|
approvalCallerScopes,
|
|
};
|
|
}
|
|
|
|
if (params.senderIsOwner === true) {
|
|
return {
|
|
isInternalGatewayCaller,
|
|
isMissingPairingPrivilege: false,
|
|
isMissingSetupHandoffPrivilege: false,
|
|
canIssueFullAccessSetup: true,
|
|
approvalCallerScopes: COMMAND_OWNER_PAIRING_SCOPES,
|
|
};
|
|
}
|
|
|
|
return {
|
|
isInternalGatewayCaller,
|
|
isMissingPairingPrivilege: true,
|
|
isMissingSetupHandoffPrivilege: true,
|
|
canIssueFullAccessSetup: false,
|
|
approvalCallerScopes: undefined,
|
|
};
|
|
}
|