Refactor NIP-05 verification: extract handle-fetching logic into reusable NostrFetcherTrait and enhance UI to display all verified handles with improved feedback.

This commit is contained in:
HolgerHatGarKeineNode
2026-01-23 17:09:00 +01:00
parent dfb1c3fa0f
commit 4b9ad0f6ab
5 changed files with 115 additions and 77 deletions

View File

@@ -12,6 +12,37 @@ use swentel\nostr\Subscription\Subscription;
trait NostrFetcherTrait
{
/**
* Get all NIP-05 handles for a given pubkey from nostr.json
*
* @param string $pubkey The public key in hex format
* @return array Array of handles associated with the pubkey
*/
public function getNip05HandlesForPubkey(string $pubkey): array
{
try {
$response = \Illuminate\Support\Facades\Http::get(
'https://einundzwanzig.space/.well-known/nostr.json',
);
$data = $response->json();
if (! isset($data['names'])) {
return [];
}
$handles = [];
foreach ($data['names'] as $handle => $handlePubkey) {
if ($handlePubkey === $pubkey) {
$handles[] = $handle;
}
}
return $handles;
} catch (\Exception) {
return [];
}
}
public function fetchProfile($npubs)
{
$hex = collect([]);

View File

@@ -12,7 +12,7 @@ return [
/**
* Use this setting to specify the site name that will be used in OpenGraph tags.
*/
'site_name' => 'Einundzwanzig Verein',
'site_name' => 'EINUNDZWANZIG Verein',
/**
* Use this setting to specify the path to the sitemap of your website. This exact path will outputted, so
@@ -75,7 +75,7 @@ return [
* Use this setting to provide a suffix that will be added after the title on each page.
* If you don't want a suffix, you should specify an empty string.
*/
'suffix' => ' - Einundzwanzig Verein',
'suffix' => ' - EINUNDZWANZIG Verein',
/**
* Use this setting to provide a custom title for the homepage. We will not use the suffix on the homepage,

View File

@@ -26,10 +26,10 @@
<flux:header sticky class="bg-zinc-50 dark:bg-zinc-900 border-b border-zinc-200 dark:border-zinc-700">
<flux:sidebar.toggle class="lg:hidden" icon="bars-2" inset="left"/>
<flux:brand href="/" name="Einundzwanzig" class="max-lg:hidden dark:hidden">
<flux:brand href="/" name="EINUNDZWANZIG" class="max-lg:hidden dark:hidden">
<img src="{{ asset('einundzwanzig-alpha.jpg') }}" alt="Logo" class="h-6 w-6">
</flux:brand>
<flux:brand href="/" name="Einundzwanzig" class="max-lg:hidden! hidden dark:flex">
<flux:brand href="/" name="EINUNDZWANZIG" class="max-lg:hidden! hidden dark:flex">
<img src="{{ asset('einundzwanzig-alpha.jpg') }}" alt="Logo" class="h-6 w-6">
</flux:brand>
@@ -84,7 +84,7 @@
<flux:sidebar.header>
<flux:sidebar.brand
href="/"
name="Einundzwanzig"
name="EINUNDZWANZIG"
>
<img src="{{ asset('einundzwanzig-alpha.jpg') }}" alt="Logo" class="h-6 w-6">
</flux:sidebar.brand>

View File

@@ -2,11 +2,14 @@
use App\Models\EinundzwanzigPleb;
use App\Support\NostrAuth;
use App\Traits\NostrFetcherTrait;
use Flux\Flux;
use Livewire\Component;
new class extends Component
{
use NostrFetcherTrait;
public ?EinundzwanzigPleb $currentPleb = null;
public ?string $currentPubkey = null;
@@ -21,6 +24,8 @@ new class extends Component
public bool $nip05HandleMismatch = false;
public array $nip05VerifiedHandles = [];
protected $listeners = [
'nostrLoggedIn' => 'handleNostrLoggedIn',
'nostrLoggedOut' => 'handleNostrLoggedOut',
@@ -40,27 +45,17 @@ new class extends Component
if ($this->currentPleb->nip05_handle) {
$this->nip05Handle = $this->currentPleb->nip05_handle;
// Verify NIP-05 handle against nostr.json
try {
$response = \Illuminate\Support\Facades\Http::get(
'https://einundzwanzig.space/.well-known/nostr.json',
);
$data = $response->json();
if (isset($data['names'])) {
foreach ($data['names'] as $handle => $pubkey) {
if ($pubkey === $this->currentPubkey) {
$this->nip05Verified = true;
$this->nip05VerifiedHandle = $handle;
// Check if verified handle differs from database handle
if ($handle !== $this->nip05Handle) {
$this->nip05HandleMismatch = true;
}
break;
}
}
// Get all NIP-05 handles for current pubkey
$this->nip05VerifiedHandles = $this->getNip05HandlesForPubkey($this->currentPubkey);
if (count($this->nip05VerifiedHandles) > 0) {
$this->nip05Verified = true;
$this->nip05VerifiedHandle = $this->nip05VerifiedHandles[0];
// Check if verified handle differs from database handle
if (! in_array($this->nip05Handle, $this->nip05VerifiedHandles, true)) {
$this->nip05HandleMismatch = true;
}
} catch (\Exception) {
// Silently fail if nostr.json is not accessible
}
}
@@ -121,6 +116,7 @@ new class extends Component
$this->nip05Verified = false;
$this->nip05VerifiedHandle = null;
$this->nip05HandleMismatch = false;
$this->nip05VerifiedHandles = [];
}
}
?>
@@ -251,25 +247,33 @@ new class extends Component
<!-- NIP-05 Verification Status -->
@if($nip05Verified)
@if($nip05HandleMismatch)
<flux:callout variant="warning" icon="exclamation-triangle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Dein aktiviertes Handle ist <br><strong class="break-all">{{ $nip05VerifiedHandle }}@einundzwanzig.space</strong>
</p>
<flux:callout variant="success" icon="check-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Du hast {{ count($nip05VerifiedHandles) }} aktiv{{ count($nip05VerifiedHandles) > 1 ? 'ierte' : 'isiert' }}e{{ count($nip05VerifiedHandles) > 1 ? ' Handles' : 'es Handle' }} für deinen Pubkey!
</p>
@if($nip05HandleMismatch)
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">
Die Synchronisation zu <strong class="break-all">{{ $nip05Handle }}@einundzwanzig.space</strong> wird automatisch im Hintergrund durchgeführt.
</p>
</flux:callout>
@else
<flux:callout variant="success" icon="check-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Dein Handle <strong class="break-all">{{ $nip05VerifiedHandle }}@einundzwanzig.space</strong> ist aktiv verifiziert!
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">
Dein Handle ist in der NIP-05 Konfiguration eingetragen und bereit für die Verwendung.
</p>
</flux:callout>
@endif
@endif
</flux:callout>
<!-- List of all active handles -->
<div class="mt-4 p-4 bg-white/50 dark:bg-zinc-800/50 rounded border border-zinc-200 dark:border-zinc-600">
<p class="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
Deine aktivierten Handles:
</p>
<ul class="space-y-2">
@foreach($nip05VerifiedHandles as $handle)
<li class="flex items-center gap-2 text-sm">
<span class="break-all text-zinc-800 dark:text-zinc-200 font-mono">
{{ $handle }}@einundzwanzig.space
</span>
<flux:badge color="green" size="xs">OK</flux:badge>
</li>
@endforeach
</ul>
</div>
@elseif($nip05Handle)
<flux:callout variant="secondary" icon="information-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">

View File

@@ -3,6 +3,7 @@
use App\Livewire\Forms\ApplicationForm;
use App\Models\EinundzwanzigPleb;
use App\Support\NostrAuth;
use App\Traits\NostrFetcherTrait;
use Flux\Flux;
use Livewire\Component;
use swentel\nostr\Event\Event as NostrEvent;
@@ -17,6 +18,8 @@ use swentel\nostr\Subscription\Subscription;
new class extends Component
{
use NostrFetcherTrait;
public ApplicationForm $form;
public bool $no = false;
@@ -35,6 +38,8 @@ new class extends Component
public bool $nip05HandleMismatch = false;
public array $nip05VerifiedHandles = [];
public array $yearsPaid = [];
public array $events = [];
@@ -71,27 +76,17 @@ new class extends Component
if ($this->currentPleb->nip05_handle) {
$this->nip05Handle = $this->currentPleb->nip05_handle;
// Verify NIP-05 handle against nostr.json
try {
$response = \Illuminate\Support\Facades\Http::get(
'https://einundzwanzig.space/.well-known/nostr.json',
);
$data = $response->json();
if (isset($data['names'])) {
foreach ($data['names'] as $handle => $pubkey) {
if ($pubkey === $this->currentPubkey) {
$this->nip05Verified = true;
$this->nip05VerifiedHandle = $handle;
// Check if verified handle differs from database handle
if ($handle !== $this->nip05Handle) {
$this->nip05HandleMismatch = true;
}
break;
}
}
// Get all NIP-05 handles for the current pubkey
$this->nip05VerifiedHandles = $this->getNip05HandlesForPubkey($this->currentPubkey);
if (count($this->nip05VerifiedHandles) > 0) {
$this->nip05Verified = true;
$this->nip05VerifiedHandle = $this->nip05VerifiedHandles[0];
// Check if verified handle differs from database handle
if (! in_array($this->nip05Handle, $this->nip05VerifiedHandles, true)) {
$this->nip05HandleMismatch = true;
}
} catch (\Exception) {
// Silently fail if nostr.json is not accessible
}
}
$this->no = $this->currentPleb->no_email;
@@ -468,25 +463,33 @@ new class extends Component
<!-- NIP-05 Verification Status -->
@if($nip05Verified)
@if($nip05HandleMismatch)
<flux:callout variant="warning" icon="exclamation-triangle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Dein aktiviertes Handle ist <br><strong class="break-all">{{ $nip05VerifiedHandle }}@einundzwanzig.space</strong>
</p>
<flux:callout variant="success" icon="check-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Du hast {{ count($nip05VerifiedHandles) }} aktiv{{ count($nip05VerifiedHandles) > 1 ? 'ierte' : 'isiert' }}e{{ count($nip05VerifiedHandles) > 1 ? ' Handles' : 'es Handle' }} für deinen Pubkey!
</p>
@if($nip05HandleMismatch)
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">
Die Synchronisation zu <strong class="break-all">{{ $nip05Handle }}@einundzwanzig.space</strong> wird automatisch im Hintergrund durchgeführt.
</p>
</flux:callout>
@else
<flux:callout variant="success" icon="check-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">
Dein Handle <strong class="break-all">{{ $nip05VerifiedHandle }}@einundzwanzig.space</strong> ist aktiv verifiziert!
</p>
<p class="text-sm text-zinc-600 dark:text-zinc-400 mt-1">
Dein Handle ist in der NIP-05 Konfiguration eingetragen und bereit für die Verwendung.
</p>
</flux:callout>
@endif
@endif
</flux:callout>
<!-- List of all active handles -->
<div class="mt-4 p-4 bg-white/50 dark:bg-zinc-800/50 rounded border border-zinc-200 dark:border-zinc-600">
<p class="text-sm font-medium text-zinc-700 dark:text-zinc-300 mb-2">
Deine aktivierten Handles:
</p>
<ul class="space-y-2">
@foreach($nip05VerifiedHandles as $handle)
<li class="flex items-center gap-2 text-sm">
<span class="break-all text-zinc-800 dark:text-zinc-200 font-mono">
{{ $handle }}@einundzwanzig.space
</span>
<flux:badge color="green" size="xs">OK</flux:badge>
</li>
@endforeach
</ul>
</div>
@elseif($nip05Handle)
<flux:callout variant="secondary" icon="information-circle" class="mt-4">
<p class="font-medium text-zinc-800 dark:text-zinc-100">