feat(auth): role-based access control (roles, permissions, guards) - #40
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 17 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughChangesThe auth package now snapshots roles and permissions when it creates sessions. It adds RBAC helpers, fail-closed guards, middleware adapters, public exports, tests, and release documentation. RBAC authorization
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Request
participant toMiddleware
participant SessionGuard
participant Next
Request->>toMiddleware: invoke protected route middleware
toMiddleware->>SessionGuard: resolve session and evaluate access
alt authorized
SessionGuard->>Next: continue request
else signed out or unauthorized
SessionGuard-->>toMiddleware: return 401 or 403 result
toMiddleware-->>Request: return response or redirect
end
Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/auth/src/auth.ts`:
- Around line 175-181: Clone the roles and permissions arrays before assigning
them to snapshot in the authorization snapshot flow, covering both
config.resolveRoles results and user fallback values. Update the assignments in
the surrounding session snapshot logic so later mutations of the source objects
cannot alter stored session authorization state.
In `@packages/auth/src/rbac.test.ts`:
- Line 171: Update the cookie extraction in the RBAC tests at all three
locations to validate the optional result of getSetCookie()[0] before calling
split, removing the unsafe cast and handling an absent session cookie
explicitly.
In `@packages/auth/src/rbac.ts`:
- Around line 36-38: Update hasAllPermissions to explicitly return false when
session is null, before evaluating permissions.every; preserve the existing
all-permissions check for present sessions, including empty permission lists.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 873484c5-4069-4bf6-bf43-0f791a623c1a
📒 Files selected for processing (7)
.changeset/rbac.mdROADMAP.mdpackages/auth/src/auth.tspackages/auth/src/index.tspackages/auth/src/rbac.test.tspackages/auth/src/rbac.tspackages/auth/src/types.ts
…ull session Addresses CodeRabbit review findings on the RBAC PR: - snapshotUser now shallow-copies roles/permissions from both the resolveRoles result and the AuthUser fallback, so mutating the source can no longer change an issued session's authorization (major) - hasAllPermissions returns false for a null session even with an empty list, fixing the vacuous .every() success; hasAnyRole gets the same guard (major) - tests use the existing extractCookie helper with an explicit requireSessionCookie that fails on an absent cookie instead of an unchecked getSetCookie()[0] cast (minor) - adds regression tests: null session + empty lists, and snapshot immunity to source-array and resolver-result mutation
Part B — Authorization (RBAC)
What was verified before building
@thexjs/authalready had sessions + a session store but noroles/permissions concept, and that the framework's route middleware
(
MiddlewareFnviaexport const middleware) is the idiomatic enforcementpoint — so guards are built as middleware, not as a parallel auth mechanism.
@thexjs/authalready depends on@thexjs/core(forcheckCsrf),so importing
MiddlewareFnadds no new dependency.What was added
AuthUsergains optionalrolesandpermissions; they're snapshotted into the session at creation time.resolveRoleshook ondefineAuth— apps can derive roles from a DB orservice at sign-in. Without it, roles come from the provider's user object.
hasRole,hasAnyRole,hasPermission,hasAllPermissions(fail-closed onnullsessions).requireRole(...),requirePermission(...),requireAuth()returning
SessionGuards that fail closed: signed out → 401, authenticatedbut missing role/permission → 403.
toMiddleware(getSession, guard, opts)andauth.requireRole(roles, opts)/auth.requirePermission(...)/auth.requireAuth()/auth.guard(...)returning coreMiddlewareFns forexport const middleware, with optionalredirectTofor signed-out users.@thexjs/auth; changeset:minor.Tests added
packages/auth/src/rbac.test.ts(17 tests): role/permission helpers,guard fail-closed semantics, multi-role any-match, no-roles
authenticate-only, middleware 401/redirect/pass-through via a real session,
and
resolveRolessnapshotting.Verification
bun run lint— clean (340 files)bunx tsc --noEmit -p packages/auth— cleanbun test packages/auth/— 38 pass / 0 fail (92 expects)pre-existing
buildVercelOutputEISDIR race in the adapter test(bundles React from Bun's module cache concurrently; reproduces on clean
main2/15 runs, unrelated to this change).Summary by CodeRabbit
New Features
Documentation