UNPKG

@osiris-ai/postgres-sdk

Version:
119 lines (116 loc) 3.15 kB
import { z } from 'zod'; import { SecretSharingAuthenticator } from '@osiris-ai/sdk'; import { Client } from 'pg'; // @osiris-ai/postgres-sdk - PostgreSQL SDK for Authentication and API Clients var PostgresSecretSchema = z.object({ db_url: z.string().url({ message: "Invalid database URL format" }) }); var PostgresSecretSharingAuthenticator = class extends SecretSharingAuthenticator { secrets = null; constructor() { super("postgres", PostgresSecretSchema); } set(secrets) { const result = PostgresSecretSchema.safeParse(secrets); if (!result.success) { return false; } this.secrets = result.data; return true; } getDbUrl() { return this.secrets?.db_url ?? null; } /** * Execute SQL queries against the PostgreSQL database * @param params Action parameters containing SQL query * @param secrets Database connection secrets * @returns Query results or error response */ async action(params, secrets) { if (!params.data) { return { status: 400, statusText: "No data provided", data: null }; } const sql = params.data.sql; const queryParams = params.data.params; if (!sql || !queryParams) { return { status: 400, statusText: "No SQL query provided", data: null }; } const validation = this.validateSql(sql); if (!validation.isValid) { return { status: 400, statusText: validation.error || "Invalid SQL query", data: null }; } if (!this.secrets?.db_url) { return { status: 400, statusText: "No database connection configured", data: null }; } const client = new Client({ connectionString: this.secrets.db_url }); try { await client.connect(); const result = await client.query(sql, queryParams); await client.end(); return { status: 200, statusText: "OK", data: { rows: result.rows, rowCount: result.rowCount, command: result.command }, headers: {} }; } catch (error) { await client.end().catch(() => { }); return { status: 500, statusText: error.message || "Database query failed", data: null }; } } /** * Validate SQL query for safety (basic checks) * @param sql SQL query to validate * @returns true if query appears safe */ validateSql(sql) { const trimmedSql = sql.trim().toLowerCase(); const dangerousPatterns = [ /^\s*drop\s+/, /^\s*delete\s+.*\s+where\s+1\s*=\s*1/, /^\s*truncate\s+/, /^\s*alter\s+/, /;\s*drop\s+/, /;\s*delete\s+/, /;\s*truncate\s+/ ]; for (const pattern of dangerousPatterns) { if (pattern.test(trimmedSql)) { return { isValid: false, error: "SQL query contains potentially dangerous operations" }; } } return { isValid: true }; } }; export { PostgresSecretSharingAuthenticator }; //# sourceMappingURL=authenticator.js.map //# sourceMappingURL=authenticator.js.map