refactor(ringcentral): remove file-based credential support
Credentials now only loaded from: 1. Config file (~/.clawdbot/clawdbot.json) 2. Environment variables This matches Telegram's approach for consistency. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
parent
f9d6ec7106
commit
1ceaa31fb3
@ -1,13 +1,9 @@
|
|||||||
import { existsSync, readFileSync } from "node:fs";
|
|
||||||
import { resolve } from "node:path";
|
|
||||||
import { homedir } from "node:os";
|
|
||||||
|
|
||||||
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
import type { ClawdbotConfig } from "clawdbot/plugin-sdk";
|
||||||
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
import { DEFAULT_ACCOUNT_ID, normalizeAccountId } from "clawdbot/plugin-sdk";
|
||||||
|
|
||||||
import type { RingCentralAccountConfig, RingCentralConfig } from "./types.js";
|
import type { RingCentralAccountConfig, RingCentralConfig } from "./types.js";
|
||||||
|
|
||||||
export type RingCentralCredentialSource = "config" | "file" | "env" | "none";
|
export type RingCentralCredentialSource = "config" | "env" | "none";
|
||||||
|
|
||||||
export type ResolvedRingCentralAccount = {
|
export type ResolvedRingCentralAccount = {
|
||||||
accountId: string;
|
accountId: string;
|
||||||
@ -25,90 +21,9 @@ const ENV_CLIENT_ID = "RINGCENTRAL_CLIENT_ID";
|
|||||||
const ENV_CLIENT_SECRET = "RINGCENTRAL_CLIENT_SECRET";
|
const ENV_CLIENT_SECRET = "RINGCENTRAL_CLIENT_SECRET";
|
||||||
const ENV_JWT = "RINGCENTRAL_JWT";
|
const ENV_JWT = "RINGCENTRAL_JWT";
|
||||||
const ENV_SERVER = "RINGCENTRAL_SERVER";
|
const ENV_SERVER = "RINGCENTRAL_SERVER";
|
||||||
const ENV_CREDENTIALS_FILE = "RINGCENTRAL_CREDENTIALS_FILE";
|
|
||||||
|
|
||||||
const DEFAULT_SERVER = "https://platform.ringcentral.com";
|
const DEFAULT_SERVER = "https://platform.ringcentral.com";
|
||||||
|
|
||||||
// Default credential file locations to check
|
|
||||||
const DEFAULT_CREDENTIALS_FILES = [
|
|
||||||
"rc-credentials.json",
|
|
||||||
".clawdbot/rc-credentials.json",
|
|
||||||
];
|
|
||||||
|
|
||||||
type CredentialsFile = {
|
|
||||||
clientId?: string;
|
|
||||||
clientSecret?: string;
|
|
||||||
jwt?: string;
|
|
||||||
server?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
let cachedFileCredentials: { path: string; data: CredentialsFile } | null = null;
|
|
||||||
|
|
||||||
function findCredentialsFile(configFile?: string): { path: string; data: CredentialsFile } | null {
|
|
||||||
// If explicitly specified, use that
|
|
||||||
if (configFile?.trim()) {
|
|
||||||
const filePath = resolve(configFile.trim());
|
|
||||||
if (existsSync(filePath)) {
|
|
||||||
try {
|
|
||||||
const content = readFileSync(filePath, "utf8");
|
|
||||||
return { path: filePath, data: JSON.parse(content) as CredentialsFile };
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check env var for file path
|
|
||||||
const envFile = process.env[ENV_CREDENTIALS_FILE]?.trim();
|
|
||||||
if (envFile) {
|
|
||||||
const filePath = resolve(envFile);
|
|
||||||
if (existsSync(filePath)) {
|
|
||||||
try {
|
|
||||||
const content = readFileSync(filePath, "utf8");
|
|
||||||
return { path: filePath, data: JSON.parse(content) as CredentialsFile };
|
|
||||||
} catch {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check default locations
|
|
||||||
const searchPaths = [
|
|
||||||
...DEFAULT_CREDENTIALS_FILES.map((f) => resolve(process.cwd(), f)),
|
|
||||||
...DEFAULT_CREDENTIALS_FILES.map((f) => resolve(homedir(), f)),
|
|
||||||
];
|
|
||||||
|
|
||||||
for (const filePath of searchPaths) {
|
|
||||||
if (existsSync(filePath)) {
|
|
||||||
try {
|
|
||||||
const content = readFileSync(filePath, "utf8");
|
|
||||||
return { path: filePath, data: JSON.parse(content) as CredentialsFile };
|
|
||||||
} catch {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadFileCredentials(configFile?: string): CredentialsFile | null {
|
|
||||||
// Use cached if available and no specific file requested
|
|
||||||
if (!configFile && cachedFileCredentials) {
|
|
||||||
return cachedFileCredentials.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = findCredentialsFile(configFile);
|
|
||||||
if (result) {
|
|
||||||
if (!configFile) {
|
|
||||||
cachedFileCredentials = result;
|
|
||||||
}
|
|
||||||
return result.data;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
function listConfiguredAccountIds(cfg: ClawdbotConfig): string[] {
|
||||||
const accounts = (cfg.channels?.ringcentral as RingCentralConfig | undefined)?.accounts;
|
const accounts = (cfg.channels?.ringcentral as RingCentralConfig | undefined)?.accounts;
|
||||||
if (!accounts || typeof accounts !== "object") return [];
|
if (!accounts || typeof accounts !== "object") return [];
|
||||||
@ -176,28 +91,7 @@ function resolveCredentialsFromConfig(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Check credentials file (rc-credentials.json)
|
// 2. Check environment variables (default account only)
|
||||||
const fileCredentials = loadFileCredentials(
|
|
||||||
(account as { credentialsFile?: string }).credentialsFile,
|
|
||||||
);
|
|
||||||
if (fileCredentials) {
|
|
||||||
const fileClientId = fileCredentials.clientId?.trim();
|
|
||||||
const fileClientSecret = fileCredentials.clientSecret?.trim();
|
|
||||||
const fileJwt = fileCredentials.jwt?.trim();
|
|
||||||
const fileServer = fileCredentials.server?.trim() || DEFAULT_SERVER;
|
|
||||||
|
|
||||||
if (fileClientId && fileClientSecret && fileJwt) {
|
|
||||||
return {
|
|
||||||
clientId: fileClientId,
|
|
||||||
clientSecret: fileClientSecret,
|
|
||||||
jwt: fileJwt,
|
|
||||||
server: fileServer,
|
|
||||||
source: "file",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Check environment variables (default account only)
|
|
||||||
if (accountId === DEFAULT_ACCOUNT_ID) {
|
if (accountId === DEFAULT_ACCOUNT_ID) {
|
||||||
const envClientId = process.env[ENV_CLIENT_ID]?.trim();
|
const envClientId = process.env[ENV_CLIENT_ID]?.trim();
|
||||||
const envClientSecret = process.env[ENV_CLIENT_SECRET]?.trim();
|
const envClientSecret = process.env[ENV_CLIENT_SECRET]?.trim();
|
||||||
@ -214,21 +108,15 @@ function resolveCredentialsFromConfig(params: {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Allow partial config + file + env fallback
|
// 3. Allow partial config + env fallback
|
||||||
const finalClientId = configClientId || fileCredentials?.clientId?.trim() || envClientId;
|
const finalClientId = configClientId || envClientId;
|
||||||
const finalClientSecret = configClientSecret || fileCredentials?.clientSecret?.trim() || envClientSecret;
|
const finalClientSecret = configClientSecret || envClientSecret;
|
||||||
const finalJwt = configJwt || fileCredentials?.jwt?.trim() || envJwt;
|
const finalJwt = configJwt || envJwt;
|
||||||
const finalServer = configServer !== DEFAULT_SERVER
|
const finalServer = configServer !== DEFAULT_SERVER ? configServer : envServer;
|
||||||
? configServer
|
|
||||||
: fileCredentials?.server?.trim() || envServer;
|
|
||||||
|
|
||||||
if (finalClientId && finalClientSecret && finalJwt) {
|
if (finalClientId && finalClientSecret && finalJwt) {
|
||||||
const source: RingCentralCredentialSource =
|
const source: RingCentralCredentialSource =
|
||||||
configClientId || configClientSecret || configJwt
|
configClientId || configClientSecret || configJwt ? "config" : "env";
|
||||||
? "config"
|
|
||||||
: fileCredentials?.clientId || fileCredentials?.clientSecret || fileCredentials?.jwt
|
|
||||||
? "file"
|
|
||||||
: "env";
|
|
||||||
return {
|
return {
|
||||||
clientId: finalClientId,
|
clientId: finalClientId,
|
||||||
clientSecret: finalClientSecret,
|
clientSecret: finalClientSecret,
|
||||||
|
|||||||
@ -96,7 +96,6 @@ export type RingCentralAccountConfig = {
|
|||||||
clientSecret?: string;
|
clientSecret?: string;
|
||||||
jwt?: string;
|
jwt?: string;
|
||||||
server?: string;
|
server?: string;
|
||||||
credentialsFile?: string;
|
|
||||||
webhookPath?: string;
|
webhookPath?: string;
|
||||||
webhookVerificationToken?: string;
|
webhookVerificationToken?: string;
|
||||||
markdown?: MarkdownConfig;
|
markdown?: MarkdownConfig;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user