@mahiframework/permissions 0.1.4
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/LICENSE +21 -0
- package/README.md +7 -0
- package/dist/assignee.d.ts +57 -0
- package/dist/assignee.d.ts.map +1 -0
- package/dist/assignee.js +46 -0
- package/dist/assignee.js.map +1 -0
- package/dist/commands/permissions-cache-reset.d.ts +20 -0
- package/dist/commands/permissions-cache-reset.d.ts.map +1 -0
- package/dist/commands/permissions-cache-reset.js +24 -0
- package/dist/commands/permissions-cache-reset.js.map +1 -0
- package/dist/commands/permissions-check.d.ts +37 -0
- package/dist/commands/permissions-check.d.ts.map +1 -0
- package/dist/commands/permissions-check.js +92 -0
- package/dist/commands/permissions-check.js.map +1 -0
- package/dist/commands/permissions-show.d.ts +20 -0
- package/dist/commands/permissions-show.d.ts.map +1 -0
- package/dist/commands/permissions-show.js +49 -0
- package/dist/commands/permissions-show.js.map +1 -0
- package/dist/errors.d.ts +77 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +106 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/listeners/invalidate-permission-cache.listener.d.ts +39 -0
- package/dist/listeners/invalidate-permission-cache.listener.d.ts.map +1 -0
- package/dist/listeners/invalidate-permission-cache.listener.js +50 -0
- package/dist/listeners/invalidate-permission-cache.listener.js.map +1 -0
- package/dist/middleware/current-subject.d.ts +23 -0
- package/dist/middleware/current-subject.d.ts.map +1 -0
- package/dist/middleware/current-subject.js +31 -0
- package/dist/middleware/current-subject.js.map +1 -0
- package/dist/middleware/permission.d.ts +19 -0
- package/dist/middleware/permission.d.ts.map +1 -0
- package/dist/middleware/permission.js +34 -0
- package/dist/middleware/permission.js.map +1 -0
- package/dist/middleware/role-or-permission.d.ts +29 -0
- package/dist/middleware/role-or-permission.d.ts.map +1 -0
- package/dist/middleware/role-or-permission.js +45 -0
- package/dist/middleware/role-or-permission.js.map +1 -0
- package/dist/middleware/role.d.ts +21 -0
- package/dist/middleware/role.d.ts.map +1 -0
- package/dist/middleware/role.js +36 -0
- package/dist/middleware/role.js.map +1 -0
- package/dist/migrations/0001_create_permission_tables.d.ts +63 -0
- package/dist/migrations/0001_create_permission_tables.d.ts.map +1 -0
- package/dist/migrations/0001_create_permission_tables.js +113 -0
- package/dist/migrations/0001_create_permission_tables.js.map +1 -0
- package/dist/models/permission.model.d.ts +58 -0
- package/dist/models/permission.model.d.ts.map +1 -0
- package/dist/models/permission.model.js +18 -0
- package/dist/models/permission.model.js.map +1 -0
- package/dist/models/role.model.d.ts +60 -0
- package/dist/models/role.model.d.ts.map +1 -0
- package/dist/models/role.model.js +18 -0
- package/dist/models/role.model.js.map +1 -0
- package/dist/permission-map.d.ts +97 -0
- package/dist/permission-map.d.ts.map +1 -0
- package/dist/permission-map.js +93 -0
- package/dist/permission-map.js.map +1 -0
- package/dist/permission-registrar.d.ts +183 -0
- package/dist/permission-registrar.d.ts.map +1 -0
- package/dist/permission-registrar.js +573 -0
- package/dist/permission-registrar.js.map +1 -0
- package/dist/permissions-config.d.ts +80 -0
- package/dist/permissions-config.d.ts.map +1 -0
- package/dist/permissions-config.js +22 -0
- package/dist/permissions-config.js.map +1 -0
- package/dist/permissions-facade.d.ts +74 -0
- package/dist/permissions-facade.d.ts.map +1 -0
- package/dist/permissions-facade.js +131 -0
- package/dist/permissions-facade.js.map +1 -0
- package/dist/permissions-service-provider.d.ts +91 -0
- package/dist/permissions-service-provider.d.ts.map +1 -0
- package/dist/permissions-service-provider.js +137 -0
- package/dist/permissions-service-provider.js.map +1 -0
- package/dist/relations.d.ts +63 -0
- package/dist/relations.d.ts.map +1 -0
- package/dist/relations.js +62 -0
- package/dist/relations.js.map +1 -0
- package/dist/request-cache.d.ts +50 -0
- package/dist/request-cache.d.ts.map +1 -0
- package/dist/request-cache.js +40 -0
- package/dist/request-cache.js.map +1 -0
- package/dist/tokens.d.ts +15 -0
- package/dist/tokens.d.ts.map +1 -0
- package/dist/tokens.js +15 -0
- package/dist/tokens.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,573 @@
|
|
|
1
|
+
import { AUTH_TOKEN, CACHE_TOKEN } from "@mahiframework/core";
|
|
2
|
+
import { DB } from "@mahiframework/database";
|
|
3
|
+
import { assigneeCacheKey, resolveAssignee, } from "./assignee.js";
|
|
4
|
+
import { DuplicateNameError, PermissionNotFoundError, RoleNotFoundError, UnresolvedGuardError, } from "./errors.js";
|
|
5
|
+
import { buildMap, deserializeMap, mapKey, serializeMap, } from "./permission-map.js";
|
|
6
|
+
import { Permission } from "./models/permission.model.js";
|
|
7
|
+
import { Role } from "./models/role.model.js";
|
|
8
|
+
import { assignmentMemo, forgetMemoisedAssignments, } from "./request-cache.js";
|
|
9
|
+
/** Roles and permissions, their relationships, and who holds them. */
|
|
10
|
+
export class PermissionRegistrar {
|
|
11
|
+
app;
|
|
12
|
+
config;
|
|
13
|
+
constructor(app, config) {
|
|
14
|
+
this.app = app;
|
|
15
|
+
this.config = config;
|
|
16
|
+
}
|
|
17
|
+
// ---------------------------------------------------------------- guards
|
|
18
|
+
/**
|
|
19
|
+
* The guard a call operates on.
|
|
20
|
+
*
|
|
21
|
+
* `auth.default` is the last resort rather than the ambient
|
|
22
|
+
* `currentGuard()`, which would read the guard that authenticated THIS
|
|
23
|
+
* request. That is tempting and wrong: it throws outside a request
|
|
24
|
+
* scope (`MissingAuthContextError`), so a queue job or a seeder
|
|
25
|
+
* assigning a role would crash, and it would make the same
|
|
26
|
+
* `createRole("admin")` produce a different row depending on who
|
|
27
|
+
* happened to call it.
|
|
28
|
+
*
|
|
29
|
+
* Throws rather than defaulting to `""`: `guard_name` is NOT NULL with
|
|
30
|
+
* no wildcard, so an unresolvable guard has no safe representation, and
|
|
31
|
+
* a role stamped with the empty string is a role no check will ever
|
|
32
|
+
* match.
|
|
33
|
+
*/
|
|
34
|
+
guardName(options = {}) {
|
|
35
|
+
const named = options.guard ?? this.config.guard ?? this.defaultGuard();
|
|
36
|
+
if (named === null || named === "") {
|
|
37
|
+
throw new UnresolvedGuardError();
|
|
38
|
+
}
|
|
39
|
+
return named;
|
|
40
|
+
}
|
|
41
|
+
defaultGuard() {
|
|
42
|
+
if (!this.app.has(AUTH_TOKEN)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
return this.app.make(AUTH_TOKEN).getDefaultDriver();
|
|
46
|
+
}
|
|
47
|
+
// ----------------------------------------------------------- the cache
|
|
48
|
+
/**
|
|
49
|
+
* The role/permission map, from cache or the database.
|
|
50
|
+
*
|
|
51
|
+
* `remember()` treats `undefined` as its miss sentinel, so the loader
|
|
52
|
+
* must never return it — this one always returns an object, even for an
|
|
53
|
+
* app with no roles at all.
|
|
54
|
+
*
|
|
55
|
+
* The map crosses the cache boundary serialised (ids as strings): see
|
|
56
|
+
* `permission-map.ts` for why a `bigint` cannot be cached.
|
|
57
|
+
*/
|
|
58
|
+
async map() {
|
|
59
|
+
const store = this.cache().store(this.config.cacheStore);
|
|
60
|
+
const serialized = await store.remember(this.config.cacheKey, () => this.loadMap(), this.config.cacheTtlSeconds);
|
|
61
|
+
return deserializeMap(serialized);
|
|
62
|
+
}
|
|
63
|
+
/** Read every role, permission, and role-permission link. Three queries, no joins. */
|
|
64
|
+
async loadMap() {
|
|
65
|
+
const [roleRows, permissionRows, links] = await Promise.all([
|
|
66
|
+
DB.table("roles").select("id", "name", "guard_name").get(),
|
|
67
|
+
DB.table("permissions").select("id", "name", "guard_name").get(),
|
|
68
|
+
DB.table("role_has_permissions").select("role_id", "permission_id").get(),
|
|
69
|
+
]);
|
|
70
|
+
const grouped = new Map();
|
|
71
|
+
for (const link of links) {
|
|
72
|
+
const key = String(link.role_id);
|
|
73
|
+
const existing = grouped.get(key);
|
|
74
|
+
if (existing === undefined) {
|
|
75
|
+
grouped.set(key, [BigInt(link.permission_id)]);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
existing.push(BigInt(link.permission_id));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const roles = roleRows.map((row) => ({
|
|
82
|
+
id: BigInt(row.id),
|
|
83
|
+
name: row.name,
|
|
84
|
+
guardName: row.guard_name,
|
|
85
|
+
permissionIds: grouped.get(String(row.id)) ?? [],
|
|
86
|
+
}));
|
|
87
|
+
const permissions = permissionRows.map((row) => ({
|
|
88
|
+
id: BigInt(row.id),
|
|
89
|
+
name: row.name,
|
|
90
|
+
guardName: row.guard_name,
|
|
91
|
+
}));
|
|
92
|
+
return serializeMap(buildMap(roles, permissions));
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Drop the cached map and every memoised assignment.
|
|
96
|
+
*
|
|
97
|
+
* Called by every write here, and by the model-event listeners for
|
|
98
|
+
* writes that bypass this class (a seeder calling `Role.create()`).
|
|
99
|
+
* Forgets exactly one key — `@mahiframework/cache` has no tags, so
|
|
100
|
+
* there is no flush-by-pattern, and `flush()` would take out the app's
|
|
101
|
+
* entire cache.
|
|
102
|
+
*/
|
|
103
|
+
async forgetCache() {
|
|
104
|
+
forgetMemoisedAssignments();
|
|
105
|
+
await this.cache().store(this.config.cacheStore).forget(this.config.cacheKey);
|
|
106
|
+
}
|
|
107
|
+
cache() {
|
|
108
|
+
return this.app.make(CACHE_TOKEN);
|
|
109
|
+
}
|
|
110
|
+
// ------------------------------------------------------ role/permission CRUD
|
|
111
|
+
/** Create a role. Throws if one already exists with this name for this guard. */
|
|
112
|
+
async createRole(name, options = {}) {
|
|
113
|
+
const guard = this.guardName(options);
|
|
114
|
+
if ((await this.map()).roleByName.has(mapKey(guard, name))) {
|
|
115
|
+
throw new DuplicateNameError("role", name, guard);
|
|
116
|
+
}
|
|
117
|
+
const role = await Role.create({ name, guard_name: guard });
|
|
118
|
+
await this.forgetCache();
|
|
119
|
+
return role;
|
|
120
|
+
}
|
|
121
|
+
/** Create a permission. Throws if one already exists with this name for this guard. */
|
|
122
|
+
async createPermission(name, options = {}) {
|
|
123
|
+
const guard = this.guardName(options);
|
|
124
|
+
if ((await this.map()).permissionByName.has(mapKey(guard, name))) {
|
|
125
|
+
throw new DuplicateNameError("permission", name, guard);
|
|
126
|
+
}
|
|
127
|
+
const permission = await Permission.create({ name, guard_name: guard });
|
|
128
|
+
await this.forgetCache();
|
|
129
|
+
return permission;
|
|
130
|
+
}
|
|
131
|
+
/** Create a role only if it doesn't exist, returning either way. */
|
|
132
|
+
async findOrCreateRole(name, options = {}) {
|
|
133
|
+
const guard = this.guardName(options);
|
|
134
|
+
const existing = (await this.map()).roleByName.get(mapKey(guard, name));
|
|
135
|
+
if (existing !== undefined) {
|
|
136
|
+
return (await Role.findOrFail(existing.id));
|
|
137
|
+
}
|
|
138
|
+
return this.createRole(name, { guard });
|
|
139
|
+
}
|
|
140
|
+
/** Create a permission only if it doesn't exist, returning either way. */
|
|
141
|
+
async findOrCreatePermission(name, options = {}) {
|
|
142
|
+
const guard = this.guardName(options);
|
|
143
|
+
const existing = (await this.map()).permissionByName.get(mapKey(guard, name));
|
|
144
|
+
if (existing !== undefined) {
|
|
145
|
+
return (await Permission.findOrFail(existing.id));
|
|
146
|
+
}
|
|
147
|
+
return this.createPermission(name, { guard });
|
|
148
|
+
}
|
|
149
|
+
/** The role with this name, or `RoleNotFoundError`. */
|
|
150
|
+
async findRole(name, options = {}) {
|
|
151
|
+
const guard = this.guardName(options);
|
|
152
|
+
const mapped = (await this.map()).roleByName.get(mapKey(guard, name));
|
|
153
|
+
if (mapped === undefined) {
|
|
154
|
+
throw new RoleNotFoundError(name, guard);
|
|
155
|
+
}
|
|
156
|
+
return (await Role.findOrFail(mapped.id));
|
|
157
|
+
}
|
|
158
|
+
/** The permission with this name, or `PermissionNotFoundError`. */
|
|
159
|
+
async findPermission(name, options = {}) {
|
|
160
|
+
const guard = this.guardName(options);
|
|
161
|
+
const mapped = (await this.map()).permissionByName.get(mapKey(guard, name));
|
|
162
|
+
if (mapped === undefined) {
|
|
163
|
+
throw new PermissionNotFoundError(name, guard);
|
|
164
|
+
}
|
|
165
|
+
return (await Permission.findOrFail(mapped.id));
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Delete a role. Its assignments and permission links go with it, via
|
|
169
|
+
* the pivots' `cascadeOnDelete` foreign keys.
|
|
170
|
+
*/
|
|
171
|
+
async deleteRole(role, options = {}) {
|
|
172
|
+
const id = await this.roleId(role, options);
|
|
173
|
+
await Role.delete(id);
|
|
174
|
+
await this.forgetCache();
|
|
175
|
+
}
|
|
176
|
+
/** Delete a permission. Its assignments and role links cascade. */
|
|
177
|
+
async deletePermission(permission, options = {}) {
|
|
178
|
+
const id = await this.permissionId(permission, options);
|
|
179
|
+
await Permission.delete(id);
|
|
180
|
+
await this.forgetCache();
|
|
181
|
+
}
|
|
182
|
+
// --------------------------------------------------- role -> permissions
|
|
183
|
+
/** Grant permissions to a role, ignoring any it already has. */
|
|
184
|
+
async givePermissionToRole(role, permissions, options = {}) {
|
|
185
|
+
const roleId = await this.roleId(role, options);
|
|
186
|
+
const ids = await this.permissionIds(permissions, options);
|
|
187
|
+
const held = new Set(((await this.map()).roleById.get(roleId)?.permissionIds ?? []).map(String));
|
|
188
|
+
const missing = ids.filter((id) => !held.has(String(id)));
|
|
189
|
+
if (missing.length === 0) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
await this.insertChunked("role_has_permissions", missing.map((id) => ({ role_id: roleId, permission_id: id })));
|
|
193
|
+
await this.forgetCache();
|
|
194
|
+
}
|
|
195
|
+
/** Revoke permissions from a role. */
|
|
196
|
+
async revokePermissionFromRole(role, permissions, options = {}) {
|
|
197
|
+
const roleId = await this.roleId(role, options);
|
|
198
|
+
const ids = await this.permissionIds(permissions, options);
|
|
199
|
+
if (ids.length === 0) {
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
await DB.table("role_has_permissions")
|
|
203
|
+
.where("role_id", roleId)
|
|
204
|
+
.whereIn("permission_id", ids)
|
|
205
|
+
.delete();
|
|
206
|
+
await this.forgetCache();
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Make a role's permissions exactly this list.
|
|
210
|
+
*
|
|
211
|
+
* An empty list revokes everything, which is the whole point of a sync
|
|
212
|
+
* and the one behaviour worth being explicit about: the framework's own
|
|
213
|
+
* `detach([])` is a deliberate no-op, so a caller passing
|
|
214
|
+
* `request.input("permissions")` through that API would silently keep
|
|
215
|
+
* the old set. This writes pivots directly and means what it says.
|
|
216
|
+
*/
|
|
217
|
+
async syncRolePermissions(role, permissions, options = {}) {
|
|
218
|
+
const roleId = await this.roleId(role, options);
|
|
219
|
+
const wanted = await this.permissionIds(permissions, options);
|
|
220
|
+
await DB.transaction(async () => {
|
|
221
|
+
await DB.table("role_has_permissions").where("role_id", roleId).delete();
|
|
222
|
+
await this.insertChunked("role_has_permissions", wanted.map((id) => ({ role_id: roleId, permission_id: id })));
|
|
223
|
+
});
|
|
224
|
+
await this.forgetCache();
|
|
225
|
+
}
|
|
226
|
+
// ------------------------------------------------------- subject -> roles
|
|
227
|
+
/** Assign roles to a subject. Already-held roles are skipped, so this is idempotent. */
|
|
228
|
+
async assignRole(assignee, roles, options = {}) {
|
|
229
|
+
const subject = resolveAssignee(assignee);
|
|
230
|
+
const ids = await this.roleIds(roles, options);
|
|
231
|
+
const current = await this.assignmentsFor(subject);
|
|
232
|
+
const held = new Set(current.roleIds.map(String));
|
|
233
|
+
const missing = ids.filter((id) => !held.has(String(id)));
|
|
234
|
+
if (missing.length === 0) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await this.insertChunked("model_has_roles", missing.map((id) => ({
|
|
238
|
+
role_id: id,
|
|
239
|
+
model_type: subject.morphType,
|
|
240
|
+
model_id: subject.key,
|
|
241
|
+
})));
|
|
242
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
243
|
+
}
|
|
244
|
+
/** Remove roles from a subject. */
|
|
245
|
+
async removeRole(assignee, roles, options = {}) {
|
|
246
|
+
const subject = resolveAssignee(assignee);
|
|
247
|
+
const ids = await this.roleIds(roles, options);
|
|
248
|
+
if (ids.length === 0) {
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
await DB.table("model_has_roles")
|
|
252
|
+
.where("model_type", subject.morphType)
|
|
253
|
+
.where("model_id", subject.key)
|
|
254
|
+
.whereIn("role_id", ids)
|
|
255
|
+
.delete();
|
|
256
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
257
|
+
}
|
|
258
|
+
/** Make a subject's roles exactly this list. An empty list removes all of them. */
|
|
259
|
+
async syncRoles(assignee, roles, options = {}) {
|
|
260
|
+
const subject = resolveAssignee(assignee);
|
|
261
|
+
const wanted = await this.roleIds(roles, options);
|
|
262
|
+
await DB.transaction(async () => {
|
|
263
|
+
await DB.table("model_has_roles")
|
|
264
|
+
.where("model_type", subject.morphType)
|
|
265
|
+
.where("model_id", subject.key)
|
|
266
|
+
.delete();
|
|
267
|
+
await this.insertChunked("model_has_roles", wanted.map((id) => ({
|
|
268
|
+
role_id: id,
|
|
269
|
+
model_type: subject.morphType,
|
|
270
|
+
model_id: subject.key,
|
|
271
|
+
})));
|
|
272
|
+
});
|
|
273
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
274
|
+
}
|
|
275
|
+
// ------------------------------------------------- subject -> permissions
|
|
276
|
+
/** Grant permissions to a subject directly, alongside whatever its roles grant. */
|
|
277
|
+
async givePermissionTo(assignee, permissions, options = {}) {
|
|
278
|
+
const subject = resolveAssignee(assignee);
|
|
279
|
+
const ids = await this.permissionIds(permissions, options);
|
|
280
|
+
const current = await this.assignmentsFor(subject);
|
|
281
|
+
const held = new Set(current.permissionIds.map(String));
|
|
282
|
+
const missing = ids.filter((id) => !held.has(String(id)));
|
|
283
|
+
if (missing.length === 0) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
await this.insertChunked("model_has_permissions", missing.map((id) => ({
|
|
287
|
+
permission_id: id,
|
|
288
|
+
model_type: subject.morphType,
|
|
289
|
+
model_id: subject.key,
|
|
290
|
+
})));
|
|
291
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Revoke a directly-granted permission.
|
|
295
|
+
*
|
|
296
|
+
* Only touches `model_has_permissions`. A permission the subject also
|
|
297
|
+
* holds through a role survives this call, and `hasPermissionTo()` will
|
|
298
|
+
* still answer true — which is correct, and the reason
|
|
299
|
+
* `hasDirectPermission()` exists to tell the two apart.
|
|
300
|
+
*/
|
|
301
|
+
async revokePermissionTo(assignee, permissions, options = {}) {
|
|
302
|
+
const subject = resolveAssignee(assignee);
|
|
303
|
+
const ids = await this.permissionIds(permissions, options);
|
|
304
|
+
if (ids.length === 0) {
|
|
305
|
+
return;
|
|
306
|
+
}
|
|
307
|
+
await DB.table("model_has_permissions")
|
|
308
|
+
.where("model_type", subject.morphType)
|
|
309
|
+
.where("model_id", subject.key)
|
|
310
|
+
.whereIn("permission_id", ids)
|
|
311
|
+
.delete();
|
|
312
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
313
|
+
}
|
|
314
|
+
/** Make a subject's direct permissions exactly this list. An empty list removes all of them. */
|
|
315
|
+
async syncPermissions(assignee, permissions, options = {}) {
|
|
316
|
+
const subject = resolveAssignee(assignee);
|
|
317
|
+
const wanted = await this.permissionIds(permissions, options);
|
|
318
|
+
await DB.transaction(async () => {
|
|
319
|
+
await DB.table("model_has_permissions")
|
|
320
|
+
.where("model_type", subject.morphType)
|
|
321
|
+
.where("model_id", subject.key)
|
|
322
|
+
.delete();
|
|
323
|
+
await this.insertChunked("model_has_permissions", wanted.map((id) => ({
|
|
324
|
+
permission_id: id,
|
|
325
|
+
model_type: subject.morphType,
|
|
326
|
+
model_id: subject.key,
|
|
327
|
+
})));
|
|
328
|
+
});
|
|
329
|
+
forgetMemoisedAssignments(assigneeCacheKey(subject));
|
|
330
|
+
}
|
|
331
|
+
// ------------------------------------------------------------- the checks
|
|
332
|
+
/** Does this subject hold this role? */
|
|
333
|
+
async hasRole(assignee, role, options = {}) {
|
|
334
|
+
return this.hasAnyRole(assignee, [role], options);
|
|
335
|
+
}
|
|
336
|
+
/** Does this subject hold at least one of these roles? */
|
|
337
|
+
async hasAnyRole(assignee, roles, options = {}) {
|
|
338
|
+
const names = await this.getRoleNames(assignee, options);
|
|
339
|
+
const map = await this.map();
|
|
340
|
+
const guard = this.guardName(options);
|
|
341
|
+
return roles.some((role) => names.has(this.roleNameOf(map, role, guard)));
|
|
342
|
+
}
|
|
343
|
+
/** Does this subject hold every one of these roles? */
|
|
344
|
+
async hasAllRoles(assignee, roles, options = {}) {
|
|
345
|
+
const names = await this.getRoleNames(assignee, options);
|
|
346
|
+
const map = await this.map();
|
|
347
|
+
const guard = this.guardName(options);
|
|
348
|
+
return roles.every((role) => names.has(this.roleNameOf(map, role, guard)));
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Does this subject hold this permission, by any route?
|
|
352
|
+
*
|
|
353
|
+
* An unknown permission name returns false rather than throwing. This
|
|
354
|
+
* one is a check, not a write: the gate hook calls it with every
|
|
355
|
+
* ability string in the app, almost none of which are permissions, so
|
|
356
|
+
* throwing would turn `can("view-dashboard")` into a 500. The write
|
|
357
|
+
* methods still throw on an unknown name, which is where a typo
|
|
358
|
+
* actually matters.
|
|
359
|
+
*/
|
|
360
|
+
async hasPermissionTo(assignee, permission, options = {}) {
|
|
361
|
+
return this.hasAnyPermission(assignee, [permission], options);
|
|
362
|
+
}
|
|
363
|
+
/** Does this subject hold at least one of these permissions, by any route? */
|
|
364
|
+
async hasAnyPermission(assignee, permissions, options = {}) {
|
|
365
|
+
const held = await this.getAllPermissions(assignee, options);
|
|
366
|
+
const map = await this.map();
|
|
367
|
+
const guard = this.guardName(options);
|
|
368
|
+
return permissions.some((permission) => held.has(this.permissionNameOf(map, permission, guard)));
|
|
369
|
+
}
|
|
370
|
+
/** Does this subject hold every one of these permissions, by any route? */
|
|
371
|
+
async hasAllPermissions(assignee, permissions, options = {}) {
|
|
372
|
+
const held = await this.getAllPermissions(assignee, options);
|
|
373
|
+
const map = await this.map();
|
|
374
|
+
const guard = this.guardName(options);
|
|
375
|
+
return permissions.every((permission) => held.has(this.permissionNameOf(map, permission, guard)));
|
|
376
|
+
}
|
|
377
|
+
/** Does this subject hold this permission DIRECTLY, ignoring its roles? */
|
|
378
|
+
async hasDirectPermission(assignee, permission, options = {}) {
|
|
379
|
+
const held = await this.getDirectPermissions(assignee, options);
|
|
380
|
+
const map = await this.map();
|
|
381
|
+
return held.has(this.permissionNameOf(map, permission, this.guardName(options)));
|
|
382
|
+
}
|
|
383
|
+
// ------------------------------------------------------- introspection
|
|
384
|
+
/** This subject's role names, for the resolved guard. */
|
|
385
|
+
async getRoleNames(assignee, options = {}) {
|
|
386
|
+
const guard = this.guardName(options);
|
|
387
|
+
const map = await this.map();
|
|
388
|
+
const assignments = await this.assignmentsFor(resolveAssignee(assignee));
|
|
389
|
+
const names = new Set();
|
|
390
|
+
for (const roleId of assignments.roleIds) {
|
|
391
|
+
const role = map.roleById.get(roleId);
|
|
392
|
+
// A guard mismatch is not a filter but the entire isolation
|
|
393
|
+
// guarantee: an `api` role must not answer a `web` question, even
|
|
394
|
+
// though the assignment row says the subject holds it.
|
|
395
|
+
if (role !== undefined && role.guardName === guard) {
|
|
396
|
+
names.add(role.name);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
return names;
|
|
400
|
+
}
|
|
401
|
+
/** Permission names this subject holds via its roles only. */
|
|
402
|
+
async getPermissionsViaRoles(assignee, options = {}) {
|
|
403
|
+
const guard = this.guardName(options);
|
|
404
|
+
const map = await this.map();
|
|
405
|
+
const assignments = await this.assignmentsFor(resolveAssignee(assignee));
|
|
406
|
+
const names = new Set();
|
|
407
|
+
for (const roleId of assignments.roleIds) {
|
|
408
|
+
const role = map.roleById.get(roleId);
|
|
409
|
+
if (role === undefined || role.guardName !== guard) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
for (const permissionId of role.permissionIds) {
|
|
413
|
+
const permission = map.permissionById.get(permissionId);
|
|
414
|
+
if (permission !== undefined && permission.guardName === guard) {
|
|
415
|
+
names.add(permission.name);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return names;
|
|
420
|
+
}
|
|
421
|
+
/** Permission names granted to this subject directly, ignoring its roles. */
|
|
422
|
+
async getDirectPermissions(assignee, options = {}) {
|
|
423
|
+
const guard = this.guardName(options);
|
|
424
|
+
const map = await this.map();
|
|
425
|
+
const assignments = await this.assignmentsFor(resolveAssignee(assignee));
|
|
426
|
+
const names = new Set();
|
|
427
|
+
for (const permissionId of assignments.permissionIds) {
|
|
428
|
+
const permission = map.permissionById.get(permissionId);
|
|
429
|
+
if (permission !== undefined && permission.guardName === guard) {
|
|
430
|
+
names.add(permission.name);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return names;
|
|
434
|
+
}
|
|
435
|
+
/** Every permission name this subject holds, by either route. */
|
|
436
|
+
async getAllPermissions(assignee, options = {}) {
|
|
437
|
+
const [viaRoles, direct] = await Promise.all([
|
|
438
|
+
this.getPermissionsViaRoles(assignee, options),
|
|
439
|
+
this.getDirectPermissions(assignee, options),
|
|
440
|
+
]);
|
|
441
|
+
for (const name of direct) {
|
|
442
|
+
viaRoles.add(name);
|
|
443
|
+
}
|
|
444
|
+
return viaRoles;
|
|
445
|
+
}
|
|
446
|
+
// ------------------------------------------------------------- internals
|
|
447
|
+
/**
|
|
448
|
+
* One subject's raw assignment ids, memoised per request.
|
|
449
|
+
*
|
|
450
|
+
* Two queries, in parallel, and at most once per subject per request.
|
|
451
|
+
* The memo is what makes the gate hook affordable: it fires on every
|
|
452
|
+
* authorization check, so a controller with five `can()` calls would
|
|
453
|
+
* otherwise be ten queries against rows that cannot have changed.
|
|
454
|
+
*/
|
|
455
|
+
async assignmentsFor(subject) {
|
|
456
|
+
const memo = assignmentMemo();
|
|
457
|
+
const key = assigneeCacheKey(subject);
|
|
458
|
+
const cached = memo?.get(key);
|
|
459
|
+
if (cached !== undefined) {
|
|
460
|
+
return cached;
|
|
461
|
+
}
|
|
462
|
+
const [roleRows, permissionRows] = await Promise.all([
|
|
463
|
+
DB.table("model_has_roles")
|
|
464
|
+
.select("role_id")
|
|
465
|
+
.where("model_type", subject.morphType)
|
|
466
|
+
.where("model_id", subject.key)
|
|
467
|
+
.get(),
|
|
468
|
+
DB.table("model_has_permissions")
|
|
469
|
+
.select("permission_id")
|
|
470
|
+
.where("model_type", subject.morphType)
|
|
471
|
+
.where("model_id", subject.key)
|
|
472
|
+
.get(),
|
|
473
|
+
]);
|
|
474
|
+
const record = {
|
|
475
|
+
roleIds: roleRows.map((row) => BigInt(row.role_id)),
|
|
476
|
+
permissionIds: permissionRows.map((row) => BigInt(row.permission_id)),
|
|
477
|
+
};
|
|
478
|
+
memo?.set(key, record);
|
|
479
|
+
return record;
|
|
480
|
+
}
|
|
481
|
+
/** The role's name, whether it was named by name or by id. Unknown ids yield a non-matching sentinel. */
|
|
482
|
+
roleNameOf(map, role, guard) {
|
|
483
|
+
if (typeof role === "string") {
|
|
484
|
+
return role;
|
|
485
|
+
}
|
|
486
|
+
const mapped = map.roleById.get(role);
|
|
487
|
+
return mapped !== undefined && mapped.guardName === guard ? mapped.name : UNMATCHABLE;
|
|
488
|
+
}
|
|
489
|
+
permissionNameOf(map, permission, guard) {
|
|
490
|
+
if (typeof permission === "string") {
|
|
491
|
+
return permission;
|
|
492
|
+
}
|
|
493
|
+
const mapped = map.permissionById.get(permission);
|
|
494
|
+
return mapped !== undefined && mapped.guardName === guard ? mapped.name : UNMATCHABLE;
|
|
495
|
+
}
|
|
496
|
+
/** Resolve a role reference to its id, throwing on an unknown name. */
|
|
497
|
+
async roleId(role, options) {
|
|
498
|
+
if (typeof role === "bigint") {
|
|
499
|
+
return role;
|
|
500
|
+
}
|
|
501
|
+
if (role instanceof Role) {
|
|
502
|
+
return role.id;
|
|
503
|
+
}
|
|
504
|
+
const guard = this.guardName(options);
|
|
505
|
+
const mapped = (await this.map()).roleByName.get(mapKey(guard, role));
|
|
506
|
+
if (mapped === undefined) {
|
|
507
|
+
throw new RoleNotFoundError(role, guard);
|
|
508
|
+
}
|
|
509
|
+
return mapped.id;
|
|
510
|
+
}
|
|
511
|
+
async permissionId(permission, options) {
|
|
512
|
+
if (typeof permission === "bigint") {
|
|
513
|
+
return permission;
|
|
514
|
+
}
|
|
515
|
+
if (permission instanceof Permission) {
|
|
516
|
+
return permission.id;
|
|
517
|
+
}
|
|
518
|
+
const guard = this.guardName(options);
|
|
519
|
+
const mapped = (await this.map()).permissionByName.get(mapKey(guard, permission));
|
|
520
|
+
if (mapped === undefined) {
|
|
521
|
+
throw new PermissionNotFoundError(permission, guard);
|
|
522
|
+
}
|
|
523
|
+
return mapped.id;
|
|
524
|
+
}
|
|
525
|
+
async roleIds(roles, options) {
|
|
526
|
+
const list = Array.isArray(roles) ? roles : [roles];
|
|
527
|
+
return Promise.all(list.map((role) => this.roleId(role, options)));
|
|
528
|
+
}
|
|
529
|
+
async permissionIds(permissions, options) {
|
|
530
|
+
const list = Array.isArray(permissions) ? permissions : [permissions];
|
|
531
|
+
return Promise.all(list.map((permission) => this.permissionId(permission, options)));
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Insert pivot rows, in chunks, as one multi-row statement each.
|
|
535
|
+
*
|
|
536
|
+
* Goes to raw Kysely rather than `QueryBuilder`, whose `insert()` takes
|
|
537
|
+
* a single row: a per-row loop would turn a 500-permission sync into
|
|
538
|
+
* 500 round trips. `Role.resolveConnection()` is the handle rather
|
|
539
|
+
* than a `DatabaseManager` lookup because it swaps in the active
|
|
540
|
+
* transaction when there is one, which is what makes the `sync*`
|
|
541
|
+
* methods' delete-then-insert atomic.
|
|
542
|
+
*
|
|
543
|
+
* Chunked because pivot writes in this framework do not bound their
|
|
544
|
+
* parameter count, and a multi-row insert binds one parameter per
|
|
545
|
+
* column per row — three columns here, so a sync of 12,000 would
|
|
546
|
+
* exceed SQLite's 32,766-binding ceiling (Postgres' is 65,535) and
|
|
547
|
+
* fail at the driver rather than anywhere meaningful. 1,000 rows is
|
|
548
|
+
* 3,000 bindings, well inside every engine. Sequential, since the
|
|
549
|
+
* chunks all target one table inside one transaction.
|
|
550
|
+
*/
|
|
551
|
+
async insertChunked(table, rows) {
|
|
552
|
+
if (rows.length === 0) {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const connection = Role.resolveConnection();
|
|
556
|
+
for (let index = 0; index < rows.length; index += INSERT_CHUNK) {
|
|
557
|
+
await connection
|
|
558
|
+
.insertInto(table)
|
|
559
|
+
.values(rows.slice(index, index + INSERT_CHUNK))
|
|
560
|
+
.execute();
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* A name no role or permission can have, returned when an id-addressed
|
|
566
|
+
* lookup finds nothing. Returning this rather than throwing keeps
|
|
567
|
+
* `hasAnyRole([someDeletedId, "admin"])` answering the question it was
|
|
568
|
+
* asked; `\u0000` cannot appear in a name that came from the map, because
|
|
569
|
+
* the map's own keys use it as a separator.
|
|
570
|
+
*/
|
|
571
|
+
const UNMATCHABLE = "\u0000unmatchable";
|
|
572
|
+
const INSERT_CHUNK = 1_000;
|
|
573
|
+
//# sourceMappingURL=permission-registrar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-registrar.js","sourceRoot":"","sources":["../src/permission-registrar.ts"],"names":[],"mappings":"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"}
|