Introduce granular role-based permissions with SuperAdmin env override, admin roles UI, and permission-gated API routes. Fix admin user Nostr metadata by batching relay profile fetches, normalizing npub pubkeys to hex, and adding reusable NostrAvatar/useNostrProfile components. Co-authored-by: Cursor <cursoragent@cursor.com>
2.2 KiB
2.2 KiB
Changelog
Unreleased
Roles and permissions system
Replaced the single moderator promote/demote toggle with a full role hierarchy and a runtime-editable, granular permission system.
- Role hierarchy: SuperAdmin (env-only) > Admin > Moderator > Writer > Guest (absence of a role). SuperAdmin always holds every permission and can never be edited, demoted, or removed through the UI.
- New env var
SUPERADMIN_PUBKEYS(comma-separated hex or npub) replaces the old env-admin concept. Falls back toADMIN_PUBKEYSwhen unset so existing deployments keep working. - Permission registry: a central list of granular keys in
backend/src/constants/permissions.tsis the single source of truth. Adding a key there surfaces it automatically in the API and the Roles matrix page. - Authorization: a single
requires(permission)guard replaces the old role-name middleware and is applied to every protected endpoint. Roles and permissions are resolved live per request, so a stale JWT no longer drives access. SuperAdmin bypasses all checks. - Data model:
User.roleis now nullable (null means Guest) and uses the lowercase enumadmin,moderator,writer. A newRolePermissiontable maps roles to permission keys. A migration backfills legacy uppercase roles and seeds default permission sets; it is idempotent and safe on a live database. - New endpoints:
GET /api/auth/me,GET /api/admin/permissions,GET /api/admin/roles,PUT /api/admin/roles/:role/permissions, andPUT /api/users/:pubkey/role(replacingPOST /api/users/promoteandPOST /api/users/demote). - Dashboard: User Management now uses a per-user role selector with hierarchy enforcement and a locked SuperAdmin badge. A new SuperAdmin-only Roles page renders a permission-by-role matrix. Nav items are gated on resolved permissions. The NIP-05 reserved-username assignment is unchanged.
Migration notes
After pulling, from backend run npm run migrate:deploy (or, for databases
created with db push, npm run db:baseline-and-migrate). Set
SUPERADMIN_PUBKEYS in your .env. Existing moderators become moderator,
existing database admins become admin, and prior env admins become SuperAdmin.