Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DataSourceOptions } from 'typeorm'
import { VectorStoreDriver } from './Base'
import { resolvePostgresSSL } from '../sslConfig'
import { FLOWISE_CHATID, ICommonObject } from '../../../../src'
import { sanitizeDataSourceOptions } from '../../../../src/sanitizeDataSourceOptions'
import { TypeORMVectorStore, TypeORMVectorStoreArgs, TypeORMVectorStoreDocument } from '@langchain/community/vectorstores/typeorm'
Expand Down Expand Up @@ -36,7 +37,10 @@ export class TypeORMDriver extends VectorStoreDriver {
type: 'postgres',
host: this.getHost(),
port: this.getPort(),
ssl: this.getSSL(),
// A user-supplied `ssl` in Additional Configuration (e.g. a custom CA or
// rejectUnauthorized flag for AWS RDS / corporate CAs) takes precedence over
// the boolean SSL toggle; see resolvePostgresSSL. Falls back to the toggle.
ssl: resolvePostgresSSL(additionalConfiguration, this.getSSL()),
username: user, // Required by TypeORMVectorStore
user: user, // Required by Pool in similaritySearchVectorWithScore
password: password,
Expand Down
30 changes: 30 additions & 0 deletions packages/components/nodes/vectorstores/Postgres/sslConfig.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { resolvePostgresSSL } from './sslConfig'

describe('resolvePostgresSSL', () => {
it('falls back to the boolean toggle when Additional Configuration has no ssl', () => {
expect(resolvePostgresSSL({}, true)).toBe(true)
expect(resolvePostgresSSL({}, false)).toBe(false)
expect(resolvePostgresSSL({ connectTimeout: 5000 }, true)).toBe(true)
})

it('falls back to the boolean toggle when Additional Configuration is undefined', () => {
expect(resolvePostgresSSL(undefined, true)).toBe(true)
expect(resolvePostgresSSL(undefined, false)).toBe(false)
})

it('prefers a user-supplied ssl object over the boolean toggle', () => {
const ssl = { rejectUnauthorized: true, ca: 'CERT' }
// custom CA must win even when the toggle is off (AWS RDS / corporate CA case)
expect(resolvePostgresSSL({ ssl }, false)).toBe(ssl)
expect(resolvePostgresSSL({ ssl }, true)).toBe(ssl)
})

it('respects an explicit ssl:false in Additional Configuration', () => {
expect(resolvePostgresSSL({ ssl: false }, true)).toBe(false)
})

it('respects rejectUnauthorized:false for self-signed certificates', () => {
const ssl = { rejectUnauthorized: false }
expect(resolvePostgresSSL({ ssl }, false)).toBe(ssl)
})
})
27 changes: 27 additions & 0 deletions packages/components/nodes/vectorstores/Postgres/sslConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* SSL configuration resolution for the Postgres vector store connection.
*
* Kept as a dependency-free leaf module (no barrel import) so it can be unit
* tested in isolation, mirroring `src/sanitizeDataSourceOptions.ts`.
*/

/**
* Resolves the SSL option used to open the Postgres connection.
*
* The node exposes a boolean "SSL" toggle, but the "Additional Configuration"
* field also documents `ssl` as a supported TypeORM connection option. When an
* operator needs a custom CA (AWS RDS, an internal corporate CA) or has to relax
* verification for a self-signed certificate, they supply a richer value there,
* e.g. `{ "ssl": { "ca": "<pem>" } }` or `{ "ssl": { "rejectUnauthorized": false } }`.
* That value must take precedence over the boolean toggle instead of being
* clobbered by it, otherwise operators are pushed onto the global
* `NODE_TLS_REJECT_UNAUTHORIZED=0` escape hatch, which disables TLS verification
* process-wide. Falls back to the boolean toggle when Additional Configuration
* does not specify `ssl`, preserving the existing default behaviour.
*/
export function resolvePostgresSSL(additionalConfig: Record<string, any> | undefined, sslToggle: boolean): boolean | Record<string, any> {
if (additionalConfig != null && Object.prototype.hasOwnProperty.call(additionalConfig, 'ssl')) {
return additionalConfig.ssl
}
return sslToggle
}
Comment on lines +22 to +27

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To align with the repository's general rules, use loose equality (!= null) for nullish checks instead of combining truthiness and typeof checks. This simplifies the condition while remaining safe, as Object.prototype.hasOwnProperty.call handles primitive values gracefully without throwing errors.

Suggested change
export function resolvePostgresSSL(additionalConfig: Record<string, any> | undefined, sslToggle: boolean): boolean | Record<string, any> {
if (additionalConfig && typeof additionalConfig === 'object' && Object.prototype.hasOwnProperty.call(additionalConfig, 'ssl')) {
return additionalConfig.ssl
}
return sslToggle
}
export function resolvePostgresSSL(additionalConfig: Record<string, any> | undefined, sslToggle: boolean): boolean | Record<string, any> {
if (additionalConfig != null && Object.prototype.hasOwnProperty.call(additionalConfig, 'ssl')) {
return additionalConfig.ssl
}
return sslToggle
}
References
  1. In JavaScript/TypeScript, use loose equality (== null) as a standard idiom for a 'nullish' check that covers both null and undefined.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 06c2dbd — switched to the != null nullish check. Thanks for the review.