Check the room admin list for the delete kind before sending a NIP-29 delete

This commit is contained in:
Coracle-Bot 2026-09-21 17:58:14 +00:00
parent 6b5947ae0e
commit 94bb7adb33

View file

@ -2,7 +2,17 @@ import * as nip19 from "nostr-tools/nip19"
import {derived, get} from "svelte/store" import {derived, get} from "svelte/store"
import {formatTimestampAsDate, int, sortBy, uniq, MINUTE} from "@welshman/lib" import {formatTimestampAsDate, int, sortBy, uniq, MINUTE} from "@welshman/lib"
import type {Maybe} from "@welshman/lib" import type {Maybe} from "@welshman/lib"
import {outbox, relay, seen, tagSpec, tagValue, toNostrURI} from "@welshman/util" import {
ROOM_DELETE_EVENT,
hexTags,
outbox,
relay,
seen,
tagSpec,
tagValue,
tagValueMatcher,
toNostrURI,
} from "@welshman/util"
import type {EventContent, TrustedEvent} from "@welshman/util" import type {EventContent, TrustedEvent} from "@welshman/util"
import {Message} from "@welshman/domain" import {Message} from "@welshman/domain"
import {MembershipStatus, RoomLists, makeRoomKey, createSearch, publish} from "@welshman/app" import {MembershipStatus, RoomLists, makeRoomKey, createSearch, publish} from "@welshman/app"
@ -173,6 +183,15 @@ export const deriveUserIsRoomAdmin = (url: string, h: string) =>
$isStaff || Boolean($room?.admins?.pubkeys().includes($user.pubkey)), $isStaff || Boolean($room?.admins?.pubkeys().includes($user.pubkey)),
) )
// The room's admin list names the management kinds each admin may publish, so the ops the relay
// will answer for the user are readable before one is sent.
export const deriveUserRoomPermissions = (url: string, h: string) =>
derived([user, rooms.get().forRoom(url, h)], ([$user, $room]) => {
const tag = $room?.admins?.tags().find(tagValueMatcher(hexTags("p"), $user.pubkey))
return tag?.slice(2).map(Number) ?? []
})
// Deleting someone else's content goes one of two ways, and a space answers for either one. // Deleting someone else's content goes one of two ways, and a space answers for either one.
export enum AdminDelete { export enum AdminDelete {
Room = "room", Room = "room",
@ -185,9 +204,9 @@ export const deriveUserAdminDelete = (url: string, event: TrustedEvent) => {
const h = tagValue(tagSpec("h"), event.tags) ?? "" const h = tagValue(tagSpec("h"), event.tags) ?? ""
return derived( return derived(
[deriveUserIsRoomAdmin(url, h), deriveSpaceSupportedMethods(url)], [deriveUserRoomPermissions(url, h), deriveSpaceSupportedMethods(url)],
([$isRoomAdmin, $methods]): Maybe<AdminDelete> => { ([$permissions, $methods]): Maybe<AdminDelete> => {
if (h && $isRoomAdmin) { if (h && $permissions.includes(ROOM_DELETE_EVENT)) {
return AdminDelete.Room return AdminDelete.Room
} }