| | import path from 'path'; |
| | import axios from 'axios'; |
| | import { logger } from '@librechat/data-schemas'; |
| | import { readFileAsString } from './files'; |
| |
|
| | export interface GoogleServiceKey { |
| | type?: string; |
| | project_id?: string; |
| | private_key_id?: string; |
| | private_key?: string; |
| | client_email?: string; |
| | client_id?: string; |
| | auth_uri?: string; |
| | token_uri?: string; |
| | auth_provider_x509_cert_url?: string; |
| | client_x509_cert_url?: string; |
| | [key: string]: unknown; |
| | } |
| |
|
| | |
| | |
| | |
| | |
| | |
| | export async function loadServiceKey(keyPath: string): Promise<GoogleServiceKey | null> { |
| | if (!keyPath) { |
| | return null; |
| | } |
| |
|
| | let serviceKey: unknown; |
| |
|
| | |
| | if (keyPath.trim().match(/^[A-Za-z0-9+/]+=*$/)) { |
| | try { |
| | const decoded = Buffer.from(keyPath.trim(), 'base64').toString('utf-8'); |
| | |
| | serviceKey = JSON.parse(decoded); |
| | } catch { |
| | |
| | |
| | } |
| | } |
| |
|
| | |
| | if (!serviceKey && keyPath.trim().startsWith('{')) { |
| | try { |
| | serviceKey = JSON.parse(keyPath); |
| | } catch (error) { |
| | logger.error('Failed to parse service key from stringified JSON', error); |
| | return null; |
| | } |
| | } |
| | |
| | else if (!serviceKey && /^https?:\/\//.test(keyPath)) { |
| | try { |
| | const response = await axios.get(keyPath); |
| | serviceKey = response.data; |
| | } catch (error) { |
| | logger.error(`Failed to fetch the service key from URL: ${keyPath}`, error); |
| | return null; |
| | } |
| | } else if (!serviceKey) { |
| | |
| | try { |
| | const absolutePath = path.isAbsolute(keyPath) ? keyPath : path.resolve(keyPath); |
| | const { content: fileContent } = await readFileAsString(absolutePath); |
| | serviceKey = JSON.parse(fileContent); |
| | } catch (error) { |
| | logger.error(`Failed to load service key from file: ${keyPath}`, error); |
| | return null; |
| | } |
| | } |
| |
|
| | |
| | if (typeof serviceKey === 'string') { |
| | try { |
| | serviceKey = JSON.parse(serviceKey); |
| | } catch (parseError) { |
| | logger.error(`Failed to parse service key JSON from ${keyPath}`, parseError); |
| | return null; |
| | } |
| | } |
| |
|
| | |
| | if (!serviceKey || typeof serviceKey !== 'object') { |
| | logger.error(`Invalid service key format from ${keyPath}`); |
| | return null; |
| | } |
| |
|
| | |
| | const key = serviceKey as GoogleServiceKey; |
| | if (key.private_key && typeof key.private_key === 'string') { |
| | |
| | |
| | |
| | key.private_key = key.private_key.replace(/\\n/g, '\n'); |
| |
|
| | |
| | key.private_key = key.private_key.split(String.raw`\n`).join('\n'); |
| |
|
| | |
| | if (!key.private_key.includes('\n')) { |
| | |
| | const privateKeyMatch = key.private_key.match( |
| | /^(-----BEGIN [A-Z ]+-----)(.*)(-----END [A-Z ]+-----)$/, |
| | ); |
| | if (privateKeyMatch) { |
| | const [, header, body, footer] = privateKeyMatch; |
| | |
| | key.private_key = `${header}\n${body}\n${footer}`; |
| | } |
| | } |
| | } |
| |
|
| | return key; |
| | } |
| |
|