newsroom: Verwaltungszugang „Diesen Newsroom verwalten" (Roadmap 1b.2)

Neue Seite /newsroom/{slug}/verwalten auf den Web-Portalen: schickt den
Anmeldelink an die hinterlegte Firmen-E-Mail (sonst Pressekontakte), zeigt
sie nur maskiert, und funktioniert auch für Firmen ohne veröffentlichte
Meldung. Konto, Zuordnung und Login laufen durch ContactAccessService —
neu dort: Herkunft (profile_claim auf dem Token) und Ziel-Firma, auf deren
Kundenseite der Login landet. 410-entfernte bleiben Tombstone, aufgegangene
Slugs führen zum Überlebenden (MergedNewsroomLookup, geteilt mit der
Newsroom-Seite). 3 Links je Newsroom und Tag, 15 je IP und Stunde.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-09-15 10:42:20 +00:00
parent a3e0042055
commit 0c1c072487
15 changed files with 665 additions and 37 deletions

View file

@ -0,0 +1,75 @@
@extends('web.layouts.web-master')
@section('title', __('static.newsroom_claim.title'))
@section('meta_description', __('static.newsroom_claim.meta'))
{{--
„Diesen Newsroom verwalten" (Roadmap 1b.2): Verwaltungszugang über die
hinterlegte Firmen-E-Mail. Der Besucher gibt keine Adresse ein — der Link
geht an das, was an der Firma steht, und er sieht nur die maskierte
Adresse. Bewusst kein Angebot, kein Preis: Der Zugang ist kostenlos, und
die Seite bleibt es auch (Anti-Zombie-Zusage).
--}}
@section('content')
<x-web.static-page
:eyebrow="__('static.newsroom_claim.eyebrow')"
:title="__('static.newsroom_claim.title')"
:breadcrumb="__('static.newsroom_claim.breadcrumb')"
>
<div class="max-w-[640px]">
<p class="text-[15px] font-semibold text-ink mb-4">{{ $company->name }}</p>
@if (session('newsroom-claim-status'))
<div class="mb-6 px-4 py-3 border border-bg-rule bg-bg-elev text-[13px] text-ink-2" role="status">
{{ session('newsroom-claim-status') }}
</div>
@endif
@error('claim')
<div class="mb-6 px-4 py-3 border border-red-300 bg-red-50 text-[13px] text-red-700" role="alert">
{{ $message }}
</div>
@enderror
@if ($recipients->isEmpty() || session('newsroom-claim-none'))
<p class="text-[13.5px] text-ink-2 leading-relaxed mb-6">
{{ __('static.newsroom_claim.intro_no_email', ['company' => $company->name]) }}
</p>
@else
<p class="text-[13.5px] text-ink-2 leading-relaxed mb-4">
{{ __('static.newsroom_claim.intro', ['company' => $company->name]) }}
</p>
<ul class="mb-6 text-[14px] font-mono text-ink">
@foreach ($recipients as $recipient)
<li>{{ $recipient }}</li>
@endforeach
</ul>
<form method="POST" action="{{ route('newsroom.claim.store', ['slug' => $company->slug]) }}" class="space-y-5">
@csrf
{{-- Honeypot --}}
<div class="hidden" aria-hidden="true">
<label for="website">Website</label>
<input id="website" type="text" name="website" tabindex="-1" autocomplete="off" value="{{ old('website') }}" />
</div>
<button type="submit"
class="inline-flex items-center px-5 py-2.5 bg-brand text-white text-[13px] font-semibold hover:opacity-90">
{{ __('static.newsroom_claim.submit') }}
</button>
</form>
@endif
<p class="mt-8 text-[12.5px] text-ink-2 leading-relaxed">
{{ __('static.newsroom_claim.wrong_address') }}
<a href="{{ rtrim((string) config('domains.domain_portal_url'), '/') }}/anmeldelink" class="underline underline-offset-2 hover:text-ink">{{ __('static.newsroom_claim.login_link') }}</a>
</p>
<p class="mt-4 text-[12.5px]">
<a href="{{ route('newsroom', ['slug' => $company->slug]) }}" class="underline underline-offset-2 text-ink-2 hover:text-ink">← {{ __('static.newsroom_claim.back') }}</a>
</p>
</div>
</x-web.static-page>
@endsection