Fix admin delete hanging on "Deleting…" with Amber signer
Compute event id locally in CapacitorAmberSigner.signEvent instead of relying on Amber to echo it back. Amber (NIP-55) commonly returns only a bare `signature` for kind:5 deletions and kind:1985 moderation labels, leaving id empty — which failed the malformed-event check or emitted a bad event that stalled the relay forever (the "stuck on Deleting…" symptom). The id is a deterministic NIP-01 hash of the signed fields, so we derive it ourselves, making signature-only responses work for every kind including admin takedowns. Co-authored-by: shakespeare.diy <assistant@shakespeare.diy>
This commit is contained in:
parent
26245f3d05
commit
977d71dc60
2 changed files with 27 additions and 5 deletions
|
|
@ -72,7 +72,14 @@ export function useDeleteEntity() {
|
||||||
|
|
||||||
// Admin takedown of someone else's content: also publish a client-side
|
// Admin takedown of someone else's content: also publish a client-side
|
||||||
// moderation label so the app hides it even if relays won't honor a
|
// moderation label so the app hides it even if relays won't honor a
|
||||||
// cross-author NIP-09 deletion.
|
// cross-author NIP-09 deletion. This label is what actually hides the
|
||||||
|
// content across SkateSpots (see useAdminModeration), so it MUST succeed —
|
||||||
|
// we await it and let a failure surface to the caller as an error.
|
||||||
|
//
|
||||||
|
// NOTE: this requires a SECOND Amber approval. Both signatures now compute
|
||||||
|
// their event id locally (see CapacitorAmberSigner.signEvent), so a
|
||||||
|
// signature-only Amber response no longer produces an empty id that stalls
|
||||||
|
// the publish forever — the previous "stuck on Deleting…" cause.
|
||||||
if (isAdmin && !isOwner) {
|
if (isAdmin && !isOwner) {
|
||||||
const labelTags: string[][] = [
|
const labelTags: string[][] = [
|
||||||
['L', MODERATION_LABEL_NAMESPACE],
|
['L', MODERATION_LABEL_NAMESPACE],
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
|
|
||||||
import type { NostrEvent, NostrSigner } from '@nostrify/nostrify';
|
import type { NostrEvent, NostrSigner } from '@nostrify/nostrify';
|
||||||
import { Capacitor, registerPlugin } from '@capacitor/core';
|
import { Capacitor, registerPlugin } from '@capacitor/core';
|
||||||
import { nip19 } from 'nostr-tools';
|
import { nip19, getEventHash } from 'nostr-tools';
|
||||||
|
|
||||||
const AMBER_PACKAGE = 'com.greenart7c3.nostrsigner';
|
const AMBER_PACKAGE = 'com.greenart7c3.nostrsigner';
|
||||||
|
|
||||||
|
|
@ -242,13 +242,28 @@ export class CapacitorAmberSigner implements NostrSigner {
|
||||||
|
|
||||||
// Merge Amber's response over the original event so required fields are
|
// Merge Amber's response over the original event so required fields are
|
||||||
// never lost, then verify the essentials are present before returning.
|
// never lost, then verify the essentials are present before returning.
|
||||||
const merged: NostrEvent = {
|
const pubkey = signed.pubkey ?? this.pubkey;
|
||||||
|
const base = {
|
||||||
kind: signed.kind ?? event.kind,
|
kind: signed.kind ?? event.kind,
|
||||||
content: signed.content ?? event.content,
|
content: signed.content ?? event.content,
|
||||||
tags: signed.tags ?? event.tags,
|
tags: signed.tags ?? event.tags,
|
||||||
created_at: signed.created_at ?? event.created_at,
|
created_at: signed.created_at ?? event.created_at,
|
||||||
pubkey: signed.pubkey ?? this.pubkey,
|
pubkey,
|
||||||
id: signed.id ?? '',
|
};
|
||||||
|
|
||||||
|
// CRITICAL: Amber (NIP-55) commonly returns ONLY the `signature` for events
|
||||||
|
// like kind:5 deletions and kind:1985 labels — no `id` and no full event
|
||||||
|
// JSON. Previously we left `id: ''`, which failed the malformed-event check
|
||||||
|
// below (or emitted a bad event that stalled the relay forever). The event
|
||||||
|
// id is a deterministic NIP-01 hash of these fields, so we compute it
|
||||||
|
// ourselves instead of depending on Amber to echo it back. This makes
|
||||||
|
// signature-only responses work for EVERY kind — including admin takedowns.
|
||||||
|
const id =
|
||||||
|
signed.id && signed.id.length === 64 ? signed.id : getEventHash(base);
|
||||||
|
|
||||||
|
const merged: NostrEvent = {
|
||||||
|
...base,
|
||||||
|
id,
|
||||||
sig: signed.sig,
|
sig: signed.sig,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue