GbmedAcl: Berechtigungssystem für Shopware 6 Storefront
Das Plugin ergänzt den Shop um ein Berechtigungssystem für das Storefront. Damit lässt sich für einzelne Kunden oder für ganze Kundengruppen festlegen, was sie im Storefront sehen und tun dürfen: zum Beispiel ob Preise angezeigt werden, ob überhaupt bestellt werden darf oder ob das Kundenkonto zugänglich ist. Die Grundlage dafür sind sogenannte Privilegien (einzelne, klar abgegrenzte Berechtigungen) und Rollen (Zusammenstellungen mehrerer Privilegien), die im Administrationsbereich verwaltet und anschließend Kunden bzw. Kundengruppen zugewiesen werden.
GbmedAcl wurde bewusst als Grundgerüst für individuelle Berechtigungslogik entwickelt: Eigene Plugins können auf dieser Basis eigene Privilegien anlegen, eigene Weiterleitungsregeln (Redirects) ergänzen und sich über bereitgestellte Events in die Berechtigungsprüfung einklinken, um projektspezifische Anforderungen umzusetzen, ohne den Kern des Plugins verändern zu müssen. Die entsprechenden Ansatzpunkte sind am Ende dieser Dokumentation im Abschnitt "Erweiterbarkeit für eigene Plugins" beschrieben.
Plugin-Grundeinstellungen
Unter den Plugin-Einstellungen lässt sich festlegen, auf welchen Seiten ein Kunde ohne ausreichende Berechtigung automatisch auf die Startseite umgeleitet wird, statt lediglich die entsprechenden Inhalte ausgeblendet zu bekommen. Zur Auswahl stehen die Bereiche "Kundenkonto", "Bestellungen" und "Checkout". Ist ein Bereich hier nicht ausgewählt, werden fehlende Berechtigungen dort nur durch das Ausblenden von Inhalten sichtbar, es findet aber keine Weiterleitung statt. Diese Einstellung wirkt sich direkt auf das Verhalten aller weiter unten beschriebenen Storefront-Bereiche aus.
Diese drei mitgelieferten Bereiche sind fest vorgegeben und lassen sich nicht über die Oberfläche um weitere Auswahlmöglichkeiten ergänzen. Für zusätzliche, projektspezifische Weiterleitungsregeln kann jedoch ein eigenes Plugin auf Basis von GbmedAcl eigene Redirects bereitstellen (siehe Eigene Redirects).

Kunden Nutzerverwaltung öffnen
Die eigentliche Verwaltung von Privilegien und Rollen findet nicht bei den Plugin-Grundeinstellungen statt, sondern in einem eigenen Menüpunkt der Administration. Er befindet sich unter Einstellungen > Kunden Nutzerverwaltung und ist von dort für jeden Administrator mit entsprechender Berechtigung erreichbar.
Beim Öffnen zeigt die Seite zwei Reiter: Rollen und Privilegien. Der Reiter "Rollen" ist voreingestellt geöffnet und listet alle vorhandenen Berechtigungsrollen samt zugewiesenen Privilegien, Kundengruppen und Kunden auf; von hier aus werden neue Rollen angelegt, bestehende bearbeitet oder gelöscht (siehe Rollenverwaltung). Der Reiter "Privilegien" zeigt die Liste aller im Shop verfügbaren, einzeln schaltbaren Berechtigungen, aus denen sich Rollen zusammensetzen (siehe Privilegien-Verwaltung). Über die Schaltfläche "Hinzufügen" oben rechts, kann je nach aktivem Reiter direkt eine neue Rolle bzw. ein neues Privileg angelegt werden.

Rollenverwaltung
Eine Rolle fasst mehrere Privilegien zu einem wiederverwendbaren Berechtigungspaket zusammen, zum Beispiel "Standard-Kunde" oder "Nur Ansicht ohne Preise". Beim Anlegen oder Bearbeiten einer Rolle werden ein Name und optional eine Beschreibung vergeben, die gewünschten Privilegien über Schalter aktiviert und die Rolle direkt einer oder mehreren Kundengruppen sowie einzelnen Kunden zugeordnet. Eine Rolle kann also sowohl pauschal für eine ganze Kundengruppe als auch gezielt für einen bestimmten Kunden vergeben werden; besitzt ein Kunde sowohl über seine Kundengruppe als auch persönlich zugewiesene Rollen, gelten die Privilegien aus allen zutreffenden Rollen gemeinsam. Name und Beschreibung dienen dabei ausschließlich der internen Wiedererkennung im Admin und werden dem Kunden im Storefront nicht angezeigt.
Zusätzlich besitzt jede Rolle das Merkmal "Admin". Ist eine Rolle als Admin markiert, hat jeder Kunde mit dieser Rolle automatisch Zugriff auf alle geschützten Funktionen des Shops, unabhängig davon, welche einzelnen Privilegien der Rolle zugewiesen sind oder fehlen — sämtliche Berechtigungsprüfungen fallen für ihn immer positiv aus. Das eignet sich zum Beispiel für interne Test- oder Servicekonten, die uneingeschränkten Zugriff benötigen.

