Initial Commit
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
# permission-middleware
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Provides framework-agnostic permission checking middleware for `@suaveplan/permissions`. The `createPermissionMiddleware` factory returns a `(req, res, next)` function that reads the authenticated user from `req.user`, checks the configured permission via the adapter, and calls `next(PermissionsError)` on denial.
|
||||
|
||||
The `checkPermission` function provides a one-off convenience check without creating a full engine instance, useful for route handlers that need a single inline permission assertion.
|
||||
|
||||
## Features
|
||||
|
||||
- `createPermissionMiddleware(options)` — factory returning `MiddlewareFn`
|
||||
- `checkPermission(userId, resource, action, adapter)` — one-off policy evaluation
|
||||
- User extraction from `req.user.userId` or `req.user.sub` (JWT-compatible)
|
||||
- `ResourceExtractor` and `UserExtractor` type exports
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { createPermissionMiddleware, MemoryAdapter } from "@suaveplan/permissions";
|
||||
|
||||
const adapter = new MemoryAdapter();
|
||||
const mw = createPermissionMiddleware({
|
||||
resource: "posts",
|
||||
action: "delete",
|
||||
adapter,
|
||||
});
|
||||
// Attach to route: app.delete("/posts/:id", verifyJwt, mw, handler)
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { checkPermission } from "@suaveplan/permissions";
|
||||
import { MemoryAdapter } from "@suaveplan/permissions";
|
||||
|
||||
const adapter = new MemoryAdapter();
|
||||
|
||||
// Route handler inline check
|
||||
async function deletePost(userId: string, postId: string) {
|
||||
const result = await checkPermission(userId, "posts", "delete", adapter);
|
||||
if (!result.allowed) throw new Error(result.reason);
|
||||
// ... proceed with deletion
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `createPermissionMiddleware(options): MiddlewareFn`
|
||||
|
||||
Options: `resource`, `action`, `adapter?`.
|
||||
|
||||
Reads user from `req.user.userId` or `req.user.sub`. Calls `next(PermissionsError)` if no user, no adapter, or permission denied.
|
||||
|
||||
### `checkPermission(userId, resource, action, adapter): Promise<PolicyResult>`
|
||||
|
||||
Creates a transient `PolicyEngine` and evaluates one permission check.
|
||||
|
||||
### `ResourceExtractor`
|
||||
|
||||
`(req: unknown) => string` — type alias.
|
||||
|
||||
### `UserExtractor`
|
||||
|
||||
`(req: unknown) => string | null` — type alias.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The middleware user extraction checks both `userId` (from a `UserContext`) and `sub` (from a `JWTPayload`) to support both `@suaveplan/auth`'s `verifyTokenMiddleware` (which attaches `req.user` as `JWTPayload`) and custom middleware that attaches `req.user` as `UserContext`. No adapter means the middleware fails closed with a `PERM_CODES.ADAPTER_ERROR`, preventing accidental open access when misconfigured.
|
||||
Reference in New Issue
Block a user