Repository navigation
Expand file tree
/
Copy pathdemo-database.mjs
More file actions
110 lines (107 loc) · 4.03 KB
/
Copy pathdemo-database.mjs
File metadata and controls
110 lines (107 loc) · 4.03 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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
const invalidConfiguration = () => new Error('Local demo database configuration is invalid');
const aliases = new Map([
['host', 'host'],
['server', 'host'],
['port', 'port'],
['database', 'database'],
['username', 'username'],
['user name', 'username'],
['userid', 'username'],
['user id', 'username'],
['uid', 'username'],
['password', 'password'],
['pwd', 'password'],
['psw', 'password'],
]);
// The local demo accepts only these five fields, not the general Npgsql grammar.
// Quoted values preserve semicolons/whitespace and use doubled quote escaping.
function localConnectionFields(source) {
if (typeof source !== 'string' || /[\u0000-\u0008\u000a-\u001f\u007f]/.test(source))
throw invalidConfiguration();
const fields = new Map();
let index = 0;
while (index < source.length) {
while (/[; \t]/.test(source[index] ?? '') && index < source.length) index++;
if (index === source.length) break;
const start = index;
while (index < source.length && source[index] !== '=') {
if (!/[a-z \t]/i.test(source[index])) throw invalidConfiguration();
index++;
}
if (index === source.length) throw invalidConfiguration();
const key = aliases.get(source.slice(start, index).trim().toLowerCase());
if (!key || fields.has(key)) throw invalidConfiguration();
index++;
while (index < source.length && /[ \t]/.test(source[index])) index++;
let value = '';
const quote = source[index];
if (quote === '"' || quote === "'") {
index++;
let closed = false;
while (index < source.length) {
const character = source[index++];
if (character !== quote) value += character;
else if (source[index] === quote) {
value += quote;
index++;
} else {
closed = true;
break;
}
}
if (!closed) throw invalidConfiguration();
while (index < source.length && /[ \t]/.test(source[index])) index++;
if (index < source.length && source[index] !== ';') throw invalidConfiguration();
} else {
const start = index;
while (index < source.length && source[index] !== ';') {
if (source[index] === '"' || source[index] === "'") throw invalidConfiguration();
index++;
}
value = source.slice(start, index).trim();
}
if (!value) throw invalidConfiguration();
fields.set(key, value);
}
return fields;
}
/** Reject stale local credentials in the launcher without giving them to a child process. */
export function validateDemoDatabaseConfiguration(values) {
if (
values === null ||
values === undefined ||
typeof values.POSTGRES_DB !== 'string' ||
!values.POSTGRES_DB
)
throw invalidConfiguration();
for (const [suffix, role, passwordKey] of [
['Migration', 'learnstack_migration', 'LEARNSTACK_MIGRATION_PW'],
['Default', 'learnstack_app', 'LEARNSTACK_APP_PW'],
['PlatformAdmin', 'learnstack_platform', 'LEARNSTACK_PLATFORM_PW'],
['OutboxDispatcher', 'learnstack_outbox_admin', 'LEARNSTACK_OUTBOX_PW'],
]) {
const password = values[passwordKey];
const fields = localConnectionFields(values[`ConnectionStrings__${suffix}`]);
const port = fields.get('port') ?? '5432';
if (
typeof password !== 'string' ||
!password ||
fields.get('username') !== role ||
fields.get('password') !== password ||
fields.get('database') !== values.POSTGRES_DB ||
!['localhost', '127.0.0.1'].includes(fields.get('host')) ||
!/^\d+$/.test(port) ||
Number(port) !== 5432
)
throw invalidConfiguration();
}
}
/** Every Seeder mode receives only its own credential and process prerequisites. */
export function publicSeederEnvironment(applicationConnectionString, base = process.env) {
const environment = {};
for (const key of ['PATH', 'HOME', 'DOTNET_ROOT', 'TMPDIR', 'APPDATA'])
if (base[key] !== undefined) environment[key] = base[key];
if (applicationConnectionString !== undefined)
environment.ConnectionStrings__Default = applicationConnectionString;
return environment;
}