@decohere/data-typeorm 0.0.1-dev.126 → 0.0.1-dev.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +8 -24
- package/src/bootstrap-policy.ts +84 -0
- package/src/bootstrap.ts +76 -0
- package/src/data-source.factory.ts +51 -0
- package/src/database-options.ts +10 -0
- package/src/dialect-map.ts +12 -0
- package/{es6/src/inject-data-source.js → src/inject-data-source.ts} +15 -9
- package/src/scripts/user.ts +234 -0
- package/src/server-manager.ts +300 -0
- package/src/sql-pretty.transport.ts +29 -0
- package/src/type-orm.module.ts +155 -0
- package/src/type-orm.provider.ts +37 -0
- package/src/type-orm.repository.ts +33 -0
- package/src/typeorm-scribe.logger.ts +55 -0
- package/src/typeorm.extensions.ts +42 -0
- package/src/unit-of-work.ts +52 -0
- package/tests/bootstrap-schemas.docker.spec.ts +145 -0
- package/tests/bootstrap.spec.ts +156 -0
- package/tests/db-least-privilege.pentest.spec.ts +125 -0
- package/tests/postgres-container.ts +139 -0
- package/tests/prepare-database.docker.spec.ts +96 -0
- package/tests/server-manager.bootstrap.spec.ts +72 -0
- package/tests/trusted-dev-postgres.spec.ts +212 -0
- package/tests/type-orm.module.spec.ts +123 -0
- package/tests/typeorm.lifecycle.spec.ts +97 -0
- package/tests/unit-of-work.spec.ts +54 -0
- package/tests/user-scripts.pentest.spec.ts +42 -0
- package/LICENSE +0 -15
- package/commonjs/src/bootstrap-policy.js +0 -69
- package/commonjs/src/bootstrap.js +0 -142
- package/commonjs/src/data-source.factory.js +0 -42
- package/commonjs/src/database-options.js +0 -4
- package/commonjs/src/dialect-map.js +0 -26
- package/commonjs/src/index.js +0 -24
- package/commonjs/src/inject-data-source.js +0 -33
- package/commonjs/src/scripts/user.js +0 -259
- package/commonjs/src/server-manager.js +0 -294
- package/commonjs/src/sql-pretty.transport.js +0 -35
- package/commonjs/src/type-orm.module.js +0 -115
- package/commonjs/src/type-orm.provider.js +0 -36
- package/commonjs/src/type-orm.repository.js +0 -30
- package/commonjs/src/typeorm-scribe.logger.js +0 -70
- package/commonjs/src/typeorm.extensions.js +0 -60
- package/commonjs/src/unit-of-work.js +0 -49
- package/es6/src/bootstrap-policy.js +0 -55
- package/es6/src/bootstrap.js +0 -139
- package/es6/src/data-source.factory.js +0 -27
- package/es6/src/database-options.js +0 -1
- package/es6/src/dialect-map.js +0 -8
- package/es6/src/scripts/user.js +0 -209
- package/es6/src/server-manager.js +0 -284
- package/es6/src/sql-pretty.transport.js +0 -20
- package/es6/src/type-orm.module.js +0 -105
- package/es6/src/type-orm.provider.js +0 -26
- package/es6/src/type-orm.repository.js +0 -20
- package/es6/src/typeorm-scribe.logger.js +0 -60
- package/es6/src/typeorm.extensions.js +0 -50
- package/es6/src/unit-of-work.js +0 -39
- package/types/src/bootstrap-policy.d.ts +0 -19
- package/types/src/bootstrap.d.ts +0 -16
- package/types/src/data-source.factory.d.ts +0 -17
- package/types/src/database-options.d.ts +0 -9
- package/types/src/dialect-map.d.ts +0 -8
- package/types/src/index.d.ts +0 -7
- package/types/src/inject-data-source.d.ts +0 -14
- package/types/src/scripts/user.d.ts +0 -56
- package/types/src/server-manager.d.ts +0 -39
- package/types/src/sql-pretty.transport.d.ts +0 -2
- package/types/src/type-orm.module.d.ts +0 -17
- package/types/src/type-orm.provider.d.ts +0 -14
- package/types/src/type-orm.repository.d.ts +0 -12
- package/types/src/typeorm-scribe.logger.d.ts +0 -9
- package/types/src/typeorm.extensions.d.ts +0 -11
- package/types/src/unit-of-work.d.ts +0 -20
- /package/{es6/src/index.js → src/index.ts} +0 -0
package/LICENSE
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
ISC License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2025-2026 Typesmiths
|
|
4
|
-
|
|
5
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
-
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
-
copyright notice and this permission notice appear in all copies.
|
|
8
|
-
|
|
9
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
-
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
-
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
-
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
-
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
-
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
15
|
-
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get assertBootstrapCredentials () {
|
|
13
|
-
return assertBootstrapCredentials;
|
|
14
|
-
},
|
|
15
|
-
get assertDataSourceAuth () {
|
|
16
|
-
return assertDataSourceAuth;
|
|
17
|
-
},
|
|
18
|
-
get isDevelopmentEnv () {
|
|
19
|
-
return isDevelopmentEnv;
|
|
20
|
-
},
|
|
21
|
-
get shouldBootstrapDatabase () {
|
|
22
|
-
return shouldBootstrapDatabase;
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
const _data = require("@decohere/data");
|
|
26
|
-
function isDevelopmentEnv(nodeEnv = process.env.NODE_ENV) {
|
|
27
|
-
const env = nodeEnv?.toLowerCase() ?? "";
|
|
28
|
-
return env === "development" || env === "dev";
|
|
29
|
-
}
|
|
30
|
-
function isTrusted(info) {
|
|
31
|
-
return info.auth === "trust";
|
|
32
|
-
}
|
|
33
|
-
function has(value) {
|
|
34
|
-
return typeof value === "string" && value.length > 0;
|
|
35
|
-
}
|
|
36
|
-
function assertDataSourceAuth(info, nodeEnv = process.env.NODE_ENV) {
|
|
37
|
-
const auth = info.auth ?? "password";
|
|
38
|
-
if (auth !== "password" && auth !== "trust") {
|
|
39
|
-
throw new _data.DataConfigurationError(`Data source "${info.name}": auth must be "password" or "trust" (got ${JSON.stringify(auth)})`);
|
|
40
|
-
}
|
|
41
|
-
if (auth === "trust") {
|
|
42
|
-
if (!isDevelopmentEnv(nodeEnv)) {
|
|
43
|
-
throw new _data.DataConfigurationError(`Data source "${info.name}" sets auth: trust, which is allowed only in development (NODE_ENV is ${JSON.stringify(nodeEnv ?? "")}). A server that trusts every connection belongs on a developer's machine.`);
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (!has(info.password)) {
|
|
48
|
-
throw new _data.DataConfigurationError(`Data source "${info.name}" has no password. Set password, or auth: trust for a local server that trusts every connection.`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
function shouldBootstrapDatabase(info, nodeEnv = process.env.NODE_ENV) {
|
|
52
|
-
if (info.bootstrap === false) {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
const hasAdmin = has(info.adminUser) && (isTrusted(info) || has(info.adminPassword));
|
|
56
|
-
if (info.bootstrap === true) {
|
|
57
|
-
if (!hasAdmin) {
|
|
58
|
-
throw new _data.DataConfigurationError(`Data source "${info.name}": bootstrap requires adminUser and adminPassword (adminPassword may be left out only with auth: trust)`);
|
|
59
|
-
}
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
return isDevelopmentEnv(nodeEnv) && hasAdmin;
|
|
63
|
-
}
|
|
64
|
-
function assertBootstrapCredentials(info) {
|
|
65
|
-
if (isTrusted(info)) return;
|
|
66
|
-
if (has(info.migrateUsername) && !has(info.migratePassword)) {
|
|
67
|
-
throw new _data.DataConfigurationError(`Data source "${info.name}" has migrateUsername but no migratePassword. Set migratePassword, or auth: trust for a local server that trusts every connection.`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
Object.defineProperty(exports, "bootstrapDataSources", {
|
|
6
|
-
enumerable: true,
|
|
7
|
-
get: function() {
|
|
8
|
-
return bootstrapDataSources;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
const _data = require("@decohere/data");
|
|
12
|
-
const _bootstrappolicy = require("./bootstrap-policy.js");
|
|
13
|
-
const _servermanager = require("./server-manager.js");
|
|
14
|
-
function _ts_add_disposable_resource(env, value, async) {
|
|
15
|
-
if (value !== null && value !== void 0) {
|
|
16
|
-
if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected.");
|
|
17
|
-
var dispose, inner;
|
|
18
|
-
if (async) {
|
|
19
|
-
if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined.");
|
|
20
|
-
dispose = value[Symbol.asyncDispose];
|
|
21
|
-
}
|
|
22
|
-
if (dispose === void 0) {
|
|
23
|
-
if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined.");
|
|
24
|
-
dispose = value[Symbol.dispose];
|
|
25
|
-
if (async) inner = dispose;
|
|
26
|
-
}
|
|
27
|
-
if (typeof dispose !== "function") throw new TypeError("Object not disposable.");
|
|
28
|
-
if (inner) dispose = function() {
|
|
29
|
-
try {
|
|
30
|
-
inner.call(this);
|
|
31
|
-
} catch (e) {
|
|
32
|
-
return Promise.reject(e);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
env.stack.push({
|
|
36
|
-
value: value,
|
|
37
|
-
dispose: dispose,
|
|
38
|
-
async: async
|
|
39
|
-
});
|
|
40
|
-
} else if (async) {
|
|
41
|
-
env.stack.push({
|
|
42
|
-
async: true
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return value;
|
|
46
|
-
}
|
|
47
|
-
function _ts_dispose_resources(env) {
|
|
48
|
-
var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function(error, suppressed, message) {
|
|
49
|
-
var e = new Error(message);
|
|
50
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
51
|
-
};
|
|
52
|
-
return (_ts_dispose_resources = function _ts_dispose_resources(env) {
|
|
53
|
-
function fail(e) {
|
|
54
|
-
env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e;
|
|
55
|
-
env.hasError = true;
|
|
56
|
-
}
|
|
57
|
-
var r, s = 0;
|
|
58
|
-
function next() {
|
|
59
|
-
while(r = env.stack.pop()){
|
|
60
|
-
try {
|
|
61
|
-
if (!r.async && s === 1) return s = 0, env.stack.push(r), Promise.resolve().then(next);
|
|
62
|
-
if (r.dispose) {
|
|
63
|
-
var result = r.dispose.call(r.value);
|
|
64
|
-
if (r.async) return s |= 2, Promise.resolve(result).then(next, function(e) {
|
|
65
|
-
fail(e);
|
|
66
|
-
return next();
|
|
67
|
-
});
|
|
68
|
-
} else s |= 1;
|
|
69
|
-
} catch (e) {
|
|
70
|
-
fail(e);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (s === 1) return env.hasError ? Promise.reject(env.error) : Promise.resolve();
|
|
74
|
-
if (env.hasError) throw env.error;
|
|
75
|
-
}
|
|
76
|
-
return next();
|
|
77
|
-
})(env);
|
|
78
|
-
}
|
|
79
|
-
/** What every data source on one server and database must agree on. */ const SHARED_FIELDS = [
|
|
80
|
-
"auth",
|
|
81
|
-
"adminUser",
|
|
82
|
-
"migrateUsername"
|
|
83
|
-
];
|
|
84
|
-
async function bootstrapDataSources(dataSources, options) {
|
|
85
|
-
const nodeEnv = options.nodeEnv ?? process.env.NODE_ENV;
|
|
86
|
-
for (const info of dataSources)(0, _bootstrappolicy.assertDataSourceAuth)(info, nodeEnv);
|
|
87
|
-
const toBootstrap = dataSources.filter((info)=>(0, _bootstrappolicy.shouldBootstrapDatabase)(info, nodeEnv));
|
|
88
|
-
for (const info of toBootstrap)(0, _bootstrappolicy.assertBootstrapCredentials)(info);
|
|
89
|
-
for (const group of byServerAndDatabase(toBootstrap)){
|
|
90
|
-
const env = {
|
|
91
|
-
stack: [],
|
|
92
|
-
error: void 0,
|
|
93
|
-
hasError: false
|
|
94
|
-
};
|
|
95
|
-
try {
|
|
96
|
-
const [first] = group;
|
|
97
|
-
const server = _ts_add_disposable_resource(env, new _servermanager.PostgresServerManager(options.applicationName, first), true);
|
|
98
|
-
await server.connect();
|
|
99
|
-
await server.initializeDatabase(first.database);
|
|
100
|
-
for (const info of group){
|
|
101
|
-
await server.provisionRoles({
|
|
102
|
-
database: info.database,
|
|
103
|
-
appUsername: info.username,
|
|
104
|
-
appPassword: info.password,
|
|
105
|
-
migrateUsername: info.migrateUsername,
|
|
106
|
-
migratePassword: info.migratePassword,
|
|
107
|
-
allowAppDdl: info.synchronize === true,
|
|
108
|
-
schema: info.schema
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
} catch (e) {
|
|
112
|
-
env.error = e;
|
|
113
|
-
env.hasError = true;
|
|
114
|
-
} finally{
|
|
115
|
-
const result = _ts_dispose_resources(env);
|
|
116
|
-
if (result) await result;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
function byServerAndDatabase(dataSources) {
|
|
121
|
-
const groups = new Map();
|
|
122
|
-
for (const info of dataSources){
|
|
123
|
-
const key = `${info.host}:${info.port}/${info.database}`;
|
|
124
|
-
const group = groups.get(key);
|
|
125
|
-
if (group == null) {
|
|
126
|
-
groups.set(key, [
|
|
127
|
-
info
|
|
128
|
-
]);
|
|
129
|
-
continue;
|
|
130
|
-
}
|
|
131
|
-
const [first] = group;
|
|
132
|
-
for (const field of SHARED_FIELDS){
|
|
133
|
-
if (info[field] !== first[field]) {
|
|
134
|
-
throw new _data.DataConfigurationError(`Data sources "${first.name}" and "${info.name}" share database ${key} but set different ${field} (${JSON.stringify(first[field])} and ${JSON.stringify(info[field])})`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
group.push(info);
|
|
138
|
-
}
|
|
139
|
-
return [
|
|
140
|
-
...groups.values()
|
|
141
|
-
];
|
|
142
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get DataSourceFactory () {
|
|
13
|
-
return DataSourceFactory;
|
|
14
|
-
},
|
|
15
|
-
get ManagedDataSource () {
|
|
16
|
-
return ManagedDataSource;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const _typeorm = require("typeorm");
|
|
20
|
-
const _dialectmap = require("./dialect-map.js");
|
|
21
|
-
/** Fields used only for bootstrap / privilege provisioning — not TypeORM connection options. */ function omitProvisionFields(options) {
|
|
22
|
-
const { adminUser: _adminUser, adminPassword: _adminPassword, migrateUsername: _migrateUsername, migratePassword: _migratePassword, bootstrap: _bootstrap, auth: _auth, seed: _seed, dialect: _dialect, name: _name, ...rest } = options;
|
|
23
|
-
return rest;
|
|
24
|
-
}
|
|
25
|
-
class ManagedDataSource extends _typeorm.DataSource {
|
|
26
|
-
async [Symbol.asyncDispose]() {
|
|
27
|
-
if (this.isInitialized) await this.destroy();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
class DataSourceFactory {
|
|
31
|
-
static create(options, logger) {
|
|
32
|
-
const { applicationName } = options;
|
|
33
|
-
const { provider } = options;
|
|
34
|
-
const type = _dialectmap.ProviderMap[provider];
|
|
35
|
-
return new ManagedDataSource({
|
|
36
|
-
type,
|
|
37
|
-
logger,
|
|
38
|
-
applicationName,
|
|
39
|
-
...omitProvisionFields(options)
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get DialectMap () {
|
|
13
|
-
return DialectMap;
|
|
14
|
-
},
|
|
15
|
-
get ProviderMap () {
|
|
16
|
-
return ProviderMap;
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
const ProviderMap = {
|
|
20
|
-
postgres: "postgres",
|
|
21
|
-
mssql: "mssql"
|
|
22
|
-
};
|
|
23
|
-
const DialectMap = {
|
|
24
|
-
postgresql: "postgres",
|
|
25
|
-
tsql: "mssql"
|
|
26
|
-
};
|
package/commonjs/src/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
_export_star(require("./bootstrap.js"), exports);
|
|
6
|
-
_export_star(require("./inject-data-source.js"), exports);
|
|
7
|
-
_export_star(require("./sql-pretty.transport.js"), exports);
|
|
8
|
-
_export_star(require("./type-orm.provider.js"), exports);
|
|
9
|
-
_export_star(require("./type-orm.repository.js"), exports);
|
|
10
|
-
_export_star(require("./typeorm.extensions.js"), exports);
|
|
11
|
-
_export_star(require("./unit-of-work.js"), exports);
|
|
12
|
-
function _export_star(from, to) {
|
|
13
|
-
Object.keys(from).forEach(function(k) {
|
|
14
|
-
if (k !== "default" && !Object.prototype.hasOwnProperty.call(to, k)) {
|
|
15
|
-
Object.defineProperty(to, k, {
|
|
16
|
-
enumerable: true,
|
|
17
|
-
get: function() {
|
|
18
|
-
return from[k];
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
return from;
|
|
24
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get TypeOrmDataSourceToken () {
|
|
13
|
-
return TypeOrmDataSourceToken;
|
|
14
|
-
},
|
|
15
|
-
get injectDataSource () {
|
|
16
|
-
return injectDataSource;
|
|
17
|
-
},
|
|
18
|
-
get typeOrmDataSourceToken () {
|
|
19
|
-
return typeOrmDataSourceToken;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
const _data = require("@decohere/data");
|
|
23
|
-
const _decorators = require("@decohere/crucible/decorators");
|
|
24
|
-
const TypeOrmDataSourceToken = Symbol("TypeOrmDataSource");
|
|
25
|
-
function typeOrmDataSourceToken(name) {
|
|
26
|
-
if (name == null || name === _data.DEFAULT_DATA_SOURCE) {
|
|
27
|
-
return TypeOrmDataSourceToken;
|
|
28
|
-
}
|
|
29
|
-
return Symbol.for(`decohere:typeorm:datasource:${String(name)}`);
|
|
30
|
-
}
|
|
31
|
-
function injectDataSource(name) {
|
|
32
|
-
return (0, _decorators.inject)(typeOrmDataSourceToken(name));
|
|
33
|
-
}
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", {
|
|
3
|
-
value: true
|
|
4
|
-
});
|
|
5
|
-
function _export(target, all) {
|
|
6
|
-
for(var name in all)Object.defineProperty(target, name, {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: Object.getOwnPropertyDescriptor(all, name).get
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
_export(exports, {
|
|
12
|
-
get alterDatabaseOwnerQuery () {
|
|
13
|
-
return alterDatabaseOwnerQuery;
|
|
14
|
-
},
|
|
15
|
-
get assertSafeSqlIdent () {
|
|
16
|
-
return assertSafeSqlIdent;
|
|
17
|
-
},
|
|
18
|
-
get createSchemaQuery () {
|
|
19
|
-
return createSchemaQuery;
|
|
20
|
-
},
|
|
21
|
-
get createUserQuery () {
|
|
22
|
-
return createUserQuery;
|
|
23
|
-
},
|
|
24
|
-
get databaseOwnerQuery () {
|
|
25
|
-
return databaseOwnerQuery;
|
|
26
|
-
},
|
|
27
|
-
get defaultPrivilegesForAppQueries () {
|
|
28
|
-
return defaultPrivilegesForAppQueries;
|
|
29
|
-
},
|
|
30
|
-
get grantConnectQuery () {
|
|
31
|
-
return grantConnectQuery;
|
|
32
|
-
},
|
|
33
|
-
get grantRoleMembershipQuery () {
|
|
34
|
-
return grantRoleMembershipQuery;
|
|
35
|
-
},
|
|
36
|
-
get grantSchemaCreateQuery () {
|
|
37
|
-
return grantSchemaCreateQuery;
|
|
38
|
-
},
|
|
39
|
-
get grantSchemaPrivilegesQuery () {
|
|
40
|
-
return grantSchemaPrivilegesQuery;
|
|
41
|
-
},
|
|
42
|
-
get grantSchemaUsageQuery () {
|
|
43
|
-
return grantSchemaUsageQuery;
|
|
44
|
-
},
|
|
45
|
-
get hasDatabasePrivilegeQuery () {
|
|
46
|
-
return hasDatabasePrivilegeQuery;
|
|
47
|
-
},
|
|
48
|
-
get hasRolePrivilegesQuery () {
|
|
49
|
-
return hasRolePrivilegesQuery;
|
|
50
|
-
},
|
|
51
|
-
get hasSchemaPrivilegeQuery () {
|
|
52
|
-
return hasSchemaPrivilegeQuery;
|
|
53
|
-
},
|
|
54
|
-
get quoteIdent () {
|
|
55
|
-
return quoteIdent;
|
|
56
|
-
},
|
|
57
|
-
get quoteLiteral () {
|
|
58
|
-
return quoteLiteral;
|
|
59
|
-
},
|
|
60
|
-
get revokeRoleMembershipQuery () {
|
|
61
|
-
return revokeRoleMembershipQuery;
|
|
62
|
-
},
|
|
63
|
-
get roleExistsQuery () {
|
|
64
|
-
return roleExistsQuery;
|
|
65
|
-
},
|
|
66
|
-
get userScripts () {
|
|
67
|
-
return userScripts;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
/** Postgres identifier: letters, digits, underscore; must start with letter or underscore. */ const SAFE_IDENT = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
71
|
-
function assertSafeSqlIdent(value, label) {
|
|
72
|
-
if (typeof value !== "string" || value.length === 0 || !SAFE_IDENT.test(value)) {
|
|
73
|
-
throw new Error(`Invalid ${label}: must match ${SAFE_IDENT} (got ${JSON.stringify(value)})`);
|
|
74
|
-
}
|
|
75
|
-
return value;
|
|
76
|
-
}
|
|
77
|
-
function quoteIdent(value, label = "identifier") {
|
|
78
|
-
const safe = assertSafeSqlIdent(value, label);
|
|
79
|
-
return `"${safe.replaceAll('"', '""')}"`;
|
|
80
|
-
}
|
|
81
|
-
function quoteLiteral(value) {
|
|
82
|
-
return `'${value.replaceAll("'", "''")}'`;
|
|
83
|
-
}
|
|
84
|
-
function roleExistsQuery(username) {
|
|
85
|
-
assertSafeSqlIdent(username, "username");
|
|
86
|
-
return {
|
|
87
|
-
text: `SELECT 1 FROM pg_catalog.pg_roles WHERE rolname = $1`,
|
|
88
|
-
values: [
|
|
89
|
-
username
|
|
90
|
-
]
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function createUserQuery(username, password) {
|
|
94
|
-
const userIdent = quoteIdent(username, "username");
|
|
95
|
-
const attributes = "NOSUPERUSER NOBYPASSRLS NOCREATEDB NOCREATEROLE";
|
|
96
|
-
if (password === undefined) {
|
|
97
|
-
return {
|
|
98
|
-
text: `CREATE USER ${userIdent} WITH LOGIN ${attributes}`,
|
|
99
|
-
values: []
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
if (typeof password !== "string" || password.length === 0) {
|
|
103
|
-
throw new Error("Invalid password: must be a non-empty string");
|
|
104
|
-
}
|
|
105
|
-
const passwordLiteral = quoteLiteral(password);
|
|
106
|
-
return {
|
|
107
|
-
text: `CREATE USER ${userIdent} WITH LOGIN PASSWORD ${passwordLiteral} ${attributes}`,
|
|
108
|
-
values: []
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
function grantConnectQuery(username, database) {
|
|
112
|
-
const userIdent = quoteIdent(username, "username");
|
|
113
|
-
const dbIdent = quoteIdent(database, "database");
|
|
114
|
-
return {
|
|
115
|
-
text: `GRANT CONNECT ON DATABASE ${dbIdent} TO ${userIdent}`,
|
|
116
|
-
values: []
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
function grantSchemaUsageQuery(username, schema = "public") {
|
|
120
|
-
const userIdent = quoteIdent(username, "username");
|
|
121
|
-
const schemaIdent = quoteIdent(schema, "schema");
|
|
122
|
-
return {
|
|
123
|
-
text: `GRANT USAGE ON SCHEMA ${schemaIdent} TO ${userIdent}`,
|
|
124
|
-
values: []
|
|
125
|
-
};
|
|
126
|
-
}
|
|
127
|
-
function grantSchemaCreateQuery(username, schema = "public") {
|
|
128
|
-
const userIdent = quoteIdent(username, "username");
|
|
129
|
-
const schemaIdent = quoteIdent(schema, "schema");
|
|
130
|
-
return {
|
|
131
|
-
text: `GRANT CREATE ON SCHEMA ${schemaIdent} TO ${userIdent}`,
|
|
132
|
-
values: []
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
function createSchemaQuery(schema, owner) {
|
|
136
|
-
const schemaIdent = quoteIdent(schema, "schema");
|
|
137
|
-
const ownerIdent = quoteIdent(owner, "owner");
|
|
138
|
-
return {
|
|
139
|
-
text: `CREATE SCHEMA IF NOT EXISTS ${schemaIdent} AUTHORIZATION ${ownerIdent}`,
|
|
140
|
-
values: []
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
function hasDatabasePrivilegeQuery(username, database, privilege) {
|
|
144
|
-
assertSafeSqlIdent(username, "username");
|
|
145
|
-
assertSafeSqlIdent(database, "database");
|
|
146
|
-
return {
|
|
147
|
-
text: `SELECT has_database_privilege($1, $2, $3) AS granted`,
|
|
148
|
-
values: [
|
|
149
|
-
username,
|
|
150
|
-
database,
|
|
151
|
-
privilege
|
|
152
|
-
]
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function hasSchemaPrivilegeQuery(username, schema, privilege) {
|
|
156
|
-
assertSafeSqlIdent(username, "username");
|
|
157
|
-
assertSafeSqlIdent(schema, "schema");
|
|
158
|
-
return {
|
|
159
|
-
text: `SELECT has_schema_privilege($1, $2, $3) AS granted`,
|
|
160
|
-
values: [
|
|
161
|
-
username,
|
|
162
|
-
schema,
|
|
163
|
-
privilege
|
|
164
|
-
]
|
|
165
|
-
};
|
|
166
|
-
}
|
|
167
|
-
function hasRolePrivilegesQuery(member, role) {
|
|
168
|
-
assertSafeSqlIdent(member, "member");
|
|
169
|
-
assertSafeSqlIdent(role, "role");
|
|
170
|
-
return {
|
|
171
|
-
text: `SELECT pg_has_role($1, $2, 'USAGE') AS granted`,
|
|
172
|
-
values: [
|
|
173
|
-
member,
|
|
174
|
-
role
|
|
175
|
-
]
|
|
176
|
-
};
|
|
177
|
-
}
|
|
178
|
-
function databaseOwnerQuery(database) {
|
|
179
|
-
assertSafeSqlIdent(database, "database");
|
|
180
|
-
return {
|
|
181
|
-
text: `SELECT pg_get_userbyid(datdba) AS owner FROM pg_catalog.pg_database WHERE datname = $1`,
|
|
182
|
-
values: [
|
|
183
|
-
database
|
|
184
|
-
]
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
function grantSchemaPrivilegesQuery(username, schema = "public") {
|
|
188
|
-
const userIdent = quoteIdent(username, "username");
|
|
189
|
-
const schemaIdent = quoteIdent(schema, "schema");
|
|
190
|
-
return {
|
|
191
|
-
text: `GRANT ALL ON SCHEMA ${schemaIdent} TO ${userIdent}`,
|
|
192
|
-
values: []
|
|
193
|
-
};
|
|
194
|
-
}
|
|
195
|
-
function alterDatabaseOwnerQuery(database, username) {
|
|
196
|
-
const dbIdent = quoteIdent(database, "database");
|
|
197
|
-
const userIdent = quoteIdent(username, "username");
|
|
198
|
-
return {
|
|
199
|
-
text: `ALTER DATABASE ${dbIdent} OWNER TO ${userIdent}`,
|
|
200
|
-
values: []
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
function grantRoleMembershipQuery(member, role) {
|
|
204
|
-
const memberIdent = quoteIdent(member, "member");
|
|
205
|
-
const roleIdent = quoteIdent(role, "role");
|
|
206
|
-
return {
|
|
207
|
-
text: `GRANT ${roleIdent} TO ${memberIdent}`,
|
|
208
|
-
values: []
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
function revokeRoleMembershipQuery(member, role) {
|
|
212
|
-
const memberIdent = quoteIdent(member, "member");
|
|
213
|
-
const roleIdent = quoteIdent(role, "role");
|
|
214
|
-
return {
|
|
215
|
-
text: `REVOKE ${roleIdent} FROM ${memberIdent}`,
|
|
216
|
-
values: []
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
function defaultPrivilegesForAppQueries(migrateUsername, appUsername, schema = "public") {
|
|
220
|
-
const migrateIdent = quoteIdent(migrateUsername, "migrateUsername");
|
|
221
|
-
const appIdent = quoteIdent(appUsername, "username");
|
|
222
|
-
const schemaIdent = quoteIdent(schema, "schema");
|
|
223
|
-
return [
|
|
224
|
-
{
|
|
225
|
-
text: `ALTER DEFAULT PRIVILEGES FOR ROLE ${migrateIdent} IN SCHEMA ${schemaIdent} GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO ${appIdent}`,
|
|
226
|
-
values: []
|
|
227
|
-
},
|
|
228
|
-
{
|
|
229
|
-
text: `ALTER DEFAULT PRIVILEGES FOR ROLE ${migrateIdent} IN SCHEMA ${schemaIdent} GRANT USAGE, SELECT ON SEQUENCES TO ${appIdent}`,
|
|
230
|
-
values: []
|
|
231
|
-
}
|
|
232
|
-
];
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* @deprecated Prefer discrete query helpers + PostgresServerManager.provisionRoles.
|
|
236
|
-
* Kept for call-site / pen-test migration: emits create + CONNECT + USAGE (not ALL PRIVILEGES).
|
|
237
|
-
*/ const createOwnerUser = (username, password, database)=>{
|
|
238
|
-
quoteIdent(username, "username");
|
|
239
|
-
quoteIdent(database, "database");
|
|
240
|
-
if (typeof password !== "string" || password.length === 0) {
|
|
241
|
-
throw new Error("Invalid password: must be a non-empty string");
|
|
242
|
-
}
|
|
243
|
-
const create = createUserQuery(username, password);
|
|
244
|
-
const connect = grantConnectQuery(username, database);
|
|
245
|
-
const usage = grantSchemaUsageQuery(username);
|
|
246
|
-
return {
|
|
247
|
-
text: [
|
|
248
|
-
create.text,
|
|
249
|
-
connect.text,
|
|
250
|
-
usage.text
|
|
251
|
-
].join(";\n"),
|
|
252
|
-
values: []
|
|
253
|
-
};
|
|
254
|
-
};
|
|
255
|
-
const userExists = (username)=>roleExistsQuery(username);
|
|
256
|
-
const userScripts = {
|
|
257
|
-
createOwnerUser,
|
|
258
|
-
userExists
|
|
259
|
-
};
|