feat: roles/permissions system and Nostr profile display on admin users
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>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
# 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 to `ADMIN_PUBKEYS` when unset so existing
|
||||
deployments keep working.
|
||||
- **Permission registry**: a central list of granular keys in
|
||||
`backend/src/constants/permissions.ts` is 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.role` is now nullable (null means Guest) and uses the
|
||||
lowercase enum `admin`, `moderator`, `writer`. A new `RolePermission` table
|
||||
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`, and
|
||||
`PUT /api/users/:pubkey/role` (replacing `POST /api/users/promote` and
|
||||
`POST /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.
|
||||
Reference in New Issue
Block a user