Ungeahnte Probleme mit FW_ACL und FW_Form

Wer kennt das nicht?

Man hat eine oder mehrere Klassen fertig programmiert und getestet. Weit und breit keine gravierenden Fehler zu sehen! Man ist zufrieden mit seiner Arbeit und macht mit etwas anderem weiter.

FW_Acl

So war es auch bei mir, als ich die ACL (Access Control List) für mein Framework programmiert habe. Die ACL ist ein Hauptbestandteil des Frameworks. Sie verwaltet die Rechte von den Benutzergruppen.  Bei meinen Tests konnte ich keine Fehler feststellen. Doch als ich die FW_Acl heute in meinem aktuellen Projekt verwenden wollte, kam ein undefiniertes Verhalten zum Vorschein.

Als man in der ACL nur erlauben und nicht verbieten konnte, funktionierte alles wunderbar. Mit Einführung der disallow-Methode haben sich aber irgendwo Fehler eingeschlichen. Der Code ist 17kb lang und da macht es natürlich wahnsinnig viel Spass, nach den Fehlern zu suchen. Ich suche jetzt schon seit 19 Uhr und bin immer noch ganz am Anfang.

Das einzige, was ich weiß, ist, dass der Fehler irgendwo in der hasPermission-Methode zu suchen ist. Hier habe ich mal ein paar Debugging-Log-Zeilen eingefügt:

/**
   * @access public
   * @param string $role
   * @param string $resource
   * @param string $do_what
   * @return bool
   *
   * Wenn eine $role auf eine $resource Zugriff hat und $do_what ausführen darf,
   * gibt hasPermission true zurück. Sonst false
   */
  public function hasPermission($role, $resource, $do_what)
  {
    $role = (string)strtolower($role);
    $resource = (string)strtolower($resource);
    $do_what = (string)strtolower($do_what);

    /*
      Hier wird nicht geprüft, ob die Rollennamen und die Resourcennamen
      gültig sind, weil man so nicht jede einzelne Seite in seiner ACL angeben muss.
    */

    FW_Tools::AddStringToFile("acl.txt", "\n\n".$role.": ".$do_what." in ".$resource."\n");

    //als erstes wird geprüft, ob die Rolle Rechte auf alles hat.
    if(isset($this->rules["allow"]["permission_for_everything"][$role]))
    {
      FW_Tools::AddStringToFile("acl.txt", "alles ");
      return true;
    }
    else
    {
     FW_Tools::AddStringToFile("acl.txt", "nicht_alles ");
    }

    //wenn nicht, wird geprüft, ob rechte auf die geasmte Ressource bestehen
    if(isset($this->rules["allow"]["resources"][$resource]["roles"][$role]) &&
       count($this->rules["allow"]["resources"][$resource]["roles"][$role]) < 1)
    {
      FW_Tools::AddStringToFile("acl.txt", "gesamte_resource ");
      return true;
    }
    else
    {
      FW_Tools::AddStringToFile("acl.txt", "nicht_gesamte_resource ");
    }

    //wenn er nicht alle rechte auf alles hat und auch nicht alle rechte auf die
    //resource, wird geschaut, ob er die aktion do_what ausführen darf
    if(isset($this->rules["allow"]["resources"][$resource]["roles"][$role]) &&
       in_array($do_what, $this->rules["allow"]["resources"][$resource]["roles"][$role]))
    {
      FW_Tools::AddStringToFile("acl.txt", "aktion_in_resource ");
      return true;
    }
    else
    {
     FW_Tools::AddStringToFile("acl.txt", "nicht_aktion_in_resource ");
    }

    //Wenn Verbote für diesen User und diese Resource existieren, wird geprüft,
    //ob die Aktion auch verboten wurde. Wenn nicht, wird true zurück gegeben.
    if(isset($this->rules["disallow"]["resources"][$resource]["roles"][$role])
       && !in_array($do_what, $this->rules["disallow"]["resources"][$resource]["roles"][$role])
       && count($this->rules["disallow"]["resources"][$resource]["roles"][$role]) > 0)
    {
      FW_Tools::AddStringToFile("acl.txt", "nicht_verboten ");
      return true;
    }
    else
    {
      FW_Tools::AddStringToFile("acl.txt", "wurde_verboten_oder_nicht_erlaubt");
    }

    //vllt. gibt es vererbung?
    if(isset($this->roles[$role]["parents"]))
    {
      foreach($this->roles[$role]["parents"] as $parent_role_object)
      {
        if($this->hasPermission($parent_role_object->getRoleName(), $resource, $do_what))
        {
          return true;
        }
      }
    }

    return false;
  }

