Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
export {
CRUD_PERMISSIONS,
createAdminRole,
createEditorRole,
createOwnerRole,
createViewerRole,
} from "./role-presets.js";

View File

@@ -0,0 +1,65 @@
# role-presets
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
Provides pre-built role factories and permission bundles for the most common access-control patterns in `@suaveplan/permissions`. Rather than requiring every application to redefine the same admin/viewer/editor roles from scratch, the presets offer sensible defaults that can be used directly or overridden with a custom permissions array.
## Features
- `createAdminRole` — full wildcard `*:*` permissions, system-protected
- `createViewerRole` — `read` and `list` across all resources
- `createEditorRole` — `read`, `list`, `create`, `update` across all resources
- `createOwnerRole` — full wildcard permissions (like admin but semantically for resource owners)
- `CRUD_PERMISSIONS` — pre-built permission sets for `posts` and `users` resources
## Usage: Basic Example
```ts
import { createAdminRole, createViewerRole } from "@suaveplan/permissions";
import { MemoryAdapter } from "@suaveplan/permissions";
const adapter = new MemoryAdapter();
await adapter.createRole(createAdminRole());
await adapter.createRole(createViewerRole());
```
## Usage: Advanced Example
```ts
import { createEditorRole } from "@suaveplan/permissions";
// Override permissions
const customEditor = createEditorRole([
{ id: "editor:posts:write", resource: "posts", action: "create" },
{ id: "editor:posts:read", resource: "posts", action: "read" },
]);
```
## API Reference
### `createAdminRole(permissions?): Role`
Returns a system role with `id: "admin"` and `isSystem: true`. Default permissions: `{ resource: "*", action: "*" }`.
### `createViewerRole(permissions?): Role`
Returns a system role with `id: "viewer"`. Default: `read` and `list` on all resources.
### `createEditorRole(permissions?): Role`
Returns a system role with `id: "editor"`. Default: `read`, `list`, `create`, `update` on all resources.
### `createOwnerRole(permissions?): Role`
Returns a system role with `id: "owner"`. Default: wildcard on all resources.
### `CRUD_PERMISSIONS`
`Record<string, Permission[]>` — pre-built permission sets for `posts` and `users` resources.
## Implementation Notes
All preset roles have `isSystem: true` set, which means `RoleManager.updateRole` and `RoleManager.deleteRole` will throw `SystemRoleMutationError` to prevent accidental modification. If you need to customise a system role, either pass a custom `permissions` array to the factory, or create a new non-system role and assign it alongside the preset.

View File

@@ -0,0 +1,76 @@
import { describe, expect, it } from "@suaveplan/testing/runner";
import {
CRUD_PERMISSIONS,
createAdminRole,
createEditorRole,
createOwnerRole,
createViewerRole,
} from "./role-presets.js";
describe("createAdminRole", () => {
it("has correct id and isSystem", { timeout: 5000 }, () => {
const role = createAdminRole();
expect(role.id).toBe("admin");
expect(role.isSystem).toBe(true);
});
it("has wildcard permission by default", { timeout: 5000 }, () => {
const role = createAdminRole();
expect(role.permissions[0]?.action).toBe("*");
});
it("accepts custom permissions", { timeout: 5000 }, () => {
const custom = [{ id: "x", resource: "r", action: "read" }];
const role = createAdminRole(custom);
expect(role.permissions).toEqual(custom);
});
});
describe("createViewerRole", () => {
it("has correct id", { timeout: 5000 }, () => {
expect(createViewerRole().id).toBe("viewer");
});
it("has read and list permissions", { timeout: 5000 }, () => {
const role = createViewerRole();
const actions = role.permissions.map((p) => p.action);
expect(actions).toContain("read");
expect(actions).toContain("list");
});
});
describe("createEditorRole", () => {
it("has correct id", { timeout: 5000 }, () => {
expect(createEditorRole().id).toBe("editor");
});
it("includes create and update", { timeout: 5000 }, () => {
const role = createEditorRole();
const actions = role.permissions.map((p) => p.action);
expect(actions).toContain("create");
expect(actions).toContain("update");
});
});
describe("createOwnerRole", () => {
it("has correct id", { timeout: 5000 }, () => {
expect(createOwnerRole().id).toBe("owner");
});
it("has wildcard permission", { timeout: 5000 }, () => {
const role = createOwnerRole();
expect(role.permissions[0]?.action).toBe("*");
});
});
describe("CRUD_PERMISSIONS", () => {
it("has posts permissions", { timeout: 5000 }, () => {
expect(CRUD_PERMISSIONS["posts"]).toBeDefined();
expect(CRUD_PERMISSIONS["posts"]).toHaveLength(5);
});
it("has users permissions", { timeout: 5000 }, () => {
expect(CRUD_PERMISSIONS["users"]).toBeDefined();
expect(CRUD_PERMISSIONS["users"]).toHaveLength(5);
});
});

View File

@@ -0,0 +1,80 @@
import type { Permission, Role } from "../../types/permissions.types.js";
/** Default CRUD permissions for common resources. */
export const CRUD_PERMISSIONS: Record<string, Permission[]> = {
posts: [
{ id: "posts:create", resource: "posts", action: "create" },
{ id: "posts:read", resource: "posts", action: "read" },
{ id: "posts:update", resource: "posts", action: "update" },
{ id: "posts:delete", resource: "posts", action: "delete" },
{ id: "posts:list", resource: "posts", action: "list" },
],
users: [
{ id: "users:create", resource: "users", action: "create" },
{ id: "users:read", resource: "users", action: "read" },
{ id: "users:update", resource: "users", action: "update" },
{ id: "users:delete", resource: "users", action: "delete" },
{ id: "users:list", resource: "users", action: "list" },
],
};
/**
* Create a pre-built admin role with full wildcard permissions.
*/
export function createAdminRole(permissions?: Permission[]): Role {
return {
id: "admin",
name: "Admin",
isSystem: true,
permissions: permissions ?? [
{ id: "admin:*", resource: "*", action: "*" },
],
};
}
/**
* Create a pre-built viewer role with read-only permissions.
*/
export function createViewerRole(permissions?: Permission[]): Role {
return {
id: "viewer",
name: "Viewer",
isSystem: true,
permissions: permissions ?? [
{ id: "viewer:read", resource: "*", action: "read" },
{ id: "viewer:list", resource: "*", action: "list" },
],
};
}
/**
* Create a pre-built editor role with create, read, update, and list
* permissions.
*/
export function createEditorRole(permissions?: Permission[]): Role {
return {
id: "editor",
name: "Editor",
isSystem: true,
permissions: permissions ?? [
{ id: "editor:read", resource: "*", action: "read" },
{ id: "editor:list", resource: "*", action: "list" },
{ id: "editor:create", resource: "*", action: "create" },
{ id: "editor:update", resource: "*", action: "update" },
],
};
}
/**
* Create a pre-built owner role with full permissions including delete.
*/
export function createOwnerRole(permissions?: Permission[]): Role {
return {
id: "owner",
name: "Owner",
isSystem: true,
permissions: permissions ?? [
{ id: "owner:*", resource: "*", action: "*" },
],
};
}