@@ -25,20 +25,13 @@ export function composeFileRequiresPostgresPassword(composeFile: string): boolea
2525}
2626
2727/** Where a chosen `POSTGRES_PASSWORD` came from. */
28- export type PostgresPasswordSource = 'environment' | ' generated' | 'legacy'
28+ export type PostgresPasswordSource = 'generated' | 'legacy'
2929
3030export interface PostgresPasswordChoice {
3131 value : string
3232 source : PostgresPasswordSource
3333}
3434
35- /**
36- * A password the wizard can persist verbatim: Compose interpolates it unescaped
37- * into `DATABASE_URL`, and `.env` reinterprets whitespace, comments, quotes and
38- * `$`, so only URL-unreserved characters survive both unchanged.
39- */
40- const PERSISTABLE_PASSWORD = / ^ [ A - Z a - z 0 - 9 . _ ~ - ] + $ /
41-
4235interface ChooseOptions {
4336 /** The shell environment, whose `POSTGRES_PASSWORD` Compose interpolates over `.env`. */
4437 shell ?: NodeJS . ProcessEnv
@@ -47,57 +40,35 @@ interface ChooseOptions {
4740
4841/**
4942 * Picks the `POSTGRES_PASSWORD` to write to a Compose install's `.env`, or null
50- * when `.env` already has the right one . The production Compose file requires
51- * the variable, and the value must match what the data volume was created with —
43+ * when nothing should be written . The production Compose file requires the
44+ * variable, and the value must match what the data volume was created with —
5245 * Postgres ignores `POSTGRES_PASSWORD` on an existing data directory, so a
5346 * wrong value locks the app out of its own database:
5447 *
55- * - A value exported in the shell is what Compose is using. It is persisted when
56- * `.env` has none , so a later run without the export does not fall back to a
57- * guess. An empty export, one that differs from `.env`, or one `.env` cannot
58- * hold verbatim is refused: which value the volume was created with cannot be
59- * known, and either silent choice can lock the app out.
60- * - With no value anywhere, an existing volume was created with the legacy
61- * password, and a project with no volume yet gets a generated one.
48+ * - A value exported in the shell is the operator's to manage: Compose
49+ * interpolates it over `.env`, so nothing is written. An empty export is
50+ * refused, because Compose would use the empty value and refuse to start
51+ * however good the one in `.env` is.
52+ * - Otherwise a value in `.env` stands, an existing volume was created with the
53+ * legacy password the file used to default to, and a project with no volume
54+ * yet gets a generated one.
6255 */
6356export function choosePostgresPassword (
6457 envFileValue : string | undefined ,
6558 project : string ,
6659 { shell = process . env , hasDatabaseVolume = composeDatabaseVolumeExists } : ChooseOptions = { }
6760) : PostgresPasswordChoice | null {
6861 const shellValue = shell . POSTGRES_PASSWORD
69- if ( shellValue === undefined ) {
70- if ( envFileValue ) return null
71- return hasDatabaseVolume ( project )
72- ? { value : LEGACY_POSTGRES_PASSWORD , source : 'legacy' }
73- : { value : generateSecret ( ) , source : 'generated' }
74- }
7562 if ( shellValue === '' ) {
7663 throw new SetupError (
7764 'POSTGRES_PASSWORD is exported but empty, and Compose uses it over .env.' ,
7865 [ 'unset it (unset POSTGRES_PASSWORD) so the value in .env applies' ]
7966 )
8067 }
81- if ( envFileValue ) {
82- if ( envFileValue === shellValue ) return null
83- throw new SetupError (
84- 'POSTGRES_PASSWORD in the shell differs from the one in .env, so it is unclear which one the database was created with.' ,
85- [
86- 'unset the exported POSTGRES_PASSWORD if .env holds the database password' ,
87- 'or set the exported value in .env if that is the database password' ,
88- ]
89- )
90- }
91- if ( ! PERSISTABLE_PASSWORD . test ( shellValue ) ) {
92- throw new SetupError (
93- 'POSTGRES_PASSWORD is exported only in the shell, and contains characters that cannot be stored in .env and embedded in DATABASE_URL unchanged.' ,
94- [
95- 'use only letters, digits and . _ ~ - (for a new install: openssl rand -hex 24)' ,
96- 'or add it to .env yourself if you have confirmed it works in a connection URL' ,
97- ]
98- )
99- }
100- return { value : shellValue , source : 'environment' }
68+ if ( shellValue !== undefined || envFileValue ) return null
69+ return hasDatabaseVolume ( project )
70+ ? { value : LEGACY_POSTGRES_PASSWORD , source : 'legacy' }
71+ : { value : generateSecret ( ) , source : 'generated' }
10172}
10273
10374/** Whether a Compose project already has a Postgres data volume, found by Compose's own labels. */
@@ -159,10 +130,6 @@ export function reportPostgresPasswordChoice(
159130 choice : PostgresPasswordChoice ,
160131 { compose, user, envPath } : { compose : string ; user : string ; envPath : string }
161132) : void {
162- if ( choice . source === 'environment' ) {
163- p . log . step ( `Saved POSTGRES_PASSWORD from the shell environment to ${ envPath } ` )
164- return
165- }
166133 if ( choice . source === 'generated' ) {
167134 p . log . step ( `Generated POSTGRES_PASSWORD in ${ envPath } ` )
168135 return
0 commit comments