Ein Klick auf eine Rolle in der Liste öffnet ein Modal-Fenster zur Bearbeitung einer Rolle. Im Formular werden Name und Beschreibung der Rolle gepflegt, die nur zu internen Zwecken dienen. Die Rolle kann direkt Kundengruppen oder Kunden zugewiesen werden. Aus den verfügbaren Privilegien kann gezielt das Recht eingestellt werden.

Privilegien-Verwaltung
Privilegien sind die kleinsten, einzeln schaltbaren Berechtigungen des Plugins, zum Beispiel "Preise sehen" oder "Bestellungen anlegen". In dieser Verwaltung wird die Liste der im Shop verfügbaren Privilegien gepflegt: das Privileg (z. B. price:read) für die Prüfung, eine Priorität für die Sortierung sowie Name und Beschreibung für interne Zwecke. Neue Einträge werden direkt in der Tabelle per Inline-Bearbeitung angelegt oder geändert; das Plugin liefert bereits eine Reihe von Standard-Privilegien mit, auf denen die unten beschriebenen Storefront-Funktionen aufbauen. Diese Liste bildet die Grundlage für die Rollenverwaltung, da dort nur Privilegien ausgewählt werden können, die hier vorhanden sind.
Der Anzeigename und die Beschreibung eines Privilegs dienen ausschließlich der Übersicht im Admin, etwa als Beschriftung der Schalter bei der Rollen-Bearbeitung; im Storefront werden sie an keiner Stelle angezeigt.

Standard-Privilegien
Das Plugin wird mit einer vordefinierten Sammlung von Standard-Privilegien installiert, die die grundlegenden Berechtigungen für eine typische Shop-Nutzung abdecken. Diese Privilegien können direkt in Rollen verwendet werden und steuern, auf welche Bereiche und Funktionen Kunden Zugriff haben. Die folgende Tabelle gibt einen Überblick über alle verfügbaren Standard-Privilegien:
| Privileg | Name | Beschreibung |
|---|---|---|
| product:read | Produkte sehen | Der Kunde kann Produktlisten und Produktdetails anschauen |
| price:read | Preise sehen | Der Kunde kann Produktpreise an allen Stellen im Shop anschauen |
| account:read | Konto sehen | Der Kunde kann sich anmelden und anschließend auf sein Kundenkonto sowie die dort hinterlegten Kontodaten zugreifen |
| account:create | Registrierung erlaubt | Der Kunde kann sich im Shop registrieren und ein Konto erstellen |
| order:read | Bestellungen sehen | Der Kunde kann seine Bestellhistorie und bestehende Bestellungen anschauen |
| order:create | Bestellungen anlegen | Der Kunde kann Produkte in den Warenkorb legen und Bestellungen abschließen |
Diese Privilegien bilden die Grundlage für die meisten Szenarien. Sie können sie in unterschiedlichen Kombinationen zu Rollen zusammenfassen, um verschiedene Kundenprofile zu erstellen, zum Beispiel "Nur Ansicht", "Kunde mit Kaufrecht" oder "Registrierter Benutzer".
Rollen am Kundenprofil
In der Kundenverwaltung wird auf der Detailseite eines einzelnen Kunden zusätzlich angezeigt, welche ACL-Rollen diesem Kunden persönlich zugewiesen sind, und es können dort direkt weitere Rollen hinzugefügt oder entfernt werden. Das ist der schnellste Weg, um die Berechtigungen für genau einen bestimmten Kunden individuell anzupassen, unabhängig davon, welche Rollen über dessen Kundengruppe ohnehin gelten.

Rollen an der Kundengruppe
Ebenso lassen sich auf der Detailseite einer Kundengruppe ACL-Rollen hinterlegen. Diese Rollen gelten dann automatisch für alle Kunden, die dieser Kundengruppe angehören, sofern für den einzelnen Kunden keine abweichenden, persönlichen Rollen vergeben wurden. Das eignet sich, um größere Kundensegmente (z. B. "Händler" oder "Geschäftskunden") mit einheitlichen Berechtigungen zu versehen, ohne jeden Kunden einzeln pflegen zu müssen. Direkt nach der Installation wird für alle bestehenden Kundengruppen automatisch eine mitgelieferte Standardrolle hinterlegt.

