@pgpmjs/core 3.0.9 → 3.1.0
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/esm/index.js +1 -0
- package/esm/init/client.js +27 -79
- package/esm/roles/index.js +489 -0
- package/index.d.ts +1 -0
- package/index.js +1 -0
- package/init/client.d.ts +23 -8
- package/init/client.js +27 -79
- package/package.json +7 -7
- package/roles/index.d.ts +37 -0
- package/roles/index.js +497 -0
- package/esm/init/sql/bootstrap-roles.sql +0 -55
- package/esm/init/sql/bootstrap-test-roles.sql +0 -72
- package/init/sql/bootstrap-roles.sql +0 -55
- package/init/sql/bootstrap-test-roles.sql +0 -72
package/init/client.d.ts
CHANGED
|
@@ -1,24 +1,39 @@
|
|
|
1
|
+
import { RoleMapping, TestUserCredentials } from '@pgpmjs/types';
|
|
1
2
|
import { PgConfig } from 'pg-env';
|
|
2
3
|
export declare class PgpmInit {
|
|
3
4
|
private pool;
|
|
4
5
|
private pgConfig;
|
|
5
6
|
constructor(config: PgConfig);
|
|
6
7
|
/**
|
|
7
|
-
* Bootstrap standard roles (anonymous, authenticated, administrator)
|
|
8
|
+
* Bootstrap standard roles (anonymous, authenticated, administrator).
|
|
9
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
10
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
8
11
|
*/
|
|
9
|
-
bootstrapRoles(): Promise<void>;
|
|
12
|
+
bootstrapRoles(roles: RoleMapping): Promise<void>;
|
|
10
13
|
/**
|
|
11
|
-
* Bootstrap test roles (
|
|
14
|
+
* Bootstrap test roles (app_user, app_admin with grants to base roles).
|
|
15
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
16
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
17
|
+
* @param connections - Test user credentials from getConnEnvOptions().connections!
|
|
12
18
|
*/
|
|
13
|
-
bootstrapTestRoles(): Promise<void>;
|
|
19
|
+
bootstrapTestRoles(roles: RoleMapping, connections: TestUserCredentials): Promise<void>;
|
|
14
20
|
/**
|
|
15
|
-
* Bootstrap database roles with custom username and password
|
|
21
|
+
* Bootstrap database roles with custom username and password.
|
|
22
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
23
|
+
* @param username - The username to create
|
|
24
|
+
* @param password - The password for the user
|
|
25
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
26
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
16
27
|
*/
|
|
17
|
-
bootstrapDbRoles(username: string, password: string): Promise<void>;
|
|
28
|
+
bootstrapDbRoles(username: string, password: string, roles: RoleMapping, useLocksForRoles?: boolean): Promise<void>;
|
|
18
29
|
/**
|
|
19
|
-
* Remove database roles and revoke grants
|
|
30
|
+
* Remove database roles and revoke grants.
|
|
31
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
32
|
+
* @param username - The username to remove
|
|
33
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
34
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
20
35
|
*/
|
|
21
|
-
removeDbRoles(username: string): Promise<void>;
|
|
36
|
+
removeDbRoles(username: string, roles: RoleMapping, useLocksForRoles?: boolean): Promise<void>;
|
|
22
37
|
/**
|
|
23
38
|
* Close the database connection
|
|
24
39
|
*/
|
package/init/client.js
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PgpmInit = void 0;
|
|
4
4
|
const logger_1 = require("@pgpmjs/logger");
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
|
-
const path_1 = require("path");
|
|
7
5
|
const pg_cache_1 = require("pg-cache");
|
|
6
|
+
const roles_1 = require("../roles");
|
|
8
7
|
const log = new logger_1.Logger('init');
|
|
9
8
|
class PgpmInit {
|
|
10
9
|
pool;
|
|
@@ -14,13 +13,14 @@ class PgpmInit {
|
|
|
14
13
|
this.pool = (0, pg_cache_1.getPgPool)(this.pgConfig);
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
|
-
* Bootstrap standard roles (anonymous, authenticated, administrator)
|
|
16
|
+
* Bootstrap standard roles (anonymous, authenticated, administrator).
|
|
17
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
18
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
18
19
|
*/
|
|
19
|
-
async bootstrapRoles() {
|
|
20
|
+
async bootstrapRoles(roles) {
|
|
20
21
|
try {
|
|
21
22
|
log.info('Bootstrapping PGPM roles...');
|
|
22
|
-
const
|
|
23
|
-
const sql = (0, fs_1.readFileSync)(sqlPath, 'utf-8');
|
|
23
|
+
const sql = (0, roles_1.generateCreateBaseRolesSQL)(roles);
|
|
24
24
|
await this.pool.query(sql);
|
|
25
25
|
log.success('Successfully bootstrapped PGPM roles');
|
|
26
26
|
}
|
|
@@ -30,14 +30,16 @@ class PgpmInit {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
/**
|
|
33
|
-
* Bootstrap test roles (
|
|
33
|
+
* Bootstrap test roles (app_user, app_admin with grants to base roles).
|
|
34
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
35
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
36
|
+
* @param connections - Test user credentials from getConnEnvOptions().connections!
|
|
34
37
|
*/
|
|
35
|
-
async bootstrapTestRoles() {
|
|
38
|
+
async bootstrapTestRoles(roles, connections) {
|
|
36
39
|
try {
|
|
37
40
|
log.warn('WARNING: This command creates test roles and should NEVER be run on a production database!');
|
|
38
41
|
log.info('Bootstrapping PGPM test roles...');
|
|
39
|
-
const
|
|
40
|
-
const sql = (0, fs_1.readFileSync)(sqlPath, 'utf-8');
|
|
42
|
+
const sql = (0, roles_1.generateCreateTestUsersSQL)(roles, connections);
|
|
41
43
|
await this.pool.query(sql);
|
|
42
44
|
log.success('Successfully bootstrapped PGPM test roles');
|
|
43
45
|
}
|
|
@@ -47,58 +49,17 @@ class PgpmInit {
|
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
|
-
* Bootstrap database roles with custom username and password
|
|
52
|
+
* Bootstrap database roles with custom username and password.
|
|
53
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
54
|
+
* @param username - The username to create
|
|
55
|
+
* @param password - The password for the user
|
|
56
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
57
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
51
58
|
*/
|
|
52
|
-
async bootstrapDbRoles(username, password) {
|
|
59
|
+
async bootstrapDbRoles(username, password, roles, useLocksForRoles = false) {
|
|
53
60
|
try {
|
|
54
61
|
log.info(`Bootstrapping PGPM database roles for user: ${username}...`);
|
|
55
|
-
const sql =
|
|
56
|
-
BEGIN;
|
|
57
|
-
DO $do$
|
|
58
|
-
DECLARE
|
|
59
|
-
v_username TEXT := '${username.replace(/'/g, "''")}';
|
|
60
|
-
v_password TEXT := '${password.replace(/'/g, "''")}';
|
|
61
|
-
BEGIN
|
|
62
|
-
BEGIN
|
|
63
|
-
EXECUTE format('CREATE ROLE %I LOGIN PASSWORD %L', v_username, v_password);
|
|
64
|
-
EXCEPTION
|
|
65
|
-
WHEN duplicate_object THEN
|
|
66
|
-
-- Role already exists; optionally sync attributes here with ALTER ROLE
|
|
67
|
-
NULL;
|
|
68
|
-
END;
|
|
69
|
-
END
|
|
70
|
-
$do$;
|
|
71
|
-
|
|
72
|
-
-- Robust GRANTs under concurrency: GRANT can race on pg_auth_members unique index.
|
|
73
|
-
-- Catch unique_violation (23505) and continue so CI/CD concurrent jobs don't fail.
|
|
74
|
-
DO $do$
|
|
75
|
-
DECLARE
|
|
76
|
-
v_username TEXT := '${username.replace(/'/g, "''")}';
|
|
77
|
-
BEGIN
|
|
78
|
-
BEGIN
|
|
79
|
-
EXECUTE format('GRANT %I TO %I', 'anonymous', v_username);
|
|
80
|
-
EXCEPTION
|
|
81
|
-
WHEN unique_violation THEN
|
|
82
|
-
-- Membership was granted concurrently; ignore.
|
|
83
|
-
NULL;
|
|
84
|
-
WHEN undefined_object THEN
|
|
85
|
-
-- One of the roles doesn't exist yet; order operations as needed.
|
|
86
|
-
RAISE NOTICE 'Missing role when granting % to %', 'anonymous', v_username;
|
|
87
|
-
END;
|
|
88
|
-
|
|
89
|
-
BEGIN
|
|
90
|
-
EXECUTE format('GRANT %I TO %I', 'authenticated', v_username);
|
|
91
|
-
EXCEPTION
|
|
92
|
-
WHEN unique_violation THEN
|
|
93
|
-
-- Membership was granted concurrently; ignore.
|
|
94
|
-
NULL;
|
|
95
|
-
WHEN undefined_object THEN
|
|
96
|
-
RAISE NOTICE 'Missing role when granting % to %', 'authenticated', v_username;
|
|
97
|
-
END;
|
|
98
|
-
END
|
|
99
|
-
$do$;
|
|
100
|
-
COMMIT;
|
|
101
|
-
`;
|
|
62
|
+
const sql = (0, roles_1.generateCreateUserSQL)(username, password, roles, useLocksForRoles);
|
|
102
63
|
await this.pool.query(sql);
|
|
103
64
|
log.success(`Successfully bootstrapped PGPM database roles for user: ${username}`);
|
|
104
65
|
}
|
|
@@ -108,29 +69,16 @@ COMMIT;
|
|
|
108
69
|
}
|
|
109
70
|
}
|
|
110
71
|
/**
|
|
111
|
-
* Remove database roles and revoke grants
|
|
72
|
+
* Remove database roles and revoke grants.
|
|
73
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
74
|
+
* @param username - The username to remove
|
|
75
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
76
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
112
77
|
*/
|
|
113
|
-
async removeDbRoles(username) {
|
|
78
|
+
async removeDbRoles(username, roles, useLocksForRoles = false) {
|
|
114
79
|
try {
|
|
115
80
|
log.info(`Removing PGPM database roles for user: ${username}...`);
|
|
116
|
-
const sql =
|
|
117
|
-
BEGIN;
|
|
118
|
-
DO $do$
|
|
119
|
-
BEGIN
|
|
120
|
-
IF EXISTS (
|
|
121
|
-
SELECT 1
|
|
122
|
-
FROM
|
|
123
|
-
pg_catalog.pg_roles
|
|
124
|
-
WHERE
|
|
125
|
-
rolname = '${username}') THEN
|
|
126
|
-
REVOKE anonymous FROM ${username};
|
|
127
|
-
REVOKE authenticated FROM ${username};
|
|
128
|
-
DROP ROLE ${username};
|
|
129
|
-
END IF;
|
|
130
|
-
END
|
|
131
|
-
$do$;
|
|
132
|
-
COMMIT;
|
|
133
|
-
`;
|
|
81
|
+
const sql = (0, roles_1.generateRemoveUserSQL)(username, roles, useLocksForRoles);
|
|
134
82
|
await this.pool.query(sql);
|
|
135
83
|
log.success(`Successfully removed PGPM database roles for user: ${username}`);
|
|
136
84
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pgpmjs/core",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"author": "Constructive <developers@constructive.io>",
|
|
5
5
|
"description": "PGPM Package and Migration Tools",
|
|
6
6
|
"main": "index.js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"copy": "npm run copy:pkg; npm run copy:sql",
|
|
24
24
|
"copy:pkg": "makage assets",
|
|
25
|
-
"copy:sql": "copyfiles -f src/migrate/sql/* dist/migrate/sql && copyfiles -f src/migrate/sql/* dist/esm/migrate/sql
|
|
25
|
+
"copy:sql": "copyfiles -f src/migrate/sql/* dist/migrate/sql && copyfiles -f src/migrate/sql/* dist/esm/migrate/sql",
|
|
26
26
|
"clean": "makage clean",
|
|
27
27
|
"prepack": "npm run build",
|
|
28
28
|
"build": "makage build && npm run copy",
|
|
@@ -47,21 +47,21 @@
|
|
|
47
47
|
"makage": "^0.1.9"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@pgpmjs/env": "^2.8.
|
|
50
|
+
"@pgpmjs/env": "^2.8.6",
|
|
51
51
|
"@pgpmjs/logger": "^1.3.5",
|
|
52
|
-
"@pgpmjs/server-utils": "^2.8.
|
|
53
|
-
"@pgpmjs/types": "^2.12.
|
|
52
|
+
"@pgpmjs/server-utils": "^2.8.8",
|
|
53
|
+
"@pgpmjs/types": "^2.12.6",
|
|
54
54
|
"create-gen-app": "^0.6.0",
|
|
55
55
|
"csv-to-pg": "^2.0.10",
|
|
56
56
|
"glob": "^13.0.0",
|
|
57
57
|
"komoji": "^0.7.11",
|
|
58
58
|
"parse-package-name": "^1.0.0",
|
|
59
59
|
"pg": "^8.16.3",
|
|
60
|
-
"pg-cache": "^1.6.
|
|
60
|
+
"pg-cache": "^1.6.8",
|
|
61
61
|
"pg-env": "^1.2.4",
|
|
62
62
|
"pgsql-deparser": "^17.12.2",
|
|
63
63
|
"pgsql-parser": "^17.9.2",
|
|
64
64
|
"yanse": "^0.1.8"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "ac6c6b866ea6a578baf61208b22fcb12fdd46e5d"
|
|
67
67
|
}
|
package/roles/index.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { RoleMapping, TestUserCredentials } from '@pgpmjs/types';
|
|
2
|
+
/**
|
|
3
|
+
* Generate SQL to create base roles (anonymous, authenticated, administrator).
|
|
4
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
5
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateCreateBaseRolesSQL(roles: RoleMapping): string;
|
|
8
|
+
/**
|
|
9
|
+
* Generate SQL to create a user with password and grant base roles.
|
|
10
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
11
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
12
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
13
|
+
*/
|
|
14
|
+
export declare function generateCreateUserSQL(username: string, password: string, roles: RoleMapping, useLocksForRoles?: boolean): string;
|
|
15
|
+
/**
|
|
16
|
+
* Generate SQL to create test users with grants to base roles.
|
|
17
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
18
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
19
|
+
* @param connections - Test user credentials from getConnEnvOptions().connections!
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateCreateTestUsersSQL(roles: RoleMapping, connections: TestUserCredentials): string;
|
|
22
|
+
/**
|
|
23
|
+
* Generate SQL to grant a role to a user
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateGrantRoleSQL(role: string, user: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Generate SQL to remove a user and revoke grants.
|
|
28
|
+
* Callers should use getConnEnvOptions() from @pgpmjs/env to get merged values.
|
|
29
|
+
* @param roles - Role mapping from getConnEnvOptions().roles!
|
|
30
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateRemoveUserSQL(username: string, roles: RoleMapping, useLocksForRoles?: boolean): string;
|
|
33
|
+
/**
|
|
34
|
+
* Generate SQL to create a user with grants to specified roles (for test harness)
|
|
35
|
+
* @param useLocksForRoles - Whether to use advisory locks (from getConnEnvOptions().useLocksForRoles)
|
|
36
|
+
*/
|
|
37
|
+
export declare function generateCreateUserWithGrantsSQL(username: string, password: string, rolesToGrant: string[], useLocksForRoles?: boolean): string;
|