feat: add scoped API keys for programmatic site access
Introduce ApiKey model, CRUD endpoints, and admin UI so agents can authenticate with permission-scoped keys. Normalize pubkeys to hex on login, dedupe legacy npub/hex user rows, and ignore .cursor in git. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -22,6 +22,7 @@ import {
|
||||
MessageSquare,
|
||||
Building2,
|
||||
KeyRound,
|
||||
Key,
|
||||
} from "lucide-react";
|
||||
|
||||
// Each item is shown when the user holds any of its permissions. Items with no
|
||||
@@ -44,6 +45,7 @@ const navItems: {
|
||||
{ href: "/admin/categories", label: "Categories", icon: Tag, permissions: ["categories.manage"] },
|
||||
{ href: "/admin/users", label: "Users", icon: Users, permissions: ["users.assign_role", "nip05.assign"] },
|
||||
{ href: "/admin/roles", label: "Roles", icon: KeyRound, permissions: ["roles.edit_permissions"] },
|
||||
{ href: "/admin/api-keys", label: "API Keys", icon: Key, permissions: ["api_keys.manage"] },
|
||||
{ href: "/admin/relays", label: "Relays", icon: Radio, permissions: ["relays.manage"] },
|
||||
{ href: "/admin/settings", label: "Settings", icon: Settings, permissions: ["settings.edit"] },
|
||||
{ href: "/admin/nostr", label: "Nostr Tools", icon: Wrench, permissions: ["nostr_tools.use"] },
|
||||
@@ -58,8 +60,8 @@ export function AdminSidebar() {
|
||||
: "";
|
||||
|
||||
return (
|
||||
<aside className="w-64 bg-surface-container-lowest min-h-screen p-6 flex flex-col shrink-0">
|
||||
<div className="mb-8">
|
||||
<aside className="w-64 bg-surface-container-lowest h-screen sticky top-0 p-6 flex flex-col shrink-0">
|
||||
<div className="mb-8 shrink-0">
|
||||
<Link href="/" className="text-primary-container font-bold text-xl">
|
||||
BBE Admin
|
||||
</Link>
|
||||
@@ -73,7 +75,7 @@ export function AdminSidebar() {
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className="mb-6">
|
||||
<div className="mb-6 shrink-0">
|
||||
<p className="text-on-surface/70 text-sm font-mono truncate">{shortPubkey}</p>
|
||||
<span
|
||||
className={cn(
|
||||
@@ -87,7 +89,7 @@ export function AdminSidebar() {
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<nav className="flex-1 space-y-1">
|
||||
<nav className="flex-1 overflow-y-auto min-h-0 space-y-1">
|
||||
{navItems
|
||||
.filter(
|
||||
(item) =>
|
||||
@@ -114,7 +116,7 @@ export function AdminSidebar() {
|
||||
})}
|
||||
</nav>
|
||||
|
||||
<div className="mt-auto space-y-2 pt-6">
|
||||
<div className="shrink-0 space-y-2 pt-6">
|
||||
<button
|
||||
onClick={logout}
|
||||
className="flex items-center gap-3 px-4 py-3 rounded-lg transition-colors text-on-surface/70 hover:text-on-surface hover:bg-surface-container w-full"
|
||||
|
||||
Reference in New Issue
Block a user