Erweiterbarkeit für eigene Plugins
GbmedAcl wurde bewusst als flexibles Grundgerüst für eine individuelle Berechtigungslogik entwickelt. Dadurch können Entwickler eigene Plugins auf Basis von GbmedAcl erstellen und die vorhandene Zugriffskontrolle gezielt an die Anforderungen ihres Projekts anpassen.
Über die vorgesehenen Erweiterungspunkte lassen sich beispielsweise eigene Privilegien und Benutzerrechte definieren, individuelle Weiterleitungsregeln (Redirects) ergänzen oder vorhandene Events nutzen, um eigene Funktionen in den Ablauf der Berechtigungsprüfung einzubinden. So können auch komplexere oder projektspezifische Anforderungen an Zugriffsrechte und Benutzerberechtigungen umgesetzt werden.
Ein wichtiger Vorteil dabei: Der Core von GbmedAcl Plugin muss nicht verändert werden. Eigene Erweiterungen bleiben dadurch vom grundlegenden Plugin-Code getrennt und können unabhängig von der zentralen Berechtigungslogik umgesetzt werden.
Eigene Privilegien
Ein eigenes Privileg ist zunächst nichts weiter als eine frei wählbare Zeichenkette (z. B. mein-plugin:sonderpreis-sehen), die als Schlüssel in einer Rolle hinterlegt und anschließend geprüft wird. Damit ein solches Privileg auch in der Rollen-Bearbeitung im Admin auswählbar ist, kann das Privileg Manuell in der Privilegien-Verwaltung im Admin anlegen (siehe Privilegien-Verwaltung).
Wird ein Privileg nicht dauerhaft in der Datenbank benötigt, sondern nur zur Laufzeit angeboten, kann es alternativ über das Event Gbmed\Acl\Event\GbmedAclPrivilegesEvent ergänzt werden; es taucht dann ebenfalls in der Privilegien-Auswahl der Rollen-Bearbeitung auf, ohne einen eigenen Datenbank-Eintrag zu benötigen.
namespace MeinPlugin\Subscriber;
use Gbmed\Acl\Core\Content\GbmedAcl\Aggregate\GbmedAclPrivilege\GbmedAclPrivilegeEntity;
use Gbmed\Acl\Event\GbmedAclPrivilegesEvent;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class CustomPrivilegesSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
GbmedAclPrivilegesEvent::class => 'onGbmedAclPrivilegesEvent',
];
}
public function onGbmedAclPrivilegesEvent(GbmedAclPrivilegesEvent $event)
{
$privilege = new GbmedAclPrivilegeEntity();
$privilege->setId(Uuid::fromStringToHex('mein-plugin:sonderpreis-sehen'));
$privilege->setPrivilege('mein-plugin:sonderpreis-sehen');
$privilege->setPriority(100);
$privilege->setName('Sonderpreis sehen');
$privilege->setDescription('Der Kunde kann seinen Sonderpreis sehen.');
$event->addPrivilege($privilege);
}
}

