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,83 @@
|
||||
-- Roles and permissions system.
|
||||
-- Makes User.role nullable (null means Guest), backfills legacy uppercase roles
|
||||
-- to the new lowercase enum, adds the RolePermission table, and seeds default
|
||||
-- permission sets. Safe and idempotent to run on a live database.
|
||||
|
||||
-- RedefineTables: make User.role nullable and drop its default, converting values.
|
||||
PRAGMA defer_foreign_keys=ON;
|
||||
PRAGMA foreign_keys=OFF;
|
||||
CREATE TABLE "new_User" (
|
||||
"id" TEXT NOT NULL PRIMARY KEY,
|
||||
"pubkey" TEXT NOT NULL,
|
||||
"role" TEXT,
|
||||
"displayName" TEXT,
|
||||
"username" TEXT,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
"updatedAt" DATETIME NOT NULL
|
||||
);
|
||||
INSERT INTO "new_User" ("id", "pubkey", "role", "displayName", "username", "createdAt", "updatedAt")
|
||||
SELECT
|
||||
"id",
|
||||
"pubkey",
|
||||
CASE
|
||||
WHEN "role" = 'ADMIN' THEN 'admin'
|
||||
WHEN "role" = 'MODERATOR' THEN 'moderator'
|
||||
WHEN "role" = 'WRITER' THEN 'writer'
|
||||
WHEN "role" IN ('admin', 'moderator', 'writer') THEN "role"
|
||||
ELSE NULL
|
||||
END,
|
||||
"displayName",
|
||||
"username",
|
||||
"createdAt",
|
||||
"updatedAt"
|
||||
FROM "User";
|
||||
DROP TABLE "User";
|
||||
ALTER TABLE "new_User" RENAME TO "User";
|
||||
CREATE UNIQUE INDEX "User_pubkey_key" ON "User"("pubkey");
|
||||
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
|
||||
PRAGMA foreign_keys=ON;
|
||||
PRAGMA defer_foreign_keys=OFF;
|
||||
|
||||
-- CreateTable
|
||||
CREATE TABLE IF NOT EXISTS "RolePermission" (
|
||||
"role" TEXT NOT NULL,
|
||||
"permission" TEXT NOT NULL,
|
||||
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
PRIMARY KEY ("role", "permission")
|
||||
);
|
||||
|
||||
-- Seed default permission sets. INSERT OR IGNORE keeps this idempotent and never
|
||||
-- clobbers permissions an operator has already customized at runtime.
|
||||
INSERT OR IGNORE INTO "RolePermission" ("role", "permission") VALUES
|
||||
('admin', 'events.create'),
|
||||
('admin', 'events.edit'),
|
||||
('admin', 'events.delete'),
|
||||
('admin', 'organizers.manage'),
|
||||
('admin', 'gallery.upload'),
|
||||
('admin', 'gallery.delete'),
|
||||
('admin', 'blog.draft'),
|
||||
('admin', 'blog.publish'),
|
||||
('admin', 'blog.delete'),
|
||||
('admin', 'faq.manage'),
|
||||
('admin', 'submissions.review'),
|
||||
('admin', 'board.manage'),
|
||||
('admin', 'moderation.act'),
|
||||
('admin', 'categories.manage'),
|
||||
('admin', 'users.assign_role'),
|
||||
('admin', 'nip05.assign'),
|
||||
('admin', 'relays.manage'),
|
||||
('admin', 'settings.edit'),
|
||||
('admin', 'nostr_tools.use'),
|
||||
('moderator', 'events.create'),
|
||||
('moderator', 'events.edit'),
|
||||
('moderator', 'events.delete'),
|
||||
('moderator', 'submissions.review'),
|
||||
('moderator', 'moderation.act'),
|
||||
('moderator', 'gallery.upload'),
|
||||
('moderator', 'board.manage'),
|
||||
('moderator', 'categories.manage'),
|
||||
('moderator', 'faq.manage'),
|
||||
('writer', 'blog.draft'),
|
||||
('writer', 'gallery.upload'),
|
||||
('writer', 'events.create');
|
||||
Reference in New Issue
Block a user