From abc6dc2860816d4a9511f8d53e15cb2f4fb9cfc3 Mon Sep 17 00:00:00 2001 From: 1amKhush Date: Fri, 17 Apr 2026 05:57:10 +0530 Subject: [PATCH] feat(rbac): implement NIP-29 room roles and permission gating (#47) --- src/app/components/EventMenu.svelte | 8 +- src/app/components/ProfileDetail.svelte | 43 +- src/app/components/RoleBadge.svelte | 25 ++ src/app/components/RoomDetail.svelte | 50 ++- src/app/components/RoomMembers.svelte | 140 ++++-- src/app/components/SpaceDetail.svelte | 6 +- src/app/components/SpaceMembers.svelte | 184 ++++++-- src/app/core/roles.ts | 542 ++++++++++++++++++++++++ src/app/core/state.ts | 88 ++-- src/app/core/sync.ts | 3 +- src/app/util/storage.ts | 2 + 11 files changed, 951 insertions(+), 140 deletions(-) create mode 100644 src/app/components/RoleBadge.svelte create mode 100644 src/app/core/roles.ts diff --git a/src/app/components/EventMenu.svelte b/src/app/components/EventMenu.svelte index 174a28b5..0527c34e 100644 --- a/src/app/components/EventMenu.svelte +++ b/src/app/components/EventMenu.svelte @@ -3,7 +3,7 @@ import type {Snippet} from "svelte" import {goto} from "$app/navigation" import type {TrustedEvent} from "@welshman/util" - import {COMMENT, ManagementMethod} from "@welshman/util" + import {COMMENT, ManagementMethod, getTagValue} from "@welshman/util" import {pubkey, repository, relaysByUrl, manageRelay} from "@welshman/app" import ShareCircle from "@assets/icons/share-circle.svg?dataurl" import Code2 from "@assets/icons/code-2.svg?dataurl" @@ -18,6 +18,7 @@ import EventShare from "@app/components/EventShare.svelte" import EventDeleteConfirm from "@app/components/EventDeleteConfirm.svelte" import {hasNip29, deriveUserIsSpaceAdmin} from "@app/core/state" + import {hasPermission} from "@app/core/roles" import {pushModal} from "@app/util/modal" import {pushToast} from "@app/util/toast" import {makeSpaceChatPath} from "@app/util/routes" @@ -33,7 +34,8 @@ const {url, noun, event, onClick, customActions}: Props = $props() const isRoot = event.kind !== COMMENT - const userIsAdmin = deriveUserIsSpaceAdmin(url) + const h = getTagValue("h", event.tags) + const canDelete = h ? hasPermission(url, h, 9005) : deriveUserIsSpaceAdmin(url) const report = () => pushModal(Report, {url, event}) @@ -107,7 +109,7 @@ Report Content - {#if $userIsAdmin} + {#if $canDelete}