In eigenen Twig-Templates wird ein Privileg über die Funktion acl_can() geprüft, die für den aktuell im Storefront aktiven Kunden true oder false liefert:
{% set can = acl_can('mein-plugin:sonderpreis-sehen') %}
{% if can %}
{{ sonderpreis }}
{% endif %}
acl_can() akzeptiert auch ein Array mehrerer Privilegien und liefert dann true, sobald mindestens eines davon zutrifft.
Für die Prüfung von Benutzer- und Zugriffsrechten im PHP-Code steht der AclRoleService zur Verfügung. Der Service übernimmt die eigentliche Abfrage der Berechtigungen und kann dadurch verwendet werden, um innerhalb des eigenen Plugins gezielt zu prüfen, ob ein Benutzer über ein bestimmtes Recht oder Privileg verfügt.
Der AclRoleService wird bereits beim Erstellen des SalesChannelContext eingebunden. Dadurch ist der Service innerhalb des entsprechenden Kontextes verfügbar und kann an den vorgesehenen Stellen im PHP-Code jederzeit für Berechtigungsprüfungen verwendet werden.
$salesChannelContext = $event->getSalesChannelContext();
$aclRoleService = AclRoleService::getAclRoleService($salesChannelContext);
$can = $aclRoleService ? $aclRoleService->can('mein-plugin:sonderpreis-sehen') : false;
if (!$can) {
return;
}
Eigene Redirects
Ein Redirect entscheidet, ob ein Kunde ohne ausreichende Berechtigung beim Aufruf bestimmter Seiten auf die Startseite umgeleitet wird. Ein eigener Redirect wird als Klasse angelegt, die von Gbmed\Acl\Core\AclRedirect\AbstractAclRedirect erbt und zwei Methoden implementiert: getRedirectName() liefert einen eindeutigen technischen Namen, redirect(ResponseEvent $event) enthält die eigentliche Prüf- und Weiterleitungslogik.
namespace MeinPlugin\Core\AclRedirect;
use Gbmed\Acl\Core\AclRedirect\AbstractAclRedirect;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
class MeinBereichRedirect extends AbstractAclRedirect
{
public function getRedirectName(): string
{
return 'mein_bereich';
}
public function redirect(ResponseEvent $event): void
{
$request = $event->getRequest();
$role = $this->getAclRoleService($request);
if (!$role || $role->can('mein-plugin:sonderbereich-sehen')) {
return;
}
if ($this->checkRoute($this->getRoute($request), ['mein_plugin.sonderbereich.page'])) {
$event->setResponse($this->redirectToRoute('frontend.home.page'));
}
}
}
Damit die Registry sie automatisch bei jeder Antwort mit ausführt, wird die Klasse als Service mit dem Tag gbmed.acl.redirect registriert:
<service id="MeinPlugin\Core\AclRedirect\MeinBereichRedirect">
<argument type="service" id="router"/>
<argument type="service" id="Shopware\Core\System\SystemConfig\SystemConfigService"/>
<argument type="service" id="event_dispatcher"/>
<tag name="gbmed.acl.redirect"/>
</service>
Die Basisklasse AbstractAclRedirect stellt dafür bereits Hilfsmethoden bereit, u. a. getAclRoleService() (Berechtigungsobjekt des aktuellen Kunden), getRoute() (aktuell aufgerufene Route), checkRoute() (Abgleich gegen eine Liste von Routen) und redirectToRoute(). Die generische Ein/Aus-Schaltung in den Plugin-Grundeinstellungen ("Redirect anwenden bei") kennt nur die drei mitgelieferten Bereiche Kundenkonto, Bestellungen und Checkout; ein eigener Redirect entscheidet daher üblicherweise eigenständig, ob und wann er aktiv wird, statt sich auf isSystemConfigRedirectOn() zu verlassen.
Events
GbmedAcl stellt mehrere Events bereit, über die sich eigene Plugins in die Berechtigungsprüfung einklinken können, ohne bestehenden Code zu verändern:
Gbmed\Acl\Event\GbmedAclPrivilegesEvent wird ausgelöst, sobald die Liste der verfügbaren Privilegien zusammengestellt wird (u. a. für die Privilegien-Auswahl in der Rollen-Bearbeitung im Admin). Über $event->addPrivilege() bzw. $event->addPrivileges() lassen sich weitere, rein zur Laufzeit erzeugte Privilegien ergänzen, ohne dass dafür ein Datenbank-Eintrag notwendig ist.
Gbmed\Acl\Event\GbmedAclRoleEvent wird am Ende jeder can()-Prüfung ausgelöst und enthält das bisher ermittelte Ergebnis, das geprüfte Privileg (bzw. die geprüften Privilegien), die vollständige Privilegien-Zuordnung des Kunden sowie den Sales-Channel-Kontext. Über $event->setResult() kann das Ergebnis der Prüfung nachträglich anhand eigener, zusätzlicher Kriterien überschrieben werden, zum Beispiel um ein Privileg abhängig von einer eigenen Kundeneigenschaft zusätzlich freizuschalten oder gezielt zu sperren.
Gbmed\Acl\Event\GbmedAclRedirectBlacklistEvent (und die XHR-Variante GbmedAclRedirectBlacklistXhrEvent) werden von den mitgelieferten Redirects (Kundenkonto, Bestellungen, Checkout) ausgelöst, kurz bevor die aktuelle Route gegen deren Liste zu schützender Routen geprüft wird. Über $event->addBlacklist() lassen sich eigene Routen in diese bestehenden Redirects mit aufnehmen, ohne dafür einen komplett eigenen Redirect (siehe Eigene Redirects) schreiben zu müssen:
namespace MeinPlugin\Subscriber;
use Gbmed\Acl\Event\GbmedAclRedirectBlacklistEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class MeineRouteZumCheckoutRedirectHinzufuegenSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
GbmedAclRedirectBlacklistEvent::class => 'onBlacklist',
];
}
public function onBlacklist(GbmedAclRedirectBlacklistEvent $event): void
{
$event->addBlacklist('mein_plugin.checkout_erweiterung.page');
}
}