ithilbert / consentlaw-client
Client für die consentLaw-API – ruft Rechtstexte (Impressum, Datenschutz, AGB, Cookie-Richtlinie, AVV) und Stellenangebote ab und liefert sie als Blade-Komponenten aus. Mit Cache und ausfallsicherem Fallback.
Deleted by maintainer on 2026-10-20 10:52:24 UTC
Requires
- php: ^8.5
- illuminate/cache: ^11.0 || ^12.0
- illuminate/console: ^11.0 || ^12.0
- illuminate/filesystem: ^11.0 || ^12.0
- illuminate/http: ^11.0 || ^12.0
- illuminate/routing: ^11.0 || ^12.0
- illuminate/support: ^11.0 || ^12.0
- illuminate/view: ^11.0 || ^12.0
- league/commonmark: ^2.10.2
Requires (Dev)
- orchestra/testbench: ^9.0 || ^10.0
- phpunit/phpunit: ^11.0 || ^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Laravel-Client für die consentLaw-API. Holt Rechtstexte (Impressum, Datenschutz, AGB, Cookie-Richtlinie, AVV) und Stellenangebote in ein beliebiges Laravel-Projekt – mit Cache und ausfallsicherem Fallback.
Installation
Störungsmeldungen laufen über das Basis-Package ithilbert/alerts. Composer löst
VCS-Repositories nicht transitiv auf. Deshalb muss das Host-Projekt das Repository
in seiner composer.json selbst eintragen, bevor das Package installiert wird:
"repositories": [ { "type": "vcs", "url": "https://github.com/ITHilbert/alerts.git" } ]
Das Repository ist privat. Composer braucht dafür einen GitHub-Token (in auth.json
oder COMPOSER_AUTH). Solange ithilbert/alerts kein Release-Tag hat, ist dev-main
nötig. Dann installieren:
composer require ithilbert/consentlaw-client
ithilbert/alerts kommt dadurch als Abhängigkeit mit. Kanäle und Empfänger der
Störungsmeldungen stellt man in alerts über ALERTS_* ein (siehe dessen README).
In der .env den Token der Domain eintragen (zu finden in consentLaw unter
Domain → Integration & Setup):
CONSENTLAW_URL=https://www.consentlaw.eu CONSENTLAW_TOKEN=dein-domain-token
Optional die Konfiguration veröffentlichen:
php artisan vendor:publish --tag=consentlaw-config
Nutzung
Blade-Komponenten (empfohlen)
Die Inhalte landen in deinem Layout, unter deiner URL:
{{-- Rechtstexte --}} <x-consentlaw::impressum /> <x-consentlaw::datenschutz /> <x-consentlaw::agb /> <x-consentlaw::cookie-richtlinie /> <x-consentlaw::avv /> {{-- oder generisch --}} <x-consentlaw::document type="impressum" /> {{-- Stellenangebote (inkl. Schema.org JobPosting für Google for Jobs) --}} <x-consentlaw::jobs />
Ist kein Inhalt verfügbar, rendert die Komponente den Slot – so bleibt das Layout intakt:
<x-consentlaw::jobs> <p>Zurzeit sind keine Stellen ausgeschrieben.</p> </x-consentlaw::jobs>
Andere Sprache:
<x-consentlaw::impressum locale="en" />
Programmatisch
use ITHilbert\ConsentLaw\Facades\ConsentLaw; ConsentLaw::impressum()->content(); // string (HTML/Markdown-Quelle) ConsentLaw::impressum()->get(); // ?Document (mit Format, Datum, isStale) ConsentLaw::datenschutz()->exists(); // bool ConsentLaw::jobs()->all(); // Collection<Job> ConsentLaw::jobs()->current(); // ohne abgelaufene Fristen ConsentLaw::jobs()->find($id); // ?Job ConsentLaw::locale('en')->agb()->content(); // andere Sprache ConsentLaw::isConfigured(); // Token gesetzt?
Eigenes Markup für Jobs: siehe Abschnitt „Eigenes Markup“ weiter unten.
Fertige Seiten (optional)
Standardmäßig registriert das Package keine Routen, um nicht mit bestehenden Seiten zu kollidieren. Wer schnell starten will:
CONSENTLAW_ROUTES_ENABLED=true
Danach sind /impressum, /datenschutz, /agb, /cookie-richtlinie, /avv
und /jobs erreichbar. Pfade, Middleware, Prefix und Layout sind in
config/consentlaw.php frei einstellbar:
'routes' => [ 'enabled' => true, 'layout' => 'layouts.app', // eigenes Layout einhängen 'paths' => ['impressum' => 'legal-notice'], ],
Caching & Ausfallsicherheit
Ein Impressum darf nie von der Seite verschwinden, nur weil ein API-Aufruf fehlschlägt. Der Ablauf jedes Abrufs:
| Schritt | Verhalten |
|---|---|
| 1. Cache frisch (TTL, Standard 1 h) | direkt ausliefern, kein HTTP-Request |
| 2. Wartezeit nach Störung aktiv | kein HTTP-Request, direkt Schritt 4 |
| 3. Cache alt/leer | API abrufen → Cache und Fallback-Datei aktualisieren |
| 4. API gestört (Timeout, DNS, 5xx, 429, 401, 403 …) | Wartezeit setzen, letzten Stand aus der Fallback-Datei ausliefern (isStale = true) |
| 5. Server antwortet mit 404 | null – der Token ist ungültig oder der Inhalt ist nicht veröffentlicht. Der Vermerk wird für die Cache-TTL gecacht (kein erneuter HTTP-Aufruf), 404 wird nicht wiederholt |
| 6. Kein Fallback vorhanden | null, die Komponente rendert den Slot |
Der Unterschied zwischen 4 und 5 ist beabsichtigt: Bei einer Störung ist ein alter Inhalt besser als keiner. Nur eine 404 ist eine klare Aussage des Servers („nicht veröffentlicht“) – dann wäre es falsch, weiter alte Inhalte zu zeigen. Jeder andere Fehlerstatus (z. B. 429 durch das Rate-Limit von consentLaw) gilt als Störung.
„Nicht veröffentlicht“ wird gecacht
Ein 404 wird für die Dauer von CONSENTLAW_CACHE_TTL vermerkt: Ein Kunde ohne AGB löst
nicht bei jedem Seitenaufruf einen HTTP-Aufruf aus. Ein 404 wird außerdem nicht
wiederholt (http.retries gilt nur für Störungen: Verbindungsfehler, 5xx, andere
Fehlerstatus). Bei cache.enabled=false oder TTL 0 wird nicht gecacht.
forget(), refresh(), consentlaw:load und consentlaw:flush verwerfen den Vermerk.
Wartezeit nach einer Störung
Nach einer Störung wird die API für CONSENTLAW_FALLBACK_RETRY_AFTER Sekunden
(Standard 300) nicht erneut gefragt, sondern direkt der Fallback ausgeliefert –
auch wenn keiner existiert (dann direkt nichts). Ohne diese Wartezeit würde nach jeder
abgelaufenen Cache-TTL jeder Seitenaufruf erneut auf den API-Timeout warten, und die
Homepage wäre bei einem Ausfall von consentLaw langsam. Nach Ablauf wird die API wieder
gefragt. Die Wartezeit gilt je Inhalt, liegt im Cache-Store und ist von
CONSENTLAW_CACHE_TTL/cache.enabled unabhängig; 0 schaltet sie ab.
consentlaw:load und consentlaw:flush heben sie auf.
Fallback-Dateien liegen auf der konfigurierten Disk unter consentlaw/ (beim
Standard-Disk local ist das storage/app/private/consentlaw/) und enthalten den
Token-Hash im Namen – nach einem Token-Wechsel werden keine fremden Inhalte
wiederverwendet.
Nach dem Deploy neu laden
Der storage/-Ordner ist üblicherweise nicht im Git. Damit direkt nach einem Deploy ein
Fallback-Stand bereitliegt:
php artisan consentlaw:load
php artisan consentlaw:flush # Cache + Fallback verwerfen
consentlaw:load meldet einen nicht veröffentlichten Typ (404, z. B. ein Kunde ohne
AGB) nur als Hinweis und endet mit Exit-Code 0. Exit-Code 1 gibt es nur ohne Token oder
wenn ein Typ wegen einer Störung weder von der API noch aus dem Fallback geliefert
werden konnte – so scheitern Deploy-Skripte nur bei echten Problemen.
Antworten alle Typen (5 Dokumente und Jobs) mit 404, ist fast sicher der Token ungültig: Dann endet der Befehl mit Exit-Code 1 und dem Hinweis, den Token zu prüfen.
Störungsmeldung über alerts
Fehlende oder veraltete Rechtstexte sind abmahnfähig – ein Log liest niemand. Das Package
meldet deshalb drei Störungsfälle als Event (Namespace ITHilbert\ConsentLaw\Events):
| Event | Wann | Properties |
|---|---|---|
RechtstextNichtLieferbar |
API gestört (kein 404) und kein Fallback vorhanden bzw. Fallback abgeschaltet – der Inhalt fehlt auf der Seite | typ, locale, fehler |
NotstandVeraltet |
API gestört, ausgeliefert wird ein Fallback, der älter ist als CONSENTLAW_FALLBACK_WARN_AFTER (Standard 7 Tage). Der Inhalt bleibt sichtbar |
typ, locale, alterInSekunden, fehler |
TokenVermutlichUngueltig |
consentlaw:load: alle Typen antworten mit 404 (Exit-Code und Ausgabe wie bisher) |
– |
RechtstextNichtLieferbar und NotstandVeraltet entstehen beim Seitenaufruf, beim
„Neu laden“-Button und bei consentlaw:load – aber nur, wenn wirklich abgerufen wurde:
Während der Wartezeit nach einer Störung (CONSENTLAW_FALLBACK_RETRY_AFTER) wird nicht
abgerufen und deshalb auch nichts gemeldet. Ein einzelnes 404 („nicht veröffentlicht“,
z. B. ein Kunde ohne AGB) ist keine Störung. fehler enthält den Token nur maskiert.
Die Meldung übernimmt das Basis-Package ithilbert/alerts. Der Listener MeldeStoerungAnAlerts
ruft dafür den Port AlertReporter auf, genau einmal je Event. Der Listener ist immer aktiv.
Eine eigene Mail-Konfiguration gibt es im Package nicht mehr.
| Event | Schlüssel in alerts | Titel der Meldung |
|---|---|---|
RechtstextNichtLieferbar |
consentlaw.nicht-lieferbar |
Rechtstext nicht lieferbar |
NotstandVeraltet |
consentlaw.notstand-veraltet |
Veralteter Notstand |
TokenVermutlichUngueltig |
consentlaw.token-vermutlich-ungueltig |
Token vermutlich ungültig |
- Schlüssel: Je Fall ein fester Schlüssel, unabhängig vom Typ. Die Drosselung von alerts gilt deshalb pro Fall. Weitere Typen mit demselben Fall erzeugen keine eigene Meldung, sondern zählen in der Sammelmeldung.
- Inhalt: Website (
APP_URL), Typ und, falls gesetzt, Sprache. BeiNotstandVeraltetdas Alter in Tagen (ab einem Tag; darunter in Stunden). Dazu kommen „Was ist passiert“ und „Was ist zu tun“. Der Fehlertext (Token maskiert) steht beiRechtstextNichtLieferbarundNotstandVeraltet.TokenVermutlichUngueltighat weder Typ, Sprache noch Fehlertext. - Freigabe:
php artisan alerts:reset consentlaw.nicht-lieferbarhebt die Sperre dieses Falls auf. Das nächste Auftreten wird sofort gemeldet.php artisan alerts:reset --allhebt alle Sperren auf, auch die anderer Packages. - Kanäle, Empfänger, Drosselung: Stellt man in alerts über
ALERTS_*ein, z. B.ALERTS_MAIL_TO,ALERTS_MAILER,ALERTS_CHANNELSundALERTS_SPERRE_STUNDEN. Die vollständige Liste steht in der README vonithilbert/alerts. - Fallstrick: Ein Kanal ohne vollständige Konfiguration wird von alerts still übersprungen.
Ohne
ALERTS_MAIL_TOgeht also keine Mail raus, und es erscheint keine Fehlermeldung. - Fehlschlag: Wirft der Port eine Exception, wird das als Warnung geloggt
(
[consentlaw] Störungsmeldung an alerts fehlgeschlagen., Token maskiert). Seitenaufruf, Fallback und Exit-Code vonconsentlaw:loadbleiben unverändert. - Abschalten: Meldungen lassen sich in alerts abschalten, z. B. mit
ALERTS_ENABLED=false. Das wirkt auf alle Meldungen des Hosts. Die Events werden dabei weiter ausgelöst.
Die Events bleiben unverändert und lassen sich zusätzlich abonnieren:
Event::listen(\ITHilbert\ConsentLaw\Events\RechtstextNichtLieferbar::class, function ($event) { // $event->typ, $event->locale, $event->fehler });
Konfiguration
| ENV | Standard | Bedeutung |
|---|---|---|
CONSENTLAW_URL |
https://www.consentlaw.eu |
Basis-URL der Instanz |
CONSENTLAW_TOKEN |
– | Domain-Token (Pflicht) |
CONSENTLAW_CACHE_TTL |
3600 |
Frische in Sekunden, 0 = Cache aus |
CONSENTLAW_CACHE_STORE |
Standard-Store | z.B. redis |
CONSENTLAW_TIMEOUT |
5 |
HTTP-Timeout in Sekunden |
CONSENTLAW_FALLBACK_DISK |
local |
Disk für die Fallback-Dateien |
CONSENTLAW_FALLBACK_WARN_AFTER |
604800 |
Log-Warnung und Störungsmeldung NotstandVeraltet ab diesem Alter (Sekunden) |
CONSENTLAW_FALLBACK_RETRY_AFTER |
300 |
Wartezeit nach einer Störung, in der die API nicht erneut gefragt wird (Sekunden, 0 = aus) |
CONSENTLAW_ROUTES_ENABLED |
false |
Fertige Seiten registrieren |
APP_TEST |
false |
Zentraler Hilfen-Schalter: „Neu laden“-Button (wirkt in jeder Umgebung, auch Production) |
CONSENTLAW_LOCALE |
App-Locale | Sprache der Inhalte |
Kanäle, Empfänger und Drosselung der Störungsmeldungen stehen in den ALERTS_*-Variablen
von ithilbert/alerts.
Neu laden per Button
Wer Texte in consentLaw ändert, kann sie auf einer Homepage sofort neu laden – ohne SSH und
ohne auf den stündlichen Abruf zu warten. Der Schalter ist der zentrale Hilfen-Schalter
APP_TEST in der .env; er wirkt in jeder Umgebung, auch auf Production:
APP_TEST=true
Ablauf: APP_TEST=true setzen → Texte neu laden → APP_TEST=false zurücksetzen. Ist die
Config gecacht, nach jeder Änderung php artisan config:clear ausführen (bzw. danach neu
config:cache).
Mit gesetztem Schalter erscheint über jeder Dokument-Komponente (<x-consentlaw::impressum />,
<x-consentlaw::document /> …) und über <x-consentlaw::jobs /> ein Button „Neu laden“
(auch, wenn gerade kein Inhalt oder ein Slot-Fallback angezeigt wird). Ein Klick holt genau
diesen Typ frisch von consentLaw (Cache und Wartezeit nach einer Störung werden umgangen,
Fallback-Datei wird aktualisiert) und leitet auf die vorherige Seite zurück. Eine Störung
führt nicht zu einer Fehlerseite; die Seite zeigt dann den bisherigen Stand.
- Standard aus: Die Route (
POST consentlaw/neu-laden/{typ}, Nameconsentlaw.neu-laden) und das Limit sind immer registriert; ohne den Schalter antwortet die Aktion mit 404, ohne die API aufzurufen, und es erscheint kein Button. - Rückleitung: Der Button sendet die aktuelle Adresse (Pfad und Query) im versteckten Feld
zurueckmit; die Rückleitung funktioniert damit auch mitReferrer-Policy: no-referrer. Akzeptiert wird nur ein lokaler Pfad; ein ungültiger Wert verhindert das Neu laden nicht, die Rückleitung nutzt dann den Referer des eigenen Hosts bzw. die Startseite. - Alternative ohne Button:
php artisan consentlaw:load. - CSRF-Hinweis: Homepages, deren
web-Gruppe wederStartSessionnochVerifyCsrfTokenenthält, haben für diese Route keinen CSRF-Schutz. SolangeAPP_TESTan ist, kann dann eine fremde Seite das Neu laden auslösen (begrenzt auf 6 Anfragen pro Minute und IP). Den Schalter deshalb nur kurz eingeschaltet lassen. - Limit: höchstens 6 Anfragen pro Minute und IP (sonst 429); der Aufruf braucht ein
gültiges CSRF-Token (Middleware-Gruppe
web, siehe CSRF-Hinweis). Die Rückleitung geht nur auf die eigene Domain. Hinter einem Reverse Proxy ohne konfigurierte Trusted Proxies teilen sich alle Besucher eine IP und damit das Limit. - Rückmeldung: Hat die Seite eine Session (Gruppe
web), zeigt die Komponente nach dem Neu laden einmalig eine Meldung (role="status", Klassenconsentlaw-refresh-meldungund--okbzw.--fehler): Erfolg mit Stand, Störung mit gespeichertem Stand, Störung ohne Stand, „nicht veröffentlicht oder Token ungültig“ oder „kein Token konfiguriert“. Die Meldung erscheint nur bei der Komponente (Typ und Sprache), deren Button ausgelöst wurde, und enthält nie Token, URLs oder Exception-Texte. Ohne Session funktioniert das Neu laden wie bisher, nur ohne Meldung. - Ohne Token: Fehlt
CONSENTLAW_TOKEN, rendern die Komponenten (document,impressum…,jobs) ohne API-Aufruf wie bei „kein Inhalt verfügbar“ (leer bzw. Slot) und schreiben eine Warnung ins Log; die Seite antwortet mit 200. Die PHP-API (ConsentLaw::document(),jobs()) wirft weiterhinMissingTokenException. Die optionalen Package-Seiten verhalten sich ebenso: Dokument-Seite 404 (wie fehlender Inhalt), Jobs-Seite 200 mit leerer Liste. - Darstellung: dezentes Entwicklungswerkzeug (kleiner Button mit gestricheltem Rand); das
Partial bringt einen eigenen
<style>-Block mit niedriger Spezifität mit, das Formular trägt die Klasseconsentlaw-refreshund lässt sich im Seiten-CSS überschreiben. Eigenes Markup über die veröffentlichten Views (partials/neu-laden.blade.php). - Sprache: Hat die Komponente ein
locale-Attribut (<x-consentlaw::impressum locale="en" />), sendet der Button diese Sprache mit (verstecktes Feldlocale; erlaubt sind Angaben wiede,en,en_GB,pt-BR– andere Schreibweisen wieDEführen beim Klick zu 422) und lädt genau diese Sprachvariante neu. Ohnelocale-Attribut wird die konfigurierte Standardsprache (CONSENTLAW_LOCALE) neu geladen. Eine ungültige Sprachangabe (erlaubt:de,en,de_DE,pt-BR…) wird mit 422 abgewiesen, ohne dass die API aufgerufen wird. - Freigabe auch in der Aktion: Die Aktion prüft die Freigabe (Schalter
APP_TESTan) bei jedem Aufruf erneut und antwortet sonst mit 404 ohne API-Aufruf – auch wenn die Route z. B. aus einem Route-Cache stammt. - Bekannte Grenze: Ist der Fallback per
.envabgeschaltet und das Neu-Laden scheitert, kann die Seite bis zum nächsten erfolgreichen Abruf ohne Inhalt sein (Standard: Fallback an).
Eigenes Markup
Wer Stellenangebote im eigenen Layout ausgibt (z. B. als Aufklapp-Menü) und nicht
<x-consentlaw::jobs /> nutzt, setzt drei Bausteine zusammen:
@php // Daten: wirft ohne CONSENTLAW_TOKEN nicht (leere Liste + Warnung im Log) $jobs = app(\ITHilbert\ConsentLaw\Support\KomponentenInhalt::class)->jobs(null, false); @endphp {{-- "Neu laden"-Button (erscheint nur bei APP_TEST=true) --}} @include('consentlaw::components.partials.neu-laden', ['typ' => 'jobs', 'locale' => null]) @foreach($jobs as $job) <details> <summary>{{ $job->title }}</summary> {!! $job->descriptionHtml() !!} </details> @endforeach {{-- JSON-LD für Google for Jobs (je Stelle ein <script>, sonst keine Ausgabe) --}} <x-consentlaw::jobs-schema :jobs="$jobs" />
- Daten:
KomponentenInhalt::jobs()stattConsentLaw::jobs(): Letzteres wirft ohne Token eineMissingTokenException. - Beschreibung:
$job->descriptionHtml()liefert ausgabefertiges HTML (Markdown gerendert, HTML unverändert) – keine eigene Fallunterscheidung nötig. - JSON-LD:
<x-consentlaw::jobs-schema>baut das Schema.org-JobPosting;<x-consentlaw::jobs />nutzt dieselbe Komponente.
Felder je Stelle für Google for Jobs
Zusätzlich zu den bisherigen Feldern liefert die API je Stelle (alle optional, fehlende oder falsch typisierte Werte ergeben die Standardwerte):
| API-Feld | Job-Eigenschaft |
Standard | JSON-LD |
|---|---|---|---|
hiring_organization (name, url, logo) |
hiringOrganization (?HiringOrganization) |
null |
hiringOrganization (sameAs/logo nur bei absoluter http(s)-URL) |
remote (bool) |
remote |
false |
jobLocationType: TELECOMMUTE |
applicant_countries (ISO-3166-1 alpha-2) |
applicantCountries |
[] |
applicantLocationRequirements |
work_location (remote | vor_ort) |
workLocation (?string) |
null |
remote → jobLocationType: TELECOMMUTE und kein jobLocation; vor_ort → weder jobLocationType noch applicantLocationRequirements; ohne Angabe gilt remote |
address (street_address, postal_code, address_locality, address_country) |
address (?JobAddress) |
null |
jobLocation (Place + PostalAddress, leere Teile entfallen; ohne address der Freitext location) |
base_salary (currency, unit, value oder min_value/max_value) |
baseSalary (?BaseSalary) |
null |
baseSalary (MonetaryAmount mit QuantitativeValue; Einheit HOUR, DAY, WEEK, MONTH oder YEAR) |
Ein Arbeitgeber ohne Namen gilt als fehlend; Ländercodes werden großgeschrieben, ungültige und doppelte entfallen. Ein ungültiges Gehalt (unbekannte Einheit, Währung kein 3-Buchstaben-Code, kein oder negativer Betrag) und eine unbrauchbare Adresse gelten als fehlend. Das Beispiel oben gibt Remote- und Vor-Ort-Stellen ohne weitere Logik korrekt aus: <x-consentlaw::jobs-schema> übernimmt Ort, Remote-Angaben und Gehalt.
Format der Inhalte
consentLaw liefert Inhalte je Endpunkt als Markdown oder HTML. Das format-Feld der
API-Antwort (markdown bzw. html) gilt immer. Schickt die API kein format mit,
gilt markdown – es gibt keine Erkennung am Inhalt mehr. So läuft auch ein
HTML-artiger Inhalt ohne Formatangabe durch den Markdown-Filter (siehe unten) und nie
ungefiltert auf die Seite.
Allowlist: Nur ein Format, das exakt html lautet, wird ungefiltert ausgegeben.
Jeder andere Wert (leer, HTML, Html, text, unbekannt, falscher Datentyp) gilt als
Markdown und läuft durch den Filter. Das gilt für Dokumente (format) ebenso wie für
Job-Beschreibungen (description_format). Die Normalisierung passiert an einer Stelle
(ITHilbert\ConsentLaw\Data\Inhaltsformat::ausApi()); die Properties format und
descriptionFormat liefern danach immer markdown oder html.
Zeilenumbrüche: consentLaw pflegt Texte zeilenweise (z. B. Adressblöcke). Deshalb
gilt bei Markdown ein einfacher Zeilenumbruch (\n oder \r\n) als Zeilenumbruch und
wird als <br /> ausgegeben – nicht als Leerzeichen wie im CommonMark-Standard. Eine
Leerzeile trennt weiterhin Absätze (<p>); Listen, Überschriften, Tabellen und
Code-Blöcke bleiben unverändert. Zwei Leerzeichen oder ein Backslash am Zeilenende sowie
ein <br> vor dem Zeilenende ergeben ebenfalls genau ein <br />. Das gilt an allen
Ausgabestellen (Dokumente, Job-Beschreibungen, JSON-LD). Inhalte mit format: html
sind nicht betroffen.
Sicherheit der Markdown-Ausgabe
Markdown aus consentLaw wird an einer Stelle gerendert
(ITHilbert\ConsentLaw\Support\MarkdownRenderer::render()), genutzt von allen
Komponenten, den Fertig-Seiten und dem JSON-LD der Jobs. Der Renderer filtert:
- Rohes HTML (
<script>,<iframe>,<img onerror=…>, Event-Handler) wird entfernt, nicht escaped. - Unsichere Link-Ziele (
javascript:,data:,vbscript:) werden entfernt. <br>,<br/>und<br />bleiben als Zeilenumbruch erhalten; einfache Zeilenumbrüche werden ebenfalls zu<br />(siehe „Format der Inhalte“).- GitHub-Flavored Markdown (Tabellen, Durchgestrichenes, Autolinks) wird unterstützt.
Wer Markdown in eigenem Markup ausgibt, nutzt denselben Renderer statt Str::markdown().
Inhalte mit format: html werden nicht durch den Renderer geschickt – consentLaw
filtert HTML beim Speichern.
Sicherheit des Tokens
Der Domain-Token steht im URL-Pfad der API (api/impressum/<token>) und ist ein
Geheimnis. Er erscheint nie im Klartext in Exception-Meldungen, Log-Einträgen oder
der Ausgabe von consentlaw:load. Die Maskierung passiert an einer Stelle
(ITHilbert\ConsentLaw\Support\TokenMaskierung, genutzt vom HttpTransport und von der
Störungsmeldung an alerts) und gilt auch für Meldungen fremder Bibliotheken (Guzzle/cURL nennen die vollständige URL):
- URLs erscheinen mit maskiertem Token, z. B.
…/api/impressum/abcd…– höchstens die ersten 4 Zeichen bleiben sichtbar. - Tokens mit bis zu 4 Zeichen werden vollständig maskiert (
***). - Die URL ohne Token bleibt zur Diagnose in der Meldung.
Wer eine Logzeile mit Token aus einer älteren Version findet: Token in consentLaw rotieren (Aufgabe des Betreibers) und alte Logs bereinigen.
Anpassbare Views
php artisan vendor:publish --tag=consentlaw-views
Danach liegen die Templates unter resources/views/vendor/consentlaw/.
Eigener Fallback-Speicher
Wer statt Dateien eine Datenbank nutzen will, implementiert
ITHilbert\ConsentLaw\Contracts\FallbackStore und bindet ihn im eigenen
ServiceProvider:
$this->app->singleton(FallbackStore::class, DatabaseFallbackStore::class);
Changelog
Unveröffentlicht
- Neu: Arbeitsort, Adresse und Gehalt je Stelle:
Job::$workLocation,$address(JobAddress),$baseSalary(BaseSalary); das JSON-LD enthältjobLocationals PostalAddress, beiremotenur TELECOMMUTE, undbaseSalary. - Neu: Jobs für Google for Jobs:
Job::$hiringOrganization,$remote,$applicantCountriesund die Komponente<x-consentlaw::jobs-schema>(siehe „Eigenes Markup“). Das JSON-LD wird in PHP gebaut; zuvor zerstörte die@context-Blade-Direktive es. - Fix: Die Rückleitung des „Neu laden“-Buttons funktioniert auch ohne Referer (z. B.
Referrer-Policy: no-referrer): Das Formular sendet die aktuelle Adresse im Feldzurueck, ausgewertet wird nur ein lokaler Pfad. - Breaking: Die ENV-Variable
CONSENTLAW_REFRESH_BUTTONentfällt. Der „Neu laden“-Button folgt dem zentralen Hilfen-SchalterAPP_TEST(Configrefresh_button). Der Schalter wirkt jetzt auch auf Production; die bisherige Sperre fürproductionentfällt. Bei veröffentlichter Config'refresh_button' => env('APP_TEST', false)übernehmen, in der.envCONSENTLAW_REFRESH_BUTTONdurchAPP_TESTersetzen. - Der Button steht jetzt vor dem Inhalt bzw. Slot (auch bei Störung ohne Fallback) und bringt
ein eigenes, überschreibbares Stylesheet (
.consentlaw-refresh) mit. Bei veröffentlichten Views das Partialpartials/neu-laden.blade.phpneu übernehmen und das@includein eigenen Kopien vondocumentundjobsan den Anfang setzen. NeuLadenFreigabehängt nicht mehr vonApplicationab.- Route und Limiter
consentlaw-neu-ladensind jetzt immer registriert; die Freigabe prüft nur noch die Aktion (ohne Schalter 404 ohne API-Aufruf) und das Partial (Button). Damit ist es egal, ob die Routen gecacht sind (route:cache). Bei gecachter Config nach einer Änderung anAPP_TESTphp artisan config:clearausführen. - Neu: Störungsmeldung (siehe „Störungsmeldung über alerts“). Events
RechtstextNichtLieferbar,NotstandVeraltetundTokenVermutlichUngueltig; ein mitgelieferter Listener schickt dazu eine Mail (höchstens eine je Fall und 24 h). Neue ENV-VariablenCONSENTLAW_ALERT_MAIL,CONSENTLAW_ALERT_MAILER,CONSENTLAW_ALERT_LISTENER. OhneCONSENTLAW_ALERT_MAILgeht keine Mail raus. Bei veröffentlichter Config den Blockalertsergänzen (sonst gelten die Standardwerte); bei veröffentlichten Views kommtmail/stoerung.blade.phpneu hinzu. ContentResolver::resolve()erwartet zusätzlichtypundlocale(für die Störungsmeldung), der Konstruktor zusätzlich den Event-Dispatcher. Betrifft nur, wer den Resolver direkt nutzt.- Breaking: Die Störungsmeldung läuft über das Basis-Package
ithilbert/alerts(PortAlertReporter). Die eigene Mail-Infrastruktur des Packages entfällt. Umstellung:.env:CONSENTLAW_ALERT_MAIL→ALERTS_MAIL_TO,CONSENTLAW_ALERT_MAILER→ALERTS_MAILER. Die Werte bleiben gleich.CONSENTLAW_ALERT_LISTENERentfällt ersatzlos. Der Listener ist immer aktiv. Meldungen lassen sich in alerts abschalten, z. B. mitALERTS_ENABLED=false.- Die Schlüssel der Meldungen lauten
consentlaw.nicht-lieferbar,consentlaw.notstand-veraltetundconsentlaw.token-vermutlich-ungueltig. Freigabe:php artisan alerts:reset <schlüssel>. - Host-
composer.json: VCS-Repositoryhttps://github.com/ITHilbert/alerts.giteintragen (privat, GitHub-Token nötig; bis zum Releasedev-main). Danncomposer update ithilbert/consentlaw-client ithilbert/alerts. - Bei veröffentlichter Config (
config/consentlaw.php) den Blockalertslöschen. - Die veröffentlichte Vorlage
resources/views/vendor/consentlaw/mail/stoerung.blade.phpwird nicht mehr genutzt und kann gelöscht werden. - Eine eigene 24-h-Sperre gibt es nicht mehr. Die Drosselung macht alerts
(
ALERTS_SPERRE_STUNDEN, Standard 24).
Upgrade auf 1.2
- Neu: „Neu laden“-Button für Entwicklung und Test (siehe „Neu laden per Button (Entwicklung)“). Er ist standardmäßig aus und auf Production nie aktiv – bestehende Installationen ändern sich nicht.
- Neuer Config-Schlüssel
refresh_button(ENVCONSENTLAW_REFRESH_BUTTON, Standardfalse). Bei veröffentlichter Config (vendor:publish) den Schlüssel ergänzen. - Bei veröffentlichten Views (
consentlaw-views) die neue Teilansichtcomponents/partials/neu-laden.blade.phpübernehmen und in eigenen Kopien voncomponents/document.blade.phpundcomponents/jobs.blade.phpam Ende einbinden:@include('consentlaw::components.partials.neu-laden', ['typ' => $type, 'locale' => $locale])(Jobs:['typ' => 'jobs', 'locale' => $locale]). Ohnelocalelädt der Button bei Komponenten mit Sprachangabe die falsche Variante. - Die Route nutzt die Middleware-Gruppe
webund den Aliasthrottle; beides bringt jede Laravel-App mit.
Sicherheits-Update 1.1.1
Verlangt league/commonmark ab 2.10.2. Ältere Versionen haben einen DoS in der GFM-Tabellen-Erweiterung (GHSA-3q6v-r5mr-hxv8) und einen Bypass von DisallowedRawHtml (GHSA-97jj-33gv-5xf9). Nach dem Update im Kundenprojekt: composer update ithilbert/consentlaw-client league/commonmark.
Upgrade auf 1.1
- Verhaltensänderung: Ein einfacher Zeilenumbruch im Markdown wird jetzt als
<br />ausgegeben (vorher: Leerzeichen, Text lief in einer Zeile zusammen). Texte, die über mehrere Zeilen umbrochen im Markdown stehen (Fließtext mit fester Zeilenbreite), erscheinen dadurch mit Zeilenumbrüchen – Absätze gehören in consentLaw durch Leerzeilen getrennt. Betroffen sind Dokumente, Job-Beschreibungen und JSON-LD. Eigene, veröffentlichte Views müssen nicht angepasst werden. - Der Token wird in Exception-Meldungen und Logs maskiert (siehe „Sicherheit des Tokens“). Code, der den Token aus Meldungen herausliest, funktioniert nicht mehr.
Upgrade auf 1.0
Änderungen, die bestehenden Code betreffen können:
ContentResolver::resolve()liefert jetztITHilbert\ConsentLaw\Data\Abruf(Status, Payload, Abrufzeitpunkt) statt?array. Nur relevant, wenn der Resolver direkt verwendet oder ersetzt wird; die Endpoints (get(),all()…) sind unverändert und bieten zusätzlichabrufen().- Die Standard-URL ist
https://www.consentlaw.eu(vorherhttps://consentlaw.eu, das per 301 weiterleitete). Eine eigeneCONSENTLAW_URLbleibt unberührt. - Die Formaterkennung am Inhalt entfällt: Ohne
formatin der API-Antwort giltmarkdown. - Neuer Config-Schlüssel
fallback.retry_after(ENVCONSENTLAW_FALLBACK_RETRY_AFTER, Standard300): Wartezeit nach einer Störung. Bei veröffentlichter Config (vendor:publish) den Schlüssel ergänzen. - Nur ein 404 gilt als „nicht veröffentlicht“ (wird gecacht, nicht wiederholt); jeder andere Fehlerstatus gilt als Störung und liefert den Fallback.
- Markdown wird gefiltert gerendert (
MarkdownRenderer), rohes HTML undjavascript:-Links werden entfernt. consentlaw:loadendet bei „nicht veröffentlicht“ mit Exit-Code 0, außer alle Typen sind 404 (Token prüfen).
Lizenz
MIT – IT-Hilbert GmbH