@cfast/permissions 0.5.1 → 0.7.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/dist/{client-DpwiMpD0.d.ts → client-DyadVgmx.d.ts} +1 -1
- package/dist/client.d.ts +1 -1
- package/dist/index.d.ts +59 -3
- package/dist/index.js +39 -1
- package/llms.txt +27 -0
- package/package.json +1 -1
|
@@ -420,4 +420,4 @@ declare class PermissionRegistrationError extends Error {
|
|
|
420
420
|
constructor(subject: string, availableTables: readonly string[]);
|
|
421
421
|
}
|
|
422
422
|
|
|
423
|
-
export {
|
|
423
|
+
export { type CrudAction as C, type DrizzleTable as D, ForbiddenError as F, type Grant as G, type LookupDb as L, type PermissionsConfig as P, type SchemaMap as S, type TableName as T, type WithLookups as W, type Permissions as a, type PermissionAction as b, type SubjectInput as c, type WhereClause as d, type PermissionDescriptor as e, type PermissionCheckResult as f, CRUD_ACTIONS as g, type ColumnsOf as h, type GrantFn as i, type LookupFn as j, PermissionRegistrationError as k, type SqlNameOf as l, getTableName as m };
|
package/dist/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { C as CrudAction, F as ForbiddenError, b as PermissionAction, f as PermissionCheckResult, e as PermissionDescriptor } from './client-DyadVgmx.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as PermissionsConfig, a as Permissions, S as SchemaMap, b as PermissionAction, c as SubjectInput, W as WithLookups, d as WhereClause, G as Grant, e as PermissionDescriptor, f as PermissionCheckResult } from './client-
|
|
2
|
-
export {
|
|
1
|
+
import { P as PermissionsConfig, a as Permissions, S as SchemaMap, b as PermissionAction, c as SubjectInput, W as WithLookups, d as WhereClause, G as Grant, e as PermissionDescriptor, f as PermissionCheckResult, C as CrudAction, D as DrizzleTable } from './client-DyadVgmx.js';
|
|
2
|
+
export { g as CRUD_ACTIONS, h as ColumnsOf, F as ForbiddenError, i as GrantFn, L as LookupDb, j as LookupFn, k as PermissionRegistrationError, l as SqlNameOf, T as TableName, m as getTableName } from './client-DyadVgmx.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Creates a permission configuration that can be shared between server-side
|
|
@@ -263,4 +263,60 @@ type UserWithRoles = {
|
|
|
263
263
|
declare function resolveGrants(permissions: Permissions, user: UserWithRoles): Grant[];
|
|
264
264
|
declare function resolveGrants(permissions: Permissions, roles: readonly string[]): Grant[];
|
|
265
265
|
|
|
266
|
-
|
|
266
|
+
/**
|
|
267
|
+
* A single granted action for a table, including the matching grants.
|
|
268
|
+
*
|
|
269
|
+
* - `unrestricted: true` means at least one grant has no `where` clause,
|
|
270
|
+
* so the action is unconditionally permitted for every row.
|
|
271
|
+
* - `unrestricted: false` means all matching grants have `where` clauses,
|
|
272
|
+
* so whether the action is permitted depends on the specific row.
|
|
273
|
+
*/
|
|
274
|
+
type GrantedAction = {
|
|
275
|
+
action: CrudAction;
|
|
276
|
+
grants: Grant[];
|
|
277
|
+
unrestricted: boolean;
|
|
278
|
+
};
|
|
279
|
+
/**
|
|
280
|
+
* Returns the distinct CRUD actions that are granted for a given table.
|
|
281
|
+
*
|
|
282
|
+
* `manage` grants are expanded into the four CRUD actions. For each action,
|
|
283
|
+
* the result includes the matching grants and whether any of them is
|
|
284
|
+
* unrestricted (no `where` clause). Actions with no matching grant at all
|
|
285
|
+
* are excluded from the result.
|
|
286
|
+
*
|
|
287
|
+
* Used by `@cfast/db` to build `_can` annotations on query results.
|
|
288
|
+
*
|
|
289
|
+
* @param grants - The user's resolved permission grants.
|
|
290
|
+
* @param table - The Drizzle table to check grants against.
|
|
291
|
+
* @returns Array of GrantedAction objects for each permitted action.
|
|
292
|
+
*/
|
|
293
|
+
declare function getGrantedActions(grants: Grant[], table: DrizzleTable): GrantedAction[];
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Resolves table-level CRUD permissions for every table in a schema.
|
|
297
|
+
*
|
|
298
|
+
* Iterates each key in the schema map, extracts its table name, and calls
|
|
299
|
+
* {@link can} for each of the four CRUD actions (`read`, `create`, `update`,
|
|
300
|
+
* `delete`). Returns a flat, serializable map suitable for embedding in
|
|
301
|
+
* loader data and sending to the client.
|
|
302
|
+
*
|
|
303
|
+
* This is a pure grant-structural check — no database access, no SQL.
|
|
304
|
+
* Row-level `where` clauses on grants are ignored; the result reflects
|
|
305
|
+
* whether the user has *any* grant for the action on the table.
|
|
306
|
+
*
|
|
307
|
+
* @param grants - The user's resolved permission grants.
|
|
308
|
+
* @param schema - A schema map (e.g. `import * as schema from "./schema"`).
|
|
309
|
+
* @returns A record keyed by SQL table name, each mapping CRUD actions to booleans.
|
|
310
|
+
*
|
|
311
|
+
* @example
|
|
312
|
+
* ```ts
|
|
313
|
+
* import { resolveTablePermissions } from "@cfast/permissions";
|
|
314
|
+
* import * as schema from "../db/schema";
|
|
315
|
+
*
|
|
316
|
+
* const perms = resolveTablePermissions(grants, schema);
|
|
317
|
+
* // { posts: { read: true, create: true, update: false, delete: false }, ... }
|
|
318
|
+
* ```
|
|
319
|
+
*/
|
|
320
|
+
declare function resolveTablePermissions(grants: Grant[], schema: SchemaMap): Record<string, Record<CrudAction, boolean>>;
|
|
321
|
+
|
|
322
|
+
export { CrudAction, DrizzleTable, Grant, type GrantedAction, PermissionAction, PermissionCheckResult, PermissionDescriptor, Permissions, PermissionsConfig, SchemaMap, SubjectInput, type UserWithRoles, WhereClause, WithLookups, can, checkPermissions, definePermissions, getGrantedActions, grant, resolveGrants, resolveTablePermissions };
|
package/dist/index.js
CHANGED
|
@@ -234,6 +234,42 @@ function resolveGrants(permissions, userOrRoles) {
|
|
|
234
234
|
}
|
|
235
235
|
return result;
|
|
236
236
|
}
|
|
237
|
+
|
|
238
|
+
// src/granted-actions.ts
|
|
239
|
+
function getGrantedActions(grants, table) {
|
|
240
|
+
const targetName = getTableName(table);
|
|
241
|
+
const result = [];
|
|
242
|
+
for (const action of CRUD_ACTIONS) {
|
|
243
|
+
const matching = grants.filter((g) => {
|
|
244
|
+
const actionOk = g.action === action || g.action === "manage";
|
|
245
|
+
if (!actionOk) return false;
|
|
246
|
+
if (g.subject === "all") return true;
|
|
247
|
+
if (g.subject === table) return true;
|
|
248
|
+
return getTableName(g.subject) === targetName;
|
|
249
|
+
});
|
|
250
|
+
if (matching.length === 0) continue;
|
|
251
|
+
const unrestricted = matching.some((g) => !g.where);
|
|
252
|
+
result.push({ action, grants: matching, unrestricted });
|
|
253
|
+
}
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/resolve-table-permissions.ts
|
|
258
|
+
function resolveTablePermissions(grants, schema) {
|
|
259
|
+
const result = {};
|
|
260
|
+
for (const key of Object.keys(schema)) {
|
|
261
|
+
const table = schema[key];
|
|
262
|
+
const tableName = getTableName(table);
|
|
263
|
+
if (tableName === "unknown") continue;
|
|
264
|
+
if (result[tableName]) continue;
|
|
265
|
+
const perms = {};
|
|
266
|
+
for (const action of CRUD_ACTIONS) {
|
|
267
|
+
perms[action] = can(grants, action, table);
|
|
268
|
+
}
|
|
269
|
+
result[tableName] = perms;
|
|
270
|
+
}
|
|
271
|
+
return result;
|
|
272
|
+
}
|
|
237
273
|
export {
|
|
238
274
|
CRUD_ACTIONS,
|
|
239
275
|
ForbiddenError,
|
|
@@ -241,7 +277,9 @@ export {
|
|
|
241
277
|
can,
|
|
242
278
|
checkPermissions,
|
|
243
279
|
definePermissions,
|
|
280
|
+
getGrantedActions,
|
|
244
281
|
getTableName,
|
|
245
282
|
grant,
|
|
246
|
-
resolveGrants
|
|
283
|
+
resolveGrants,
|
|
284
|
+
resolveTablePermissions
|
|
247
285
|
};
|
package/llms.txt
CHANGED
|
@@ -209,11 +209,38 @@ can<typeof schema>(grants, "create", "posts") // ✓ string form, type-ch
|
|
|
209
209
|
// can<typeof schema>(grants, "create", "unknownTable") // ✗ TypeScript error
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
### `getGrantedActions(grants, table): GrantedAction[]`
|
|
213
|
+
```typescript
|
|
214
|
+
import { getGrantedActions } from "@cfast/permissions";
|
|
215
|
+
function getGrantedActions(grants: Grant[], table: DrizzleTable): GrantedAction[]
|
|
216
|
+
|
|
217
|
+
type GrantedAction = {
|
|
218
|
+
action: CrudAction; // "read" | "create" | "update" | "delete"
|
|
219
|
+
grants: Grant[]; // the matching grants
|
|
220
|
+
unrestricted: boolean; // true if any grant has no `where` clause
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
Returns the distinct CRUD actions that are granted for a given table. `manage` grants are expanded into the four CRUD actions. For each action, the result includes the matching grants and whether any of them is unrestricted (no `where` clause). Actions with no matching grant are excluded.
|
|
224
|
+
|
|
225
|
+
Used internally by `@cfast/db` to build row-level `_can` annotations on query results.
|
|
226
|
+
|
|
212
227
|
### `CRUD_ACTIONS`
|
|
213
228
|
```typescript
|
|
214
229
|
const CRUD_ACTIONS: readonly CrudAction[] = ["read", "create", "update", "delete"];
|
|
215
230
|
```
|
|
216
231
|
|
|
232
|
+
### `resolveTablePermissions(grants, schema): Record<string, Record<CrudAction, boolean>>`
|
|
233
|
+
```typescript
|
|
234
|
+
import { resolveTablePermissions } from "@cfast/permissions";
|
|
235
|
+
import * as schema from "../db/schema";
|
|
236
|
+
|
|
237
|
+
const perms = resolveTablePermissions(grants, schema);
|
|
238
|
+
// { posts: { read: true, create: true, update: false, delete: false }, ... }
|
|
239
|
+
```
|
|
240
|
+
Pure grant-structural check for every table in the schema. No DB, no SQL. Returns a serializable map. Skips non-table entries (e.g. relation objects) and deduplicates when multiple JS keys map to the same SQL name.
|
|
241
|
+
|
|
242
|
+
Used internally by `cfastJson()` from `@cfast/actions` to embed table permissions in loader data.
|
|
243
|
+
|
|
217
244
|
### Client entrypoint
|
|
218
245
|
```typescript
|
|
219
246
|
import { ForbiddenError, can } from "@cfast/permissions/client";
|