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:
+36
-5
@@ -24,10 +24,27 @@ export const api = {
|
||||
body: JSON.stringify({ pubkey }),
|
||||
}),
|
||||
verify: (pubkey: string, signedEvent: any) =>
|
||||
request<{ token: string; user: { pubkey: string; role: string; username?: string } }>("/auth/verify", {
|
||||
request<{
|
||||
token: string;
|
||||
user: {
|
||||
pubkey: string;
|
||||
role: string;
|
||||
isSuperAdmin?: boolean;
|
||||
permissions?: string[];
|
||||
username?: string;
|
||||
};
|
||||
}>("/auth/verify", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ pubkey, signedEvent }),
|
||||
}),
|
||||
getMe: () =>
|
||||
request<{
|
||||
pubkey: string;
|
||||
role: string;
|
||||
isSuperAdmin: boolean;
|
||||
permissions: string[];
|
||||
username?: string;
|
||||
}>("/auth/me"),
|
||||
|
||||
// Posts
|
||||
getPosts: (params?: { category?: string; page?: number; limit?: number; all?: boolean }) => {
|
||||
@@ -93,16 +110,30 @@ export const api = {
|
||||
|
||||
// Users
|
||||
getUsers: () => request<any[]>("/users"),
|
||||
promoteUser: (pubkey: string) =>
|
||||
request<any>("/users/promote", { method: "POST", body: JSON.stringify({ pubkey }) }),
|
||||
demoteUser: (pubkey: string) =>
|
||||
request<any>("/users/demote", { method: "POST", body: JSON.stringify({ pubkey }) }),
|
||||
setUserRole: (pubkey: string, role: string | null) =>
|
||||
request<any>(`/users/${encodeURIComponent(pubkey)}/role`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({ role }),
|
||||
}),
|
||||
updateUserUsername: (pubkey: string, username: string) =>
|
||||
request<any>(`/users/${encodeURIComponent(pubkey)}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({ username }),
|
||||
}),
|
||||
|
||||
// Roles and permissions
|
||||
getPermissionRegistry: () =>
|
||||
request<{ permissions: { key: string; label: string; group: string }[]; roles: string[] }>(
|
||||
"/admin/permissions"
|
||||
),
|
||||
getRolePermissions: () =>
|
||||
request<{ roles: { role: string; permissions: string[] }[] }>("/admin/roles"),
|
||||
updateRolePermissions: (role: string, permissions: string[]) =>
|
||||
request<{ role: string; permissions: string[] }>(
|
||||
`/admin/roles/${encodeURIComponent(role)}/permissions`,
|
||||
{ method: "PUT", body: JSON.stringify({ permissions }) }
|
||||
),
|
||||
|
||||
// Categories
|
||||
getCategories: () => request<any[]>("/categories"),
|
||||
createCategory: (data: { name: string; slug: string }) =>
|
||||
|
||||
Reference in New Issue
Block a user