mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 01:20:22 +00:00
refactor: migrate more boundary parsing to zod
This commit is contained in:
@@ -6,6 +6,8 @@ import {
|
||||
resolveMergedAccountConfig,
|
||||
} from "openclaw/plugin-sdk/account-resolution";
|
||||
import { isSecretRef, type OpenClawConfig } from "openclaw/plugin-sdk/core";
|
||||
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
||||
import { z } from "zod";
|
||||
import type { GoogleChatAccountConfig } from "./types.config.js";
|
||||
|
||||
export type GoogleChatCredentialSource = "file" | "inline" | "env" | "none";
|
||||
@@ -22,6 +24,7 @@ export type ResolvedGoogleChatAccount = {
|
||||
|
||||
const ENV_SERVICE_ACCOUNT = "GOOGLE_CHAT_SERVICE_ACCOUNT";
|
||||
const ENV_SERVICE_ACCOUNT_FILE = "GOOGLE_CHAT_SERVICE_ACCOUNT_FILE";
|
||||
const JsonRecordSchema = z.record(z.string(), z.unknown());
|
||||
|
||||
const {
|
||||
listAccountIds: listGoogleChatAccountIds,
|
||||
@@ -62,24 +65,19 @@ function mergeGoogleChatAccountConfig(
|
||||
}
|
||||
|
||||
function parseServiceAccount(value: unknown): Record<string, unknown> | null {
|
||||
if (value && typeof value === "object") {
|
||||
if (isSecretRef(value)) {
|
||||
if (isSecretRef(value)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (typeof value === "string") {
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
if (typeof value !== "string") {
|
||||
return null;
|
||||
}
|
||||
const trimmed = value.trim();
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return JSON.parse(trimmed) as Record<string, unknown>;
|
||||
} catch {
|
||||
return null;
|
||||
return safeParseJsonWithSchema(JsonRecordSchema, trimmed);
|
||||
}
|
||||
|
||||
return safeParseWithSchema(JsonRecordSchema, value);
|
||||
}
|
||||
|
||||
function resolveCredentialsFromConfig(params: {
|
||||
|
||||
@@ -49,6 +49,7 @@ function buildAccount(): ResolvedGoogleChatAccount {
|
||||
describe("googlechat setup", () => {
|
||||
afterEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.unstubAllEnvs();
|
||||
});
|
||||
|
||||
it("rejects env auth for non-default accounts", () => {
|
||||
@@ -186,6 +187,32 @@ describe("googlechat setup", () => {
|
||||
});
|
||||
|
||||
describe("resolveGoogleChatAccount", () => {
|
||||
it("parses default-account env JSON credentials only when they decode to an object", () => {
|
||||
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT", '{"client_email":"bot@example.com"}');
|
||||
|
||||
const resolved = resolveGoogleChatAccount({
|
||||
cfg: { channels: { googlechat: {} } },
|
||||
accountId: "default",
|
||||
});
|
||||
|
||||
expect(resolved.credentialSource).toBe("env");
|
||||
expect(resolved.credentials).toEqual({ client_email: "bot@example.com" });
|
||||
});
|
||||
|
||||
it("ignores env JSON credentials when they decode to a non-object value", () => {
|
||||
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT", '["not","an","object"]');
|
||||
vi.stubEnv("GOOGLE_CHAT_SERVICE_ACCOUNT_FILE", "/tmp/googlechat.json");
|
||||
|
||||
const resolved = resolveGoogleChatAccount({
|
||||
cfg: { channels: { googlechat: {} } },
|
||||
accountId: "default",
|
||||
});
|
||||
|
||||
expect(resolved.credentialSource).toBe("env");
|
||||
expect(resolved.credentials).toBeUndefined();
|
||||
expect(resolved.credentialsFile).toBe("/tmp/googlechat.json");
|
||||
});
|
||||
|
||||
it("inherits shared defaults from accounts.default for named accounts", () => {
|
||||
const cfg: OpenClawConfig = {
|
||||
channels: {
|
||||
|
||||
Reference in New Issue
Block a user