@rbacbee-lib/postgres 0.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/README.md +10 -0
- package/dist/index.cjs +264 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +235 -0
- package/dist/index.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# @rbacbee-lib/postgres
|
|
2
|
+
|
|
3
|
+
Postgres adapter for `@rbacbee-lib/core`.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import { createPostgresRbacStore } from '@rbacbee-lib/postgres';
|
|
7
|
+
|
|
8
|
+
const store = createPostgresRbacStore({ connectionString: process.env.DATABASE_URL });
|
|
9
|
+
await store.migrate();
|
|
10
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
POSTGRES_RBAC_SCHEMA: () => POSTGRES_RBAC_SCHEMA,
|
|
24
|
+
PostgresRbacStore: () => PostgresRbacStore,
|
|
25
|
+
createPostgresRbacStore: () => createPostgresRbacStore
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(index_exports);
|
|
28
|
+
|
|
29
|
+
// src/postgres-rbac-schema.ts
|
|
30
|
+
var POSTGRES_RBAC_SCHEMA = `
|
|
31
|
+
CREATE TABLE IF NOT EXISTS rbac_permissions (
|
|
32
|
+
key text PRIMARY KEY,
|
|
33
|
+
description text NULL,
|
|
34
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
35
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
36
|
+
CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),
|
|
37
|
+
CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
CREATE TABLE IF NOT EXISTS rbac_roles (
|
|
41
|
+
id text PRIMARY KEY,
|
|
42
|
+
name text NOT NULL,
|
|
43
|
+
tenant_id text NULL,
|
|
44
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
45
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
46
|
+
CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),
|
|
47
|
+
CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
CREATE TABLE IF NOT EXISTS rbac_role_permissions (
|
|
51
|
+
role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,
|
|
52
|
+
permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,
|
|
53
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
54
|
+
PRIMARY KEY (role_id, permission_key)
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
CREATE TABLE IF NOT EXISTS rbac_user_roles (
|
|
58
|
+
id bigserial PRIMARY KEY,
|
|
59
|
+
user_id text NOT NULL,
|
|
60
|
+
role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,
|
|
61
|
+
tenant_id text NULL,
|
|
62
|
+
resource_type text NULL,
|
|
63
|
+
resource_id text NULL,
|
|
64
|
+
expires_at timestamptz NULL,
|
|
65
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
66
|
+
CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant
|
|
70
|
+
ON rbac_user_roles (user_id, tenant_id);
|
|
71
|
+
|
|
72
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role
|
|
73
|
+
ON rbac_user_roles (role_id);
|
|
74
|
+
|
|
75
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource
|
|
76
|
+
ON rbac_user_roles (resource_type, resource_id);
|
|
77
|
+
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission
|
|
79
|
+
ON rbac_role_permissions (permission_key);
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
// src/postgres-rbac-store.ts
|
|
83
|
+
var import_pg = require("pg");
|
|
84
|
+
var PostgresRbacStore = class {
|
|
85
|
+
constructor(pool, ownsPool = false) {
|
|
86
|
+
this.pool = pool;
|
|
87
|
+
this.ownsPool = ownsPool;
|
|
88
|
+
}
|
|
89
|
+
pool;
|
|
90
|
+
ownsPool;
|
|
91
|
+
async migrate() {
|
|
92
|
+
await this.pool.query(POSTGRES_RBAC_SCHEMA);
|
|
93
|
+
}
|
|
94
|
+
async close() {
|
|
95
|
+
if (this.ownsPool) {
|
|
96
|
+
await this.pool.end();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async getAccessProfile(query) {
|
|
100
|
+
const tenantId = query.tenantId ?? null;
|
|
101
|
+
const [rolesResult, permissionsResult] = await Promise.all([
|
|
102
|
+
this.pool.query(
|
|
103
|
+
`
|
|
104
|
+
SELECT r.id, r.name, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at
|
|
105
|
+
FROM rbac_user_roles ur
|
|
106
|
+
INNER JOIN rbac_roles r ON r.id = ur.role_id
|
|
107
|
+
WHERE ur.user_id = $1
|
|
108
|
+
AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)
|
|
109
|
+
AND (ur.expires_at IS NULL OR ur.expires_at > now())
|
|
110
|
+
`,
|
|
111
|
+
[query.userId, tenantId]
|
|
112
|
+
),
|
|
113
|
+
this.pool.query(
|
|
114
|
+
`
|
|
115
|
+
SELECT p.key, ur.role_id, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at
|
|
116
|
+
FROM rbac_user_roles ur
|
|
117
|
+
INNER JOIN rbac_role_permissions rp ON rp.role_id = ur.role_id
|
|
118
|
+
INNER JOIN rbac_permissions p ON p.key = rp.permission_key
|
|
119
|
+
WHERE ur.user_id = $1
|
|
120
|
+
AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)
|
|
121
|
+
AND (ur.expires_at IS NULL OR ur.expires_at > now())
|
|
122
|
+
`,
|
|
123
|
+
[query.userId, tenantId]
|
|
124
|
+
)
|
|
125
|
+
]);
|
|
126
|
+
if (rolesResult.rowCount === 0 && permissionsResult.rowCount === 0) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
const profile = {
|
|
130
|
+
userId: query.userId,
|
|
131
|
+
...query.tenantId === void 0 ? {} : { tenantId: query.tenantId },
|
|
132
|
+
loadedAt: /* @__PURE__ */ new Date(),
|
|
133
|
+
roles: rolesResult.rows.map(mapRole),
|
|
134
|
+
permissions: permissionsResult.rows.map(mapPermission)
|
|
135
|
+
};
|
|
136
|
+
return profile;
|
|
137
|
+
}
|
|
138
|
+
async upsertPermission(permission) {
|
|
139
|
+
await this.pool.query(
|
|
140
|
+
`
|
|
141
|
+
INSERT INTO rbac_permissions (key, description)
|
|
142
|
+
VALUES ($1, $2)
|
|
143
|
+
ON CONFLICT (key) DO UPDATE
|
|
144
|
+
SET description = EXCLUDED.description,
|
|
145
|
+
updated_at = now()
|
|
146
|
+
`,
|
|
147
|
+
[permission.key, permission.description ?? null]
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
async deletePermission(permissionKey) {
|
|
151
|
+
await this.pool.query("DELETE FROM rbac_permissions WHERE key = $1", [permissionKey]);
|
|
152
|
+
}
|
|
153
|
+
async createRole(role) {
|
|
154
|
+
await this.pool.query(
|
|
155
|
+
`
|
|
156
|
+
INSERT INTO rbac_roles (id, name, tenant_id)
|
|
157
|
+
VALUES ($1, $2, $3)
|
|
158
|
+
ON CONFLICT (id) DO UPDATE
|
|
159
|
+
SET name = EXCLUDED.name,
|
|
160
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
161
|
+
updated_at = now()
|
|
162
|
+
`,
|
|
163
|
+
[role.id, role.name, role.tenantId ?? null]
|
|
164
|
+
);
|
|
165
|
+
for (const permission of role.permissions ?? []) {
|
|
166
|
+
await this.upsertPermission({ key: permission });
|
|
167
|
+
await this.grantPermissionToRole(role.id, permission);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
async deleteRole(roleId) {
|
|
171
|
+
await this.pool.query("DELETE FROM rbac_roles WHERE id = $1", [roleId]);
|
|
172
|
+
}
|
|
173
|
+
async grantPermissionToRole(roleId, permissionKey) {
|
|
174
|
+
await this.pool.query(
|
|
175
|
+
`
|
|
176
|
+
INSERT INTO rbac_role_permissions (role_id, permission_key)
|
|
177
|
+
VALUES ($1, $2)
|
|
178
|
+
ON CONFLICT (role_id, permission_key) DO NOTHING
|
|
179
|
+
`,
|
|
180
|
+
[roleId, permissionKey]
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
async revokePermissionFromRole(roleId, permissionKey) {
|
|
184
|
+
await this.pool.query(
|
|
185
|
+
"DELETE FROM rbac_role_permissions WHERE role_id = $1 AND permission_key = $2",
|
|
186
|
+
[roleId, permissionKey]
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
async assignRole(assignment) {
|
|
190
|
+
await this.pool.query(
|
|
191
|
+
`
|
|
192
|
+
INSERT INTO rbac_user_roles (
|
|
193
|
+
user_id,
|
|
194
|
+
role_id,
|
|
195
|
+
tenant_id,
|
|
196
|
+
resource_type,
|
|
197
|
+
resource_id,
|
|
198
|
+
expires_at
|
|
199
|
+
)
|
|
200
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
201
|
+
`,
|
|
202
|
+
[
|
|
203
|
+
assignment.userId,
|
|
204
|
+
assignment.roleId,
|
|
205
|
+
assignment.tenantId ?? null,
|
|
206
|
+
assignment.resourceType ?? null,
|
|
207
|
+
assignment.resourceId ?? null,
|
|
208
|
+
assignment.expiresAt ?? null
|
|
209
|
+
]
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
async revokeRole(revocation) {
|
|
213
|
+
await this.pool.query(
|
|
214
|
+
`
|
|
215
|
+
DELETE FROM rbac_user_roles
|
|
216
|
+
WHERE user_id = $1
|
|
217
|
+
AND role_id = $2
|
|
218
|
+
AND ($3::text IS NULL OR tenant_id = $3)
|
|
219
|
+
AND ($4::text IS NULL OR resource_type = $4)
|
|
220
|
+
AND ($5::text IS NULL OR resource_id = $5)
|
|
221
|
+
`,
|
|
222
|
+
[
|
|
223
|
+
revocation.userId,
|
|
224
|
+
revocation.roleId,
|
|
225
|
+
revocation.tenantId ?? null,
|
|
226
|
+
revocation.resourceType ?? null,
|
|
227
|
+
revocation.resourceId ?? null
|
|
228
|
+
]
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
function createPostgresRbacStore(options) {
|
|
233
|
+
if (options.pool !== void 0) {
|
|
234
|
+
return new PostgresRbacStore(options.pool);
|
|
235
|
+
}
|
|
236
|
+
return new PostgresRbacStore(new import_pg.Pool(options), true);
|
|
237
|
+
}
|
|
238
|
+
function mapRole(row) {
|
|
239
|
+
return {
|
|
240
|
+
id: row.id,
|
|
241
|
+
name: row.name,
|
|
242
|
+
...row.tenant_id === null ? {} : { tenantId: row.tenant_id },
|
|
243
|
+
...row.resource_type === null ? {} : { resourceType: row.resource_type },
|
|
244
|
+
...row.resource_id === null ? {} : { resourceId: row.resource_id },
|
|
245
|
+
...row.expires_at === null ? {} : { expiresAt: row.expires_at }
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function mapPermission(row) {
|
|
249
|
+
return {
|
|
250
|
+
key: row.key,
|
|
251
|
+
sourceRoleId: row.role_id,
|
|
252
|
+
...row.tenant_id === null ? {} : { tenantId: row.tenant_id },
|
|
253
|
+
...row.resource_type === null ? {} : { resourceType: row.resource_type },
|
|
254
|
+
...row.resource_id === null ? {} : { resourceId: row.resource_id },
|
|
255
|
+
...row.expires_at === null ? {} : { expiresAt: row.expires_at }
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
259
|
+
0 && (module.exports = {
|
|
260
|
+
POSTGRES_RBAC_SCHEMA,
|
|
261
|
+
PostgresRbacStore,
|
|
262
|
+
createPostgresRbacStore
|
|
263
|
+
});
|
|
264
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/postgres-rbac-schema.ts","../src/postgres-rbac-store.ts"],"sourcesContent":["export * from './postgres-rbac-schema';\nexport * from './postgres-rbac-store';\n","export const POSTGRES_RBAC_SCHEMA = `\nCREATE TABLE IF NOT EXISTS rbac_permissions (\n key text PRIMARY KEY,\n description text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),\n CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')\n);\n\nCREATE TABLE IF NOT EXISTS rbac_roles (\n id text PRIMARY KEY,\n name text NOT NULL,\n tenant_id text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),\n CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_role_permissions (\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY (role_id, permission_key)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_user_roles (\n id bigserial PRIMARY KEY,\n user_id text NOT NULL,\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n tenant_id text NULL,\n resource_type text NULL,\n resource_id text NULL,\n expires_at timestamptz NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)\n);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant\n ON rbac_user_roles (user_id, tenant_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role\n ON rbac_user_roles (role_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource\n ON rbac_user_roles (resource_type, resource_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission\n ON rbac_role_permissions (permission_key);\n`;\n","import { Pool, type PoolConfig } from 'pg';\nimport type {\n AccessPermission,\n AccessProfile,\n AccessProfileQuery,\n AccessRepository,\n AccessRole,\n AssignmentRepository,\n PermissionDefinition,\n PermissionRepository,\n RoleAssignment,\n RoleAssignmentRevocation,\n RoleDefinition,\n RoleRepository\n} from '@rbacbee-lib/core';\nimport { POSTGRES_RBAC_SCHEMA } from './postgres-rbac-schema';\n\nexport interface PostgresRbacStoreOptions extends PoolConfig {\n readonly pool?: Pool;\n}\n\ninterface RoleRow {\n readonly id: string;\n readonly name: string;\n readonly tenant_id: string | null;\n readonly resource_type: string | null;\n readonly resource_id: string | null;\n readonly expires_at: Date | null;\n}\n\ninterface PermissionRow {\n readonly key: string;\n readonly role_id: string;\n readonly tenant_id: string | null;\n readonly resource_type: string | null;\n readonly resource_id: string | null;\n readonly expires_at: Date | null;\n}\n\nexport class PostgresRbacStore\n implements AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository\n{\n private readonly ownsPool: boolean;\n\n public constructor(\n private readonly pool: Pool,\n ownsPool = false\n ) {\n this.ownsPool = ownsPool;\n }\n\n public async migrate(): Promise<void> {\n await this.pool.query(POSTGRES_RBAC_SCHEMA);\n }\n\n public async close(): Promise<void> {\n if (this.ownsPool) {\n await this.pool.end();\n }\n }\n\n public async getAccessProfile(query: AccessProfileQuery): Promise<AccessProfile | null> {\n const tenantId = query.tenantId ?? null;\n const [rolesResult, permissionsResult] = await Promise.all([\n this.pool.query<RoleRow>(\n `\n SELECT r.id, r.name, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at\n FROM rbac_user_roles ur\n INNER JOIN rbac_roles r ON r.id = ur.role_id\n WHERE ur.user_id = $1\n AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)\n AND (ur.expires_at IS NULL OR ur.expires_at > now())\n `,\n [query.userId, tenantId]\n ),\n this.pool.query<PermissionRow>(\n `\n SELECT p.key, ur.role_id, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at\n FROM rbac_user_roles ur\n INNER JOIN rbac_role_permissions rp ON rp.role_id = ur.role_id\n INNER JOIN rbac_permissions p ON p.key = rp.permission_key\n WHERE ur.user_id = $1\n AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)\n AND (ur.expires_at IS NULL OR ur.expires_at > now())\n `,\n [query.userId, tenantId]\n )\n ]);\n\n if (rolesResult.rowCount === 0 && permissionsResult.rowCount === 0) {\n return null;\n }\n\n const profile: AccessProfile = {\n userId: query.userId,\n ...(query.tenantId === undefined ? {} : { tenantId: query.tenantId }),\n loadedAt: new Date(),\n roles: rolesResult.rows.map(mapRole),\n permissions: permissionsResult.rows.map(mapPermission)\n };\n\n return profile;\n }\n\n public async upsertPermission(permission: PermissionDefinition): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_permissions (key, description)\n VALUES ($1, $2)\n ON CONFLICT (key) DO UPDATE\n SET description = EXCLUDED.description,\n updated_at = now()\n `,\n [permission.key, permission.description ?? null]\n );\n }\n\n public async deletePermission(permissionKey: string): Promise<void> {\n await this.pool.query('DELETE FROM rbac_permissions WHERE key = $1', [permissionKey]);\n }\n\n public async createRole(role: RoleDefinition): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_roles (id, name, tenant_id)\n VALUES ($1, $2, $3)\n ON CONFLICT (id) DO UPDATE\n SET name = EXCLUDED.name,\n tenant_id = EXCLUDED.tenant_id,\n updated_at = now()\n `,\n [role.id, role.name, role.tenantId ?? null]\n );\n\n for (const permission of role.permissions ?? []) {\n await this.upsertPermission({ key: permission });\n await this.grantPermissionToRole(role.id, permission);\n }\n }\n\n public async deleteRole(roleId: string): Promise<void> {\n await this.pool.query('DELETE FROM rbac_roles WHERE id = $1', [roleId]);\n }\n\n public async grantPermissionToRole(roleId: string, permissionKey: string): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_role_permissions (role_id, permission_key)\n VALUES ($1, $2)\n ON CONFLICT (role_id, permission_key) DO NOTHING\n `,\n [roleId, permissionKey]\n );\n }\n\n public async revokePermissionFromRole(roleId: string, permissionKey: string): Promise<void> {\n await this.pool.query(\n 'DELETE FROM rbac_role_permissions WHERE role_id = $1 AND permission_key = $2',\n [roleId, permissionKey]\n );\n }\n\n public async assignRole(assignment: RoleAssignment): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_user_roles (\n user_id,\n role_id,\n tenant_id,\n resource_type,\n resource_id,\n expires_at\n )\n VALUES ($1, $2, $3, $4, $5, $6)\n `,\n [\n assignment.userId,\n assignment.roleId,\n assignment.tenantId ?? null,\n assignment.resourceType ?? null,\n assignment.resourceId ?? null,\n assignment.expiresAt ?? null\n ]\n );\n }\n\n public async revokeRole(revocation: RoleAssignmentRevocation): Promise<void> {\n await this.pool.query(\n `\n DELETE FROM rbac_user_roles\n WHERE user_id = $1\n AND role_id = $2\n AND ($3::text IS NULL OR tenant_id = $3)\n AND ($4::text IS NULL OR resource_type = $4)\n AND ($5::text IS NULL OR resource_id = $5)\n `,\n [\n revocation.userId,\n revocation.roleId,\n revocation.tenantId ?? null,\n revocation.resourceType ?? null,\n revocation.resourceId ?? null\n ]\n );\n }\n}\n\nexport function createPostgresRbacStore(options: PostgresRbacStoreOptions): PostgresRbacStore {\n if (options.pool !== undefined) {\n return new PostgresRbacStore(options.pool);\n }\n\n return new PostgresRbacStore(new Pool(options), true);\n}\n\nfunction mapRole(row: RoleRow): AccessRole {\n return {\n id: row.id,\n name: row.name,\n ...(row.tenant_id === null ? {} : { tenantId: row.tenant_id }),\n ...(row.resource_type === null ? {} : { resourceType: row.resource_type }),\n ...(row.resource_id === null ? {} : { resourceId: row.resource_id }),\n ...(row.expires_at === null ? {} : { expiresAt: row.expires_at })\n };\n}\n\nfunction mapPermission(row: PermissionRow): AccessPermission {\n return {\n key: row.key,\n sourceRoleId: row.role_id,\n ...(row.tenant_id === null ? {} : { tenantId: row.tenant_id }),\n ...(row.resource_type === null ? {} : { resourceType: row.resource_type }),\n ...(row.resource_id === null ? {} : { resourceId: row.resource_id }),\n ...(row.expires_at === null ? {} : { expiresAt: row.expires_at })\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACApC,gBAAsC;AAuC/B,IAAM,oBAAN,MAEP;AAAA,EAGS,YACY,MACjB,WAAW,OACX;AAFiB;AAGjB,SAAK,WAAW;AAAA,EAClB;AAAA,EAJmB;AAAA,EAHF;AAAA,EASjB,MAAa,UAAyB;AACpC,UAAM,KAAK,KAAK,MAAM,oBAAoB;AAAA,EAC5C;AAAA,EAEA,MAAa,QAAuB;AAClC,QAAI,KAAK,UAAU;AACjB,YAAM,KAAK,KAAK,IAAI;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,MAAa,iBAAiB,OAA0D;AACtF,UAAM,WAAW,MAAM,YAAY;AACnC,UAAM,CAAC,aAAa,iBAAiB,IAAI,MAAM,QAAQ,IAAI;AAAA,MACzD,KAAK,KAAK;AAAA,QACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAQA,CAAC,MAAM,QAAQ,QAAQ;AAAA,MACzB;AAAA,MACA,KAAK,KAAK;AAAA,QACR;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QASA,CAAC,MAAM,QAAQ,QAAQ;AAAA,MACzB;AAAA,IACF,CAAC;AAED,QAAI,YAAY,aAAa,KAAK,kBAAkB,aAAa,GAAG;AAClE,aAAO;AAAA,IACT;AAEA,UAAM,UAAyB;AAAA,MAC7B,QAAQ,MAAM;AAAA,MACd,GAAI,MAAM,aAAa,SAAY,CAAC,IAAI,EAAE,UAAU,MAAM,SAAS;AAAA,MACnE,UAAU,oBAAI,KAAK;AAAA,MACnB,OAAO,YAAY,KAAK,IAAI,OAAO;AAAA,MACnC,aAAa,kBAAkB,KAAK,IAAI,aAAa;AAAA,IACvD;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAa,iBAAiB,YAAiD;AAC7E,UAAM,KAAK,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,CAAC,WAAW,KAAK,WAAW,eAAe,IAAI;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,MAAa,iBAAiB,eAAsC;AAClE,UAAM,KAAK,KAAK,MAAM,+CAA+C,CAAC,aAAa,CAAC;AAAA,EACtF;AAAA,EAEA,MAAa,WAAW,MAAqC;AAC3D,UAAM,KAAK,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA,CAAC,KAAK,IAAI,KAAK,MAAM,KAAK,YAAY,IAAI;AAAA,IAC5C;AAEA,eAAW,cAAc,KAAK,eAAe,CAAC,GAAG;AAC/C,YAAM,KAAK,iBAAiB,EAAE,KAAK,WAAW,CAAC;AAC/C,YAAM,KAAK,sBAAsB,KAAK,IAAI,UAAU;AAAA,IACtD;AAAA,EACF;AAAA,EAEA,MAAa,WAAW,QAA+B;AACrD,UAAM,KAAK,KAAK,MAAM,wCAAwC,CAAC,MAAM,CAAC;AAAA,EACxE;AAAA,EAEA,MAAa,sBAAsB,QAAgB,eAAsC;AACvF,UAAM,KAAK,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA,MAKA,CAAC,QAAQ,aAAa;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAa,yBAAyB,QAAgB,eAAsC;AAC1F,UAAM,KAAK,KAAK;AAAA,MACd;AAAA,MACA,CAAC,QAAQ,aAAa;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,MAAa,WAAW,YAA2C;AACjE,UAAM,KAAK,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWA;AAAA,QACE,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW,YAAY;AAAA,QACvB,WAAW,gBAAgB;AAAA,QAC3B,WAAW,cAAc;AAAA,QACzB,WAAW,aAAa;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,WAAW,YAAqD;AAC3E,UAAM,KAAK,KAAK;AAAA,MACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAQA;AAAA,QACE,WAAW;AAAA,QACX,WAAW;AAAA,QACX,WAAW,YAAY;AAAA,QACvB,WAAW,gBAAgB;AAAA,QAC3B,WAAW,cAAc;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,wBAAwB,SAAsD;AAC5F,MAAI,QAAQ,SAAS,QAAW;AAC9B,WAAO,IAAI,kBAAkB,QAAQ,IAAI;AAAA,EAC3C;AAEA,SAAO,IAAI,kBAAkB,IAAI,eAAK,OAAO,GAAG,IAAI;AACtD;AAEA,SAAS,QAAQ,KAA0B;AACzC,SAAO;AAAA,IACL,IAAI,IAAI;AAAA,IACR,MAAM,IAAI;AAAA,IACV,GAAI,IAAI,cAAc,OAAO,CAAC,IAAI,EAAE,UAAU,IAAI,UAAU;AAAA,IAC5D,GAAI,IAAI,kBAAkB,OAAO,CAAC,IAAI,EAAE,cAAc,IAAI,cAAc;AAAA,IACxE,GAAI,IAAI,gBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,IAAI,YAAY;AAAA,IAClE,GAAI,IAAI,eAAe,OAAO,CAAC,IAAI,EAAE,WAAW,IAAI,WAAW;AAAA,EACjE;AACF;AAEA,SAAS,cAAc,KAAsC;AAC3D,SAAO;AAAA,IACL,KAAK,IAAI;AAAA,IACT,cAAc,IAAI;AAAA,IAClB,GAAI,IAAI,cAAc,OAAO,CAAC,IAAI,EAAE,UAAU,IAAI,UAAU;AAAA,IAC5D,GAAI,IAAI,kBAAkB,OAAO,CAAC,IAAI,EAAE,cAAc,IAAI,cAAc;AAAA,IACxE,GAAI,IAAI,gBAAgB,OAAO,CAAC,IAAI,EAAE,YAAY,IAAI,YAAY;AAAA,IAClE,GAAI,IAAI,eAAe,OAAO,CAAC,IAAI,EAAE,WAAW,IAAI,WAAW;AAAA,EACjE;AACF;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Pool, PoolConfig } from 'pg';
|
|
2
|
+
import { AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository, AccessProfileQuery, AccessProfile, PermissionDefinition, RoleDefinition, RoleAssignment, RoleAssignmentRevocation } from '@rbacbee-lib/core';
|
|
3
|
+
|
|
4
|
+
declare const POSTGRES_RBAC_SCHEMA = "\nCREATE TABLE IF NOT EXISTS rbac_permissions (\n key text PRIMARY KEY,\n description text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),\n CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')\n);\n\nCREATE TABLE IF NOT EXISTS rbac_roles (\n id text PRIMARY KEY,\n name text NOT NULL,\n tenant_id text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),\n CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_role_permissions (\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY (role_id, permission_key)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_user_roles (\n id bigserial PRIMARY KEY,\n user_id text NOT NULL,\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n tenant_id text NULL,\n resource_type text NULL,\n resource_id text NULL,\n expires_at timestamptz NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)\n);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant\n ON rbac_user_roles (user_id, tenant_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role\n ON rbac_user_roles (role_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource\n ON rbac_user_roles (resource_type, resource_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission\n ON rbac_role_permissions (permission_key);\n";
|
|
5
|
+
|
|
6
|
+
interface PostgresRbacStoreOptions extends PoolConfig {
|
|
7
|
+
readonly pool?: Pool;
|
|
8
|
+
}
|
|
9
|
+
declare class PostgresRbacStore implements AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository {
|
|
10
|
+
private readonly pool;
|
|
11
|
+
private readonly ownsPool;
|
|
12
|
+
constructor(pool: Pool, ownsPool?: boolean);
|
|
13
|
+
migrate(): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
getAccessProfile(query: AccessProfileQuery): Promise<AccessProfile | null>;
|
|
16
|
+
upsertPermission(permission: PermissionDefinition): Promise<void>;
|
|
17
|
+
deletePermission(permissionKey: string): Promise<void>;
|
|
18
|
+
createRole(role: RoleDefinition): Promise<void>;
|
|
19
|
+
deleteRole(roleId: string): Promise<void>;
|
|
20
|
+
grantPermissionToRole(roleId: string, permissionKey: string): Promise<void>;
|
|
21
|
+
revokePermissionFromRole(roleId: string, permissionKey: string): Promise<void>;
|
|
22
|
+
assignRole(assignment: RoleAssignment): Promise<void>;
|
|
23
|
+
revokeRole(revocation: RoleAssignmentRevocation): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
declare function createPostgresRbacStore(options: PostgresRbacStoreOptions): PostgresRbacStore;
|
|
26
|
+
|
|
27
|
+
export { POSTGRES_RBAC_SCHEMA, PostgresRbacStore, type PostgresRbacStoreOptions, createPostgresRbacStore };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Pool, PoolConfig } from 'pg';
|
|
2
|
+
import { AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository, AccessProfileQuery, AccessProfile, PermissionDefinition, RoleDefinition, RoleAssignment, RoleAssignmentRevocation } from '@rbacbee-lib/core';
|
|
3
|
+
|
|
4
|
+
declare const POSTGRES_RBAC_SCHEMA = "\nCREATE TABLE IF NOT EXISTS rbac_permissions (\n key text PRIMARY KEY,\n description text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),\n CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')\n);\n\nCREATE TABLE IF NOT EXISTS rbac_roles (\n id text PRIMARY KEY,\n name text NOT NULL,\n tenant_id text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),\n CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_role_permissions (\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY (role_id, permission_key)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_user_roles (\n id bigserial PRIMARY KEY,\n user_id text NOT NULL,\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n tenant_id text NULL,\n resource_type text NULL,\n resource_id text NULL,\n expires_at timestamptz NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)\n);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant\n ON rbac_user_roles (user_id, tenant_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role\n ON rbac_user_roles (role_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource\n ON rbac_user_roles (resource_type, resource_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission\n ON rbac_role_permissions (permission_key);\n";
|
|
5
|
+
|
|
6
|
+
interface PostgresRbacStoreOptions extends PoolConfig {
|
|
7
|
+
readonly pool?: Pool;
|
|
8
|
+
}
|
|
9
|
+
declare class PostgresRbacStore implements AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository {
|
|
10
|
+
private readonly pool;
|
|
11
|
+
private readonly ownsPool;
|
|
12
|
+
constructor(pool: Pool, ownsPool?: boolean);
|
|
13
|
+
migrate(): Promise<void>;
|
|
14
|
+
close(): Promise<void>;
|
|
15
|
+
getAccessProfile(query: AccessProfileQuery): Promise<AccessProfile | null>;
|
|
16
|
+
upsertPermission(permission: PermissionDefinition): Promise<void>;
|
|
17
|
+
deletePermission(permissionKey: string): Promise<void>;
|
|
18
|
+
createRole(role: RoleDefinition): Promise<void>;
|
|
19
|
+
deleteRole(roleId: string): Promise<void>;
|
|
20
|
+
grantPermissionToRole(roleId: string, permissionKey: string): Promise<void>;
|
|
21
|
+
revokePermissionFromRole(roleId: string, permissionKey: string): Promise<void>;
|
|
22
|
+
assignRole(assignment: RoleAssignment): Promise<void>;
|
|
23
|
+
revokeRole(revocation: RoleAssignmentRevocation): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
declare function createPostgresRbacStore(options: PostgresRbacStoreOptions): PostgresRbacStore;
|
|
26
|
+
|
|
27
|
+
export { POSTGRES_RBAC_SCHEMA, PostgresRbacStore, type PostgresRbacStoreOptions, createPostgresRbacStore };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// src/postgres-rbac-schema.ts
|
|
2
|
+
var POSTGRES_RBAC_SCHEMA = `
|
|
3
|
+
CREATE TABLE IF NOT EXISTS rbac_permissions (
|
|
4
|
+
key text PRIMARY KEY,
|
|
5
|
+
description text NULL,
|
|
6
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
7
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
8
|
+
CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),
|
|
9
|
+
CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')
|
|
10
|
+
);
|
|
11
|
+
|
|
12
|
+
CREATE TABLE IF NOT EXISTS rbac_roles (
|
|
13
|
+
id text PRIMARY KEY,
|
|
14
|
+
name text NOT NULL,
|
|
15
|
+
tenant_id text NULL,
|
|
16
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
17
|
+
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
18
|
+
CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),
|
|
19
|
+
CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE TABLE IF NOT EXISTS rbac_role_permissions (
|
|
23
|
+
role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,
|
|
24
|
+
permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,
|
|
25
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
26
|
+
PRIMARY KEY (role_id, permission_key)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
CREATE TABLE IF NOT EXISTS rbac_user_roles (
|
|
30
|
+
id bigserial PRIMARY KEY,
|
|
31
|
+
user_id text NOT NULL,
|
|
32
|
+
role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,
|
|
33
|
+
tenant_id text NULL,
|
|
34
|
+
resource_type text NULL,
|
|
35
|
+
resource_id text NULL,
|
|
36
|
+
expires_at timestamptz NULL,
|
|
37
|
+
created_at timestamptz NOT NULL DEFAULT now(),
|
|
38
|
+
CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant
|
|
42
|
+
ON rbac_user_roles (user_id, tenant_id);
|
|
43
|
+
|
|
44
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role
|
|
45
|
+
ON rbac_user_roles (role_id);
|
|
46
|
+
|
|
47
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource
|
|
48
|
+
ON rbac_user_roles (resource_type, resource_id);
|
|
49
|
+
|
|
50
|
+
CREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission
|
|
51
|
+
ON rbac_role_permissions (permission_key);
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
// src/postgres-rbac-store.ts
|
|
55
|
+
import { Pool } from "pg";
|
|
56
|
+
var PostgresRbacStore = class {
|
|
57
|
+
constructor(pool, ownsPool = false) {
|
|
58
|
+
this.pool = pool;
|
|
59
|
+
this.ownsPool = ownsPool;
|
|
60
|
+
}
|
|
61
|
+
pool;
|
|
62
|
+
ownsPool;
|
|
63
|
+
async migrate() {
|
|
64
|
+
await this.pool.query(POSTGRES_RBAC_SCHEMA);
|
|
65
|
+
}
|
|
66
|
+
async close() {
|
|
67
|
+
if (this.ownsPool) {
|
|
68
|
+
await this.pool.end();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async getAccessProfile(query) {
|
|
72
|
+
const tenantId = query.tenantId ?? null;
|
|
73
|
+
const [rolesResult, permissionsResult] = await Promise.all([
|
|
74
|
+
this.pool.query(
|
|
75
|
+
`
|
|
76
|
+
SELECT r.id, r.name, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at
|
|
77
|
+
FROM rbac_user_roles ur
|
|
78
|
+
INNER JOIN rbac_roles r ON r.id = ur.role_id
|
|
79
|
+
WHERE ur.user_id = $1
|
|
80
|
+
AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)
|
|
81
|
+
AND (ur.expires_at IS NULL OR ur.expires_at > now())
|
|
82
|
+
`,
|
|
83
|
+
[query.userId, tenantId]
|
|
84
|
+
),
|
|
85
|
+
this.pool.query(
|
|
86
|
+
`
|
|
87
|
+
SELECT p.key, ur.role_id, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at
|
|
88
|
+
FROM rbac_user_roles ur
|
|
89
|
+
INNER JOIN rbac_role_permissions rp ON rp.role_id = ur.role_id
|
|
90
|
+
INNER JOIN rbac_permissions p ON p.key = rp.permission_key
|
|
91
|
+
WHERE ur.user_id = $1
|
|
92
|
+
AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)
|
|
93
|
+
AND (ur.expires_at IS NULL OR ur.expires_at > now())
|
|
94
|
+
`,
|
|
95
|
+
[query.userId, tenantId]
|
|
96
|
+
)
|
|
97
|
+
]);
|
|
98
|
+
if (rolesResult.rowCount === 0 && permissionsResult.rowCount === 0) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const profile = {
|
|
102
|
+
userId: query.userId,
|
|
103
|
+
...query.tenantId === void 0 ? {} : { tenantId: query.tenantId },
|
|
104
|
+
loadedAt: /* @__PURE__ */ new Date(),
|
|
105
|
+
roles: rolesResult.rows.map(mapRole),
|
|
106
|
+
permissions: permissionsResult.rows.map(mapPermission)
|
|
107
|
+
};
|
|
108
|
+
return profile;
|
|
109
|
+
}
|
|
110
|
+
async upsertPermission(permission) {
|
|
111
|
+
await this.pool.query(
|
|
112
|
+
`
|
|
113
|
+
INSERT INTO rbac_permissions (key, description)
|
|
114
|
+
VALUES ($1, $2)
|
|
115
|
+
ON CONFLICT (key) DO UPDATE
|
|
116
|
+
SET description = EXCLUDED.description,
|
|
117
|
+
updated_at = now()
|
|
118
|
+
`,
|
|
119
|
+
[permission.key, permission.description ?? null]
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
async deletePermission(permissionKey) {
|
|
123
|
+
await this.pool.query("DELETE FROM rbac_permissions WHERE key = $1", [permissionKey]);
|
|
124
|
+
}
|
|
125
|
+
async createRole(role) {
|
|
126
|
+
await this.pool.query(
|
|
127
|
+
`
|
|
128
|
+
INSERT INTO rbac_roles (id, name, tenant_id)
|
|
129
|
+
VALUES ($1, $2, $3)
|
|
130
|
+
ON CONFLICT (id) DO UPDATE
|
|
131
|
+
SET name = EXCLUDED.name,
|
|
132
|
+
tenant_id = EXCLUDED.tenant_id,
|
|
133
|
+
updated_at = now()
|
|
134
|
+
`,
|
|
135
|
+
[role.id, role.name, role.tenantId ?? null]
|
|
136
|
+
);
|
|
137
|
+
for (const permission of role.permissions ?? []) {
|
|
138
|
+
await this.upsertPermission({ key: permission });
|
|
139
|
+
await this.grantPermissionToRole(role.id, permission);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
async deleteRole(roleId) {
|
|
143
|
+
await this.pool.query("DELETE FROM rbac_roles WHERE id = $1", [roleId]);
|
|
144
|
+
}
|
|
145
|
+
async grantPermissionToRole(roleId, permissionKey) {
|
|
146
|
+
await this.pool.query(
|
|
147
|
+
`
|
|
148
|
+
INSERT INTO rbac_role_permissions (role_id, permission_key)
|
|
149
|
+
VALUES ($1, $2)
|
|
150
|
+
ON CONFLICT (role_id, permission_key) DO NOTHING
|
|
151
|
+
`,
|
|
152
|
+
[roleId, permissionKey]
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
async revokePermissionFromRole(roleId, permissionKey) {
|
|
156
|
+
await this.pool.query(
|
|
157
|
+
"DELETE FROM rbac_role_permissions WHERE role_id = $1 AND permission_key = $2",
|
|
158
|
+
[roleId, permissionKey]
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
async assignRole(assignment) {
|
|
162
|
+
await this.pool.query(
|
|
163
|
+
`
|
|
164
|
+
INSERT INTO rbac_user_roles (
|
|
165
|
+
user_id,
|
|
166
|
+
role_id,
|
|
167
|
+
tenant_id,
|
|
168
|
+
resource_type,
|
|
169
|
+
resource_id,
|
|
170
|
+
expires_at
|
|
171
|
+
)
|
|
172
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
173
|
+
`,
|
|
174
|
+
[
|
|
175
|
+
assignment.userId,
|
|
176
|
+
assignment.roleId,
|
|
177
|
+
assignment.tenantId ?? null,
|
|
178
|
+
assignment.resourceType ?? null,
|
|
179
|
+
assignment.resourceId ?? null,
|
|
180
|
+
assignment.expiresAt ?? null
|
|
181
|
+
]
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
async revokeRole(revocation) {
|
|
185
|
+
await this.pool.query(
|
|
186
|
+
`
|
|
187
|
+
DELETE FROM rbac_user_roles
|
|
188
|
+
WHERE user_id = $1
|
|
189
|
+
AND role_id = $2
|
|
190
|
+
AND ($3::text IS NULL OR tenant_id = $3)
|
|
191
|
+
AND ($4::text IS NULL OR resource_type = $4)
|
|
192
|
+
AND ($5::text IS NULL OR resource_id = $5)
|
|
193
|
+
`,
|
|
194
|
+
[
|
|
195
|
+
revocation.userId,
|
|
196
|
+
revocation.roleId,
|
|
197
|
+
revocation.tenantId ?? null,
|
|
198
|
+
revocation.resourceType ?? null,
|
|
199
|
+
revocation.resourceId ?? null
|
|
200
|
+
]
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
function createPostgresRbacStore(options) {
|
|
205
|
+
if (options.pool !== void 0) {
|
|
206
|
+
return new PostgresRbacStore(options.pool);
|
|
207
|
+
}
|
|
208
|
+
return new PostgresRbacStore(new Pool(options), true);
|
|
209
|
+
}
|
|
210
|
+
function mapRole(row) {
|
|
211
|
+
return {
|
|
212
|
+
id: row.id,
|
|
213
|
+
name: row.name,
|
|
214
|
+
...row.tenant_id === null ? {} : { tenantId: row.tenant_id },
|
|
215
|
+
...row.resource_type === null ? {} : { resourceType: row.resource_type },
|
|
216
|
+
...row.resource_id === null ? {} : { resourceId: row.resource_id },
|
|
217
|
+
...row.expires_at === null ? {} : { expiresAt: row.expires_at }
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function mapPermission(row) {
|
|
221
|
+
return {
|
|
222
|
+
key: row.key,
|
|
223
|
+
sourceRoleId: row.role_id,
|
|
224
|
+
...row.tenant_id === null ? {} : { tenantId: row.tenant_id },
|
|
225
|
+
...row.resource_type === null ? {} : { resourceType: row.resource_type },
|
|
226
|
+
...row.resource_id === null ? {} : { resourceId: row.resource_id },
|
|
227
|
+
...row.expires_at === null ? {} : { expiresAt: row.expires_at }
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
POSTGRES_RBAC_SCHEMA,
|
|
232
|
+
PostgresRbacStore,
|
|
233
|
+
createPostgresRbacStore
|
|
234
|
+
};
|
|
235
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/postgres-rbac-schema.ts","../src/postgres-rbac-store.ts"],"sourcesContent":["export const POSTGRES_RBAC_SCHEMA = `\nCREATE TABLE IF NOT EXISTS rbac_permissions (\n key text PRIMARY KEY,\n description text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_permissions_key_length CHECK (length(key) BETWEEN 1 AND 128),\n CONSTRAINT rbac_permissions_key_safe CHECK (key ~ '^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$')\n);\n\nCREATE TABLE IF NOT EXISTS rbac_roles (\n id text PRIMARY KEY,\n name text NOT NULL,\n tenant_id text NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n updated_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_roles_id_length CHECK (length(id) BETWEEN 1 AND 256),\n CONSTRAINT rbac_roles_name_length CHECK (length(name) BETWEEN 1 AND 256)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_role_permissions (\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n permission_key text NOT NULL REFERENCES rbac_permissions(key) ON DELETE CASCADE,\n created_at timestamptz NOT NULL DEFAULT now(),\n PRIMARY KEY (role_id, permission_key)\n);\n\nCREATE TABLE IF NOT EXISTS rbac_user_roles (\n id bigserial PRIMARY KEY,\n user_id text NOT NULL,\n role_id text NOT NULL REFERENCES rbac_roles(id) ON DELETE CASCADE,\n tenant_id text NULL,\n resource_type text NULL,\n resource_id text NULL,\n expires_at timestamptz NULL,\n created_at timestamptz NOT NULL DEFAULT now(),\n CONSTRAINT rbac_user_roles_user_id_length CHECK (length(user_id) BETWEEN 1 AND 256)\n);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_user_tenant\n ON rbac_user_roles (user_id, tenant_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_role\n ON rbac_user_roles (role_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_user_roles_resource\n ON rbac_user_roles (resource_type, resource_id);\n\nCREATE INDEX IF NOT EXISTS idx_rbac_role_permissions_permission\n ON rbac_role_permissions (permission_key);\n`;\n","import { Pool, type PoolConfig } from 'pg';\nimport type {\n AccessPermission,\n AccessProfile,\n AccessProfileQuery,\n AccessRepository,\n AccessRole,\n AssignmentRepository,\n PermissionDefinition,\n PermissionRepository,\n RoleAssignment,\n RoleAssignmentRevocation,\n RoleDefinition,\n RoleRepository\n} from '@rbacbee-lib/core';\nimport { POSTGRES_RBAC_SCHEMA } from './postgres-rbac-schema';\n\nexport interface PostgresRbacStoreOptions extends PoolConfig {\n readonly pool?: Pool;\n}\n\ninterface RoleRow {\n readonly id: string;\n readonly name: string;\n readonly tenant_id: string | null;\n readonly resource_type: string | null;\n readonly resource_id: string | null;\n readonly expires_at: Date | null;\n}\n\ninterface PermissionRow {\n readonly key: string;\n readonly role_id: string;\n readonly tenant_id: string | null;\n readonly resource_type: string | null;\n readonly resource_id: string | null;\n readonly expires_at: Date | null;\n}\n\nexport class PostgresRbacStore\n implements AccessRepository, PermissionRepository, RoleRepository, AssignmentRepository\n{\n private readonly ownsPool: boolean;\n\n public constructor(\n private readonly pool: Pool,\n ownsPool = false\n ) {\n this.ownsPool = ownsPool;\n }\n\n public async migrate(): Promise<void> {\n await this.pool.query(POSTGRES_RBAC_SCHEMA);\n }\n\n public async close(): Promise<void> {\n if (this.ownsPool) {\n await this.pool.end();\n }\n }\n\n public async getAccessProfile(query: AccessProfileQuery): Promise<AccessProfile | null> {\n const tenantId = query.tenantId ?? null;\n const [rolesResult, permissionsResult] = await Promise.all([\n this.pool.query<RoleRow>(\n `\n SELECT r.id, r.name, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at\n FROM rbac_user_roles ur\n INNER JOIN rbac_roles r ON r.id = ur.role_id\n WHERE ur.user_id = $1\n AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)\n AND (ur.expires_at IS NULL OR ur.expires_at > now())\n `,\n [query.userId, tenantId]\n ),\n this.pool.query<PermissionRow>(\n `\n SELECT p.key, ur.role_id, ur.tenant_id, ur.resource_type, ur.resource_id, ur.expires_at\n FROM rbac_user_roles ur\n INNER JOIN rbac_role_permissions rp ON rp.role_id = ur.role_id\n INNER JOIN rbac_permissions p ON p.key = rp.permission_key\n WHERE ur.user_id = $1\n AND ($2::text IS NULL OR ur.tenant_id IS NULL OR ur.tenant_id = $2)\n AND (ur.expires_at IS NULL OR ur.expires_at > now())\n `,\n [query.userId, tenantId]\n )\n ]);\n\n if (rolesResult.rowCount === 0 && permissionsResult.rowCount === 0) {\n return null;\n }\n\n const profile: AccessProfile = {\n userId: query.userId,\n ...(query.tenantId === undefined ? {} : { tenantId: query.tenantId }),\n loadedAt: new Date(),\n roles: rolesResult.rows.map(mapRole),\n permissions: permissionsResult.rows.map(mapPermission)\n };\n\n return profile;\n }\n\n public async upsertPermission(permission: PermissionDefinition): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_permissions (key, description)\n VALUES ($1, $2)\n ON CONFLICT (key) DO UPDATE\n SET description = EXCLUDED.description,\n updated_at = now()\n `,\n [permission.key, permission.description ?? null]\n );\n }\n\n public async deletePermission(permissionKey: string): Promise<void> {\n await this.pool.query('DELETE FROM rbac_permissions WHERE key = $1', [permissionKey]);\n }\n\n public async createRole(role: RoleDefinition): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_roles (id, name, tenant_id)\n VALUES ($1, $2, $3)\n ON CONFLICT (id) DO UPDATE\n SET name = EXCLUDED.name,\n tenant_id = EXCLUDED.tenant_id,\n updated_at = now()\n `,\n [role.id, role.name, role.tenantId ?? null]\n );\n\n for (const permission of role.permissions ?? []) {\n await this.upsertPermission({ key: permission });\n await this.grantPermissionToRole(role.id, permission);\n }\n }\n\n public async deleteRole(roleId: string): Promise<void> {\n await this.pool.query('DELETE FROM rbac_roles WHERE id = $1', [roleId]);\n }\n\n public async grantPermissionToRole(roleId: string, permissionKey: string): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_role_permissions (role_id, permission_key)\n VALUES ($1, $2)\n ON CONFLICT (role_id, permission_key) DO NOTHING\n `,\n [roleId, permissionKey]\n );\n }\n\n public async revokePermissionFromRole(roleId: string, permissionKey: string): Promise<void> {\n await this.pool.query(\n 'DELETE FROM rbac_role_permissions WHERE role_id = $1 AND permission_key = $2',\n [roleId, permissionKey]\n );\n }\n\n public async assignRole(assignment: RoleAssignment): Promise<void> {\n await this.pool.query(\n `\n INSERT INTO rbac_user_roles (\n user_id,\n role_id,\n tenant_id,\n resource_type,\n resource_id,\n expires_at\n )\n VALUES ($1, $2, $3, $4, $5, $6)\n `,\n [\n assignment.userId,\n assignment.roleId,\n assignment.tenantId ?? null,\n assignment.resourceType ?? null,\n assignment.resourceId ?? null,\n assignment.expiresAt ?? null\n ]\n );\n }\n\n public async revokeRole(revocation: RoleAssignmentRevocation): Promise<void> {\n await this.pool.query(\n `\n DELETE FROM rbac_user_roles\n WHERE user_id = $1\n AND role_id = $2\n AND ($3::text IS NULL OR tenant_id = $3)\n AND ($4::text IS NULL OR resource_type = $4)\n AND ($5::text IS NULL OR resource_id = $5)\n `,\n [\n revocation.userId,\n revocation.roleId,\n revocation.tenantId ?? null,\n revocation.resourceType ?? null,\n revocation.resourceId ?? null\n ]\n );\n }\n}\n\nexport function createPostgresRbacStore(options: PostgresRbacStoreOptions): PostgresRbacStore {\n if (options.pool !== undefined) {\n return new PostgresRbacStore(options.pool);\n }\n\n return new PostgresRbacStore(new Pool(options), true);\n}\n\nfunction mapRole(row: RoleRow): AccessRole {\n return {\n id: row.id,\n name: row.name,\n ...(row.tenant_id === null ? {} : { tenantId: row.tenant_id }),\n ...(row.resource_type === null ? {} : { resourceType: row.resource_type }),\n ...(row.resource_id === null ? {} : { resourceId: row.resource_id }),\n ...(row.expires_at === null ? {} : { expiresAt: row.expires_at })\n };\n}\n\nfunction mapPermission(row: PermissionRow): AccessPermission {\n return {\n key: row.key,\n sourceRoleId: row.role_id,\n ...(row.tenant_id === null ? {} : { tenantId: row.tenant_id }),\n ...(row.resource_type === null ? {} : { resourceType: row.resource_type }),\n ...(row.resource_id === null ? {} : { resourceId: row.resource_id }),\n ...(row.expires_at === null ? {} : { expiresAt: row.expires_at })\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rbacbee-lib/postgres",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Postgres storage adapter for @rbacbee-lib/core.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"main": "./dist/index.cjs",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"require": "./dist/index.cjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsup src/index.ts --format esm,cjs --dts --sourcemap --clean --external pg --external @rbacbee-lib/core",
|
|
24
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --sourcemap --watch --external pg --external @rbacbee-lib/core",
|
|
25
|
+
"test": "vitest run --passWithNoTests",
|
|
26
|
+
"test:watch": "vitest",
|
|
27
|
+
"lint": "eslint src --max-warnings=0",
|
|
28
|
+
"typecheck": "tsc --noEmit",
|
|
29
|
+
"clean": "rimraf dist coverage"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@rbacbee-lib/core": "workspace:^",
|
|
33
|
+
"pg": "^8.13.1"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/pg": "^8.11.10"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|