Repository navigation
Expand file tree
/
Copy pathdb.js
More file actions
33 lines (31 loc) · 1.87 KB
/
Copy pathdb.js
File metadata and controls
33 lines (31 loc) · 1.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// velixir's DATABASE_URL, translated for the database clients inside Umami.
//
// velixir injects DATABASE_URL as postgres://user:pass@host:5432/db?sslmode=require. The
// database speaks TLS with a certificate issued by velixir's own CA, so the URL means what
// libpq means by "require": encrypt the connection, but do not check the certificate against
// the public CAs your machine trusts.
//
// Umami reaches Postgres through two different clients, and they read that URL differently:
//
// 1. The server, and the connection check in Umami's scripts/check-db.js, use node-postgres
// (through Prisma's pg adapter). node-postgres treats sslmode=require as verify-full, so
// the handshake fails with "self-signed certificate". Umami builds its client from the
// URL alone, so there is no ssl option to pass instead. Adding uselibpqcompat=true makes
// node-postgres read sslmode the way libpq does. The connection is still encrypted.
// 2. `prisma migrate deploy` uses Prisma's schema engine, which already reads
// sslmode=require as "encrypt, do not verify". It gets the URL exactly as injected,
// through DIRECT_DATABASE_URL, which check-db.js prefers for migrations when it is set.
//
// A URL that asks for verify-ca or verify-full (a database whose CA you hold) is left alone,
// and so is one with no sslmode at all (a local Postgres without TLS).
function forNodePostgres(databaseUrl) {
const url = new URL(databaseUrl);
const mode = (url.searchParams.get('sslmode') || '').toLowerCase();
if ((mode !== 'require' && mode !== 'prefer') || url.searchParams.has('uselibpqcompat')) {
return databaseUrl;
}
// Appended rather than rebuilt from the parsed URL, so the password comes through
// byte for byte however it was encoded.
return `${databaseUrl}${databaseUrl.includes('?') ? '&' : '?'}uselibpqcompat=true`;
}
module.exports = { forNodePostgres };