Oro BAP Tutorial OrderManager: Teil 5 – Berechtigungen

In den vorangegangenen Tutorials zur Entwicklung mit der ORO-Platform haben wir an dieser Stelle bereits eine funktionsfähige E-Commerce Anwendung erstellt, mit der Bestellungen betrachtet,  bearbeitet, neu angelegt und gelöscht  werden können. 

In diesem Beitrag soll nun das mächtige Rechte- und Rollensystem der ORO-Platform vorgestellt werden. Nach einer Beschreibung der allgemeinen Konzepte und Strukturen soll die Funktionsweise am praktischen Beispiel  gezeigt werden, indem die „OrderManager“ –Anwendung dieser Tutorial-Serie um konkrete Berechtigungen erweitert wird.

Allgemeiner Aufbau und Struktur

Die Oro-Platform enthält ein sehr leistungsfähiges und flexibles Modell, um verschiedenen Benutzern Zugriff auf einzelne Seiten, Aktionen und Daten zu gewähren oder zu verbieten.

Grundlegend basiert die Rechteverwaltung auf den Access Control Lists (kurz ACL) des Frameworks Symfony2, welche durch Oro aber erweitert werden.

Business Unit

Zentrales Element der Zugriffskontrolle sind in Oro „Business Unit“ genannte Organisationseinheiten. Diese Business Units (kurz BU oder auf Deutsch: „Geschäftsbereich“) lassen sich auf verschiedenen Ebenen hierarchisch strukturieren. 

Möchte man Daten mit Berechtigungen versehen, so muss man einzelne Datensätzen zu einer solchen Business Unit zuweisen. Dadurch wird diese Business Unit zum „Besitzer“ des Datensatzes.

Um einem Benutzer nun den Zugriff auf konkrete Datensätze zu gewähren, ordnet man ihm eine oder mehrere dieser Business Units zu.

Zugriffsebenen

Das Zugriffskonzept von Oro ist aber noch weitaus komplexer und erlaubt den Zugriff auf Daten (über  die Business Units) auf verschiedenen Ebenen. Dazu können Business Units als hierarchische Struktur erstellt werden. 

Neben den Business Units gibt es dann noch mit den Organisationen ein weiteres übergeordnetes Element zur Zugriffskontrolle. Jede Business Unit  ist genau einer Organisation zugeordnet. Mit diesen Elementen ermöglicht Oro den Zugriff auf verschiedenen Ebenen:

System-EbeneEin User auf dieser Ebene hat Zugriff auf alle Daten im System
Organisations-EbeneDer User hat Zugriff auf alle Daten der Organisation und der untergeordneten Business-Units
Divisions-EbeneDer User hat Zugriff auf die Daten der ihm direkt zugeordneten Business Units und deren untergeordneten Business Units
Business Unit-EbeneDer User hat Zugriff auf die Daten der ihm direkt zugeordneten Business Units
User-EbeneDer User hat nur Zugriff auf die  ihm direkt zugeordneten Datensätze und die Datensätze, die speziell für ihn freigegeben wurden.

In der Dokumentation zur Oro-Platform finden sich einige Beispiele zur Verdeutlichung all dieser Zusammenhänge zwischen User, Business Units und Zugriffsebenen.

Allerdings ist eine Verwaltung von Organisationen über die GUI momentan nur in der Enterprise-Edition von OroCRM möglich.

Konkrete Rechtevergabe über Rollen

Wie bereits beschrieben, wird ein User also einer Business-Unit zugeordnet. Damit hat er aber noch kein Recht um auf konkrete Daten zuzugreifen. Denn bei Oro erfolgt die Rechtevergabe zusätzlich über Rollen. In einer Rolle werden konkrete Rechte auf Aktionen und Entitäten festgelegt. Ein Benutzer erhält dann eine oder mehrere solcher Rollen und kann darüber auf die Daten zugreifen.

Für jede Entity-Klasse (also für jeden Datentyp) gibt man in einer Rolle die Zugriffsebene für die Operationen „Anzeigen“, „Erstellen“, „Bearbeiten“, „Löschen“ und „Zuweisen“ an.

Dies erledigt man am bequemsten über die Verwaltungsoberfläche unter dem Menüpunkt System → Users management → Roles.

Im hier dargestellten Beispiel werden der Rolle „Marketing Manager“ Rechte für die Entities Kontakte und Kunden zugewiesen. 