Ich vermute den Fehler in dieser Codepassage:

if(isset($this->rules["disallow"]["resources"][$resource]["roles"][$role])
       && !in_array($do_what, $this->rules["disallow"]["resources"][$resource]["roles"][$role])
       && count($this->rules["disallow"]["resources"][$resource]["roles"][$role]) > 0)
    {
      FW_Tools::AddStringToFile("acl.txt", "nicht_verboten ");
      return true;
    }
    else
    {
      FW_Tools::AddStringToFile("acl.txt", "wurde_verboten_oder_nicht_erlaubt");
    }

Das große Problem scheint in der Vererbung zu liegen. Ich will, dass sich die Klasse so verhält:

  • Man kann einzelnen Gruppen Zugriff auf alle Methoden einer Resource (entspricht einem Controller) geben.
  • Einzelne dieser Methoden können verboten werden. Die anderen Methoden dürfen aber trotzdem noch von dieser Gruppe ausgeführt werden.
  • Es können auch komplette Resourcen verboten werden. Das macht Sinn, wenn man einer Usergruppe Zugriff auf alle Resourcen mit ein paar Ausnahmen geben möchte
  • Wenn Gruppe A ein Verbot hat und Gruppe B von A erbt, hat auch Gruppe B dieses Verbot, außer das Verbot wird durch eine Erlaubnis aufgehoben.

Klingt kompliziert? Ist es auch! Ich blick jedenfalls nichtmehr durch. Vielleicht findet einer von euch ja den Fehler? Würde mich sehr freuen!

FW_Form

Dieser Fehler ist jetzt nicht soo schlimm. Ich habe in diesem Beispiel in einem Controller eine Methode, die das Formular erzeugt. Eine weitere Methode zeigt das Formular an und eine dritte überprüft das Formular und zeigt Fehler an. Wenn diese Methoden alle in einer Klasse liegen, ist das alles kein Problem!

Wenn es aber 2 Klassen gibt, die das gleiche Formular verwenden sollen, muss man sich entscheiden:

  • Formular-Objekt irgendwo ablegen (Registry?) oder
  • Den Code zur Formularerstellung doppelt schreiben.

Was würdet ihr vorziehen?

1 Star2 Stars3 Stars4 Stars5 Stars (Wurde noch nicht bewertet)
Loading...


3 Kommentare zu “Ungeahnte Probleme mit FW_ACL und FW_Form”

  1. Hi,

    ich glaube in dieser Passage liegt der Fehler:

    if(isset($this->rules[„disallow“][„resources“][$resource][„roles“][$role])
    && !in_array($do_what, $this->rules[„disallow“][„resources“][$resource][„roles“][$role])
    && count($this->rules[„disallow“][„resources“][$resource][„roles“][$role]) > 0)

    (ka wie man das als Code formatiert hier ^^)

    hast du dieses Array $this->rules[„disallow“][„resources“][$resource][„roles“][$role] initialisiert? vermutlich in FW_Acl::addRole()?

  2. Danke, dass du dir die Mühe gemacht hast, nach dem Fehler zu suchen!

    Nein, das hab ich nicht initialisiert… Evtl. könnte es daran liegen!

    Da ich aber komischerweise keine Fehler mehr reproduziueren kann (Wenn man Fehler will, wollen die Fehler nicht :(), kann ich aber auch nicht testen, ob es daran liegt/lag.

    MfG Simon

  3. Die aktuellste Version meines HMVC-Frameworks erhaltet ihr ab sofort immer hier: http://www.net-developers.de/blog/2011/02/13/download-info-shfw-hmvc-framework-in-php/

Hinterlasse einen Kommentar!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

»Informationen zum Artikel

Autor: Simon
Datum: 18.03.2009
Zeit: 22:22 Uhr
Kategorien: Mein MVC-Framework
Gelesen: 5953x heute: 2x

Kommentare: RSS 2.0.
Diesen Artikel kommentieren oder einen Trackback senden.

»Meta