feat: RBAC+web, scoped RBAC (org/event) with invitations + member management + admin web UI - #2
Open
cbot918 wants to merge 7 commits into
Open
feat: RBAC+web, scoped RBAC (org/event) with invitations + member management + admin web UI#2cbot918 wants to merge 7 commits into
cbot918 wants to merge 7 commits into
Conversation
Replace JWT-embedded permissions with TokenVersion + Cache strategy:
- Add tokenVersion (Int, default 1) to Member model
- Minimize JWT payload to { sub, v } only
- Cache permissions & tokenVersion via @nestjs/cache-manager on login
- JwtStrategy.validate() verifies tokenVersion and loads permissions from cache (DB fallback on miss)
- Add AuthService.bumpTokenVersion() to revoke tokens immediately
- Add PermissionsCacheService for centralized cache operations
Benefits:
- Tokens can be revoked instantly without waiting for JWT expiry
- JWT payload stays small regardless of permission count
- Zero DB queries on requests when cache is warm
Verified with manual E2E test: old token returns 401 after bump, new login restores access.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Add comprehensive unit tests for the new auth architecture: - PermissionsCacheService: set/get/invalidate for permissions & tokenVersion - JwtStrategy: cache hit/miss, tokenVersion mismatch, revoked token, deleted user - PermissionGuard: unauthenticated, missing permissions, all permissions granted - AuthService: getUserPermissions, devLogin, bumpTokenVersion, invalidateUserCache Also update jest config: - transformIgnorePatterns: allow ESM packages (arctic, passport-jwt) - moduleNameMapper: map src/ paths & strip .js extensions for Prisma 7 26 tests passing, 0 failing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…yle)
Reworks the flat global RBAC into a two-layer scoped model and adds an
email invitation flow, modelled on KKTIX's organization/activity permissions.
- schema: add Organization, Membership (replaces global MemberRole, carries
scopeType + org/activity FK), Invitation; Role.scope, Activity.organizationId.
Migration carries existing member_roles over as PLATFORM-scoped.
- auth: getScopedPermissions returns { platform, org, event } buckets, cached;
JWT still only carries { sub, v } (reuses tokenVersion revocation).
- guard: @RequirePermissions({ scope, param, perms }); PLATFORM grants apply
everywhere; ORG permissions cascade down to that org's events.
- api: Organization CRUD (creator auto-becomes Owner), scoped membership
management, full invitation flow (invite/accept/reject/resend/revoke,
7-day expiry, email-match, MailService log stub).
- seed: scoped permission catalogue + KKTIX default roles per scope.
- dev: GET /roles/catalog (dev-only) + extended /ui mock for manual testing.
- docs: KKTIX research note + HANDOFF.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds MemberModule (controller/service/dto) for listing and managing platform members, registered in AppModule. Minor activity dto/service tweaks + specs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Vite + React + shadcn/ui admin for the scoped RBAC: members, roles, permission codes, and organization-member role assignment. Talks to the backend via a relative /api base + vite proxy (no hard-coded origin). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
jest-e2e.setup aborts unless TEST_DATABASE_URL is set and points at localhost, so the destructive e2e suite can never wipe a remote DB. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…kups Adds HANDOFF-permission-admin.md (frontend progress + TODO), refreshes .env.example / docs, and ignores *.env.bak so local secret backups can never be committed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
中文快速:
Summary
Builds out the scoped RBAC system (modeled after KKTIX's org/event permission
model) and adds an admin web UI to manage it. Extends the existing
JwtAuthGuard/PermissionGuard foundation with a two-layer scope, an email
invitation flow, a member-management module, and a React admin front end.
What's included
Backend
PLATFORM/ORG/EVENT); org permissionscascade to events under that org (resolved at request time). JWT stays minimal
(
{ sub, v }); permissions resolved server-side and cached, with atokenVersionbump to revoke instantly.pending → accepted/rejected state machine (7-day expiry), resend included.
jest-e2e.setupaborts unlessTEST_DATABASE_URLisset and local, so the destructive e2e suite can never touch a remote DB.
Frontend (
web/, Vite + React + shadcn/ui)assignment. Talks to the API via a relative base + dev proxy (no hard-coded
origin), so it runs against the backend on any port.
Status / scope
Honest about what's done vs. pending, so review expectations are clear:
invitation UI (backend endpoints for both already exist). Tracked in
HANDOFF-permission-admin.md.Testing
TEST_DATABASE_URLis unset orpoints at a remote host.
roles + permission-code tabs, and org-member role assignment (assignment
persisted to the DB).
Happy to walk through anything or adjust scope. "Allow edits by maintainers"
is enabled — feel free to push test commits or tweaks directly to this branch.