Kontakte dürfen auf Systemebene angezeigt oder angelegt werden, also ohne Einschränkungen. Bearbeiten und Löschen stehen auf „None“ - Kontakte dürfen somit nicht bearbeitet und gelöscht werden.

Kundendaten wurden für die Operationen „Anzeigen“, „Erzeugen“ und „Bearbeiten“ der Ebene Division zugewiesen. Das heißt ein Benutzer der Rolle Marketing Manager kann die Operationen auf einen Datensatz durchführen, wenn der Datensatz der ihm direkt zugeordneten Business Unit oder aber einer untergeordneten Business-Unit gehört. Zum Löschen wurde die Ebene Business Unit eingestellt. Demzufolge darf der Nutzer nur Datensätze löschen, die der gleichen Business Unit zugewiesen sind.

Neben den Berechtigungen auf die Entities kann man zusätzlich auch den Zugriff auf einzelne Aktionen bzw. Routen steuern.

Hierzu findet sich in der Ansicht beim Bearbeiten einer Rolle der Abschnitt „Capabilities“. Für einzelne Aktionen kann man Zugriff gewähren (Wert „System“) oder verbieten (Wert „None“).

Nachfolgend werden die oben ausgeführten theoretischen Betrachtungen am konkreten Beispiel demonstriert. Dazu soll der OrderManager aus den vorherigen Artikeln unserer Tutorial-Serie um Berechtigungen erweitert werden. Als Ausgangspunkt dient der OrderManager in Version 0.4, also der Stand nach Tutorial 4 (Widgets).

Nehmen wir an, ein Modehaus hat diese Anwendung im Einsatz und verwaltet damit seine Bestellungen. Das Modehaus hat Kleidung verschiedener Marken im Angebot. Vertreter dieser Marken sollen sich im OrderManager einloggen können und dort ihre Bestellungen und die zugehörigen Kundendaten einsehen dürfen – natürlich nur die Bestellungen ihrer eigenen Marken. Um dies zu ermöglichen sind nachfolgende Schritte notwendig:

Annotations für Entites und Controller

Zunächst müssen für den Zugriff auf die Bestellungen, Bestellpositionen und Kunden die jeweiligen Entity-Klassen angepasst werden. Es werden ein neues Feld „owner“ sowie die zugehörigen Getter- und Setter-Methoden benötigt, mit denen eine Zuordnung zu einer Business-Unit möglich ist:

OrderBundle/Entity/Order.php:

[…]
use Oro\Bundle\OrganizationBundle\Entity\BusinessUnit;
use Oro\Bundle\EntityConfigBundle\Metadata\Annotation\Config;
class Order {
   […]
    /**
    * @var BusinessUnit
    * @ORM\ManyToOne(targetEntity="Oro\Bundle\OrganizationBundle\Entity\BusinessUnit")
    * @ORM\JoinColumn(name="owner", referencedColumnName="id", onDelete="SET NULL")
    */
    protected $owner;
   […]
    /**
     * @param BusinessUnit $owner
     */
    public function setOwner($owner) {
        $this->owner = $owner;
        return $this;
    }
    /**
     * @return BusinessUnit
     */
    public function getOwner() {
        return $this->owner;
    }
}

Um die Entity für die Rechteverwaltung zu registrieren, müssen nachfolgende Klassen-Annotationen ergänzt werden:

OrderBundle/Entity/Order.php:

 

[…]
 * @Config(
 *      routeName="acme_orders_order_index",
 *      defaultValues={
 *          "entity"={"icon"="icon-user", "label"="Bestellung", 
"plural_label"="Bestellungen"},
 *          "ownership"={
 *             "owner_type"="BUSINESS_UNIT",
 *             "owner_field_name"="owner",
 *             "owner_column_name"="owner"
 *          },
 *          "security"={
 *              "type"="ACL",
 *              "group_name"=""
 *          }
 *      }
 * )
class Order{
[…]

 

Für die Entities OrderPosition und Customer sind diese Schritte analog auszuführen, werden aber aus Platzgründen hier nicht extra aufgeführt. Damit die neuen Felder auch in der Datenbank erzeugt werden, führt man folgenden Befehl auf der Konsole aus:

 

php app/console-framework doctrine:schema:update –force --env dev

 

Im Controller müssen auch Annotationen und die benötigten use-Statements hinzugefügt werden, um die ACL für einzelne Actions zu registrieren.

OrderBundle/Controller/OrderController.php:

use Oro\Bundle\SecurityBundle\Annotation\Acl;
use Oro\Bundle\SecurityBundle\Annotation\AclAncestor;
[…]
/**
 * @Route(name="acme_orders_order_index")
 * @Acl(
 *      id="acme_orders_order_view",
 *      type="entity",
 *      class="AcmeOrderBundle:Order",
 *      permission="VIEW"
 * )
 * @Template
 */
public function indexAction(Request $request) {
return [];
}
/**
 * @Route(
 *    "/view/{id}", name="acme_orders_order_view", requirements={"id"="\d+"}
 * )
 * @AclAncestor("acme_orders_order_view")
 * @Template
 */
public function viewAction(Order $order) {
   […]
}
/**
 * @Acl(
 *      id="acme_orders_order_update",
 *      type="entity",
 *      class="AcmeOrderBundle:Order",
 *      permission="EDIT"
 * )
 * @Route("/update/{id}", name="acme_orders_order_update", requirements={"id"="\d+"})
 * @Template
 */
public function updateAction(Order $order) {
return $this->update($order);
}
/**
 * @Route("/create", name="acme_orders_order_create")
 * @Acl(
 *      id="acme_orders_order_create",
 *      type="entity",
 *      class="AcmeOrderBundle:Order",
 *      permission="CREATE"
 * )
 * @Template("AcmeOrderBundle:Order:update.html.twig")
 */
public function createAction()
{
return $this->update();
}
/**
 * @Route("/delete/{id}", name="acme_orders_order_delete", requirements={"id"="\d+"})
 * @Acl(
 *      id="acme_orders_order_delete",
 *      type="entity",
 *      class="AcmeOrderBundle:Order",
 *      permission="DELETE"
 * )
 */
public function deleteAction(Order $order){
   […]
}

Jetzt sind die technischen Vorarbeiten soweit abgeschlossen. Zum Abschluss muss der Befehl zum Aktualisieren der Konfiguration ausgeführt und der Cache geleert werden:

php app/console oro:entity-config:update
php app/console cache:clear

 

Konfiguration in der GUI

Als nächsten Schritt werden Business-Units angelegt und Bestellungen diesen Business-Units zugewiesen. Anschließend müssen Benutzer und Rollen mit den Berechtigungen ausgestattet werden.

All diese Aufgaben lassen sich über die GUI unter System  Users Management erledigen. Zunächst wählt man dort den Menüpunkt Business Unit aus. Hier legt man über den „create“-Button zwei Datensätze für die beiden Mode-Labels an, hier als ABC-Premium-Mode und XYZ-Fashion bezeichnet.

Anschließend navigiert man in die Bestellungsverwaltung, wählt einen Order-Datensatz und bearbeitet diesen. In der Eingabemaske sieht man nun das neue Owner-Feld, welches von Oro automatisch im ersten Daten-Block hinzugefügt wird. Hier wählt man den „Besitzer“ der Bestellung aus, in unserem Fall die ABC - Business Unit. Analog erledigt man das anschließend noch für die anderen Datensätze. In einer echten Anwendung sollte der Owner dann natürlich nicht manuell gesetzt werden müssen.

Dazu begibt man sich in das Menü System → Users Management → Roles. Dort wird eine neue Rolle für Vertreter angelegt. Dieser Rolle vergibt man Entity-Rechte für die Bestellungen. Ein Vertreter soll beispielsweise nur Bestellungen ansehen und neu erzeugen dürfen, jedoch nicht nachträglich bearbeiten oder löschen, daher setzt man den Wert für View und Create auf „Division“ und belässt den Rest bei „None“.

Ausblick

Das Rechtesystem in Oro ermöglicht komplexe und umfassende Möglichkeiten zur Zugriffssteuerung. In diesem Beitrag konnte lediglich ein grober Überblick gegeben werden.

Allerdings gibt es momentan noch einige Einschränkungen. Es existieren noch einige Bugs an verschiedenen Stellen, die vom Oro-Entwickler-Team jedoch meist recht schnell behoben werden. 

Weiterhin ist geplant zukünftig ein SHARE-Recht zu integrieren. Damit soll es möglich sein, unabhängige Business Units Zugriff auf die eigenen Daten zu erteilen.

Weitere Teile:

Kontaktieren Sie uns