Christian Seiler: einfache, projektweite Rechteverwaltung/-prüfung

Beitrag lesen

Hallo Andreas,

Wenn es Dir auf Performance ankommt - IMHO kann PEAR::DB ne ganz schöne Bremse darstellen.

Du könntest Recht haben. Das Problem ist, das Ding ist auch ohne die Abstraktionsfähigkeiten ganz nett...

Aber was mache ich mit der Oberfläche? Vielleicht eine extra-Tabelle dafür?

Also ich habe das bei mir so gelöst: (ich vereinfache hier ziemlich stark, um möglichst nahe an das ranzukommen, was Du willst) Ich habe eine Tabelle global_acl, die sieht so aus:

CREATE TABLE global_acl (
  id_type INT(1) UNSIGNED NOT NULL,
  id INT(6) UNSIGNED NOT NULL,
  right_name VARCHAR(255) NOT NULL,
  PRIMARY KEY (id_type, id, right_name)
);

id_type ist entweder 1 für Gruppe oder 0 für Benutzer. ID ist dann die entsprechende Benutzer/Gruppen-ID. Bei Dir bräuchtest Du nur ein Feld: userlevel. right_name ist dann der Name des Rechts.

Ich habe dann zum einen folgende Backend-Funktionen:

has_right ($right_name)
   => hat der aktuelle Benutzer das Recht (geprüft über JOIN mit der Benutzer/Gruppen-Tabelle)

list_rights ()
   => listet alle Rechte in der Form:

array (
  0 => array (
    'id_type' => 1,
    'id' => 1,
    'rights' => array (
      'rechta',
      'rechtb',
      'rechtc'
    )
  ),
  1 => array (
    'id_type' => 1,
    'id' => 2,
    'rights' => array (
      'rechta',
      'rechtc',
      'rechtd',
      'rechte',
      'rechtf'
    )
  )
);

Das ist praktisch für die Anzeigefunktionien (s.u.) Den Teilsourcecode, um so eine Baumdarstellung zu bekommen, hänge ich ans Ende des Postings.

has_rights ()
  => Listet alle Recht des aktuellen Benutzers auf und gibt sie als normales Array zurück: array ('rechta', 'rechtb', 'rechtc') => über JOIN mit der Benutzer/Gruppendatenbank

set_right ($id_type, $id, $right_name)
  => setzt ein Recht

unset_right ($id_type, $id, $right_name)
  => löscht ein Recht

Dann habe ich noch vier weitere Funktionen zur Verwaltung:

display_acl_form ($addurl, $changeurl, $rights_array)
   => zeigt das Rechte-Formular an:

+-----------+----------+------------+------------+-----------+---------+
|           | Recht A  | Recht B    | Recht C    | Recht D   | Recht E |
+-----------+----------+------------+------------+-----------+---------+
| Gruppe 1  |    [ ]   |     [ ]    |     [ ]    |    [X]    |   [X]   |
| Gruppe 2  |    [X]   |     [ ]    |     [X]    |    [ ]    |   [X]   |
| Benutzer1 |    [ ]   |     [X]    |     [ ]    |    [ ]    |   [ ]   |
+-----------+----------+------------+------------+-----------+---------+

- $addurl ist die URL des Scripts, das display_acl_add_form aufrufen wird. (su.)
 - $changeurl ist die URL des Scripts, das bei einem POST-Request process_acl_form aufrufen wird (su.)
 - $rights_array sind alle _verfügbaren_ Rechte (array ('rechta', 'rechtb', 'rechtc'))

process_acl_form ($rights_array)
   => Verarbeitet das Rechte-Formular

display_acl_add_form ($addurl, $backurl, $rights_array)
  => Zeit ein Rechte-Hinzufüge-Formular an:

+------------+--------------------------------+
| Typ        | [Gruppe_________]              |
+------------+--------------------------------+
| Gruppe     | [Gruppe 1_______]              |
+------------+--------------------------------+
| Benutzer   | [Benutzer1______]              |
+------------+--------------------------------+
| Rechte     | [ ] Recht A                    |
|            | [ ] Recht B                    |
|            | [ ] Recht C                    |
|            | [ ] Recht D                    |
|            | [ ] Recht E                    |
|            | [ ] Recht F                    |
|            | [ ] Recht G                    |
+------------+--------------------------------+

- $addurl ist die URL des Scripts, das bei einem POST-Request process_acl_add_form aufrufen wird (su.)
 - $backurl ist die URL des Scripts, das wieder display_acl_form aufrufen wird
 - $rights_array sind wieder alle Rechte

process_acl_add_form ($rights_array)
  => verarbeitet das Hinzufügen-Formular

Bei den Formularen sind jeweils immer noch Links zum Springen zum anderen Formular gegeben, daher die einen URL-Parameter, die anderen URL-Parameter sind für den Wert des action-Attributs des Formulars zuständig.

Wie oben erwähnt kommt hier noch ein Teilsourcecodeauszug aus list_rights; diese Struktur ist enorm hilfreich, wenn man dieses Tabellenformular anzeigen will: Man geht erst alle Zeilen durch; geht dann die Liste mit allen Rechten durch und prüft einfach mit in_array, ob das Recht auch für diese Zeile vorhanden ist.

Beachte, dass die Sortierung in der Datenbank richtig abgestimmt sein muss, sonst funktioniert es nicht.

$rows = array ();

$cur_row = null;
$cur_rights = null;

while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  // if its the first time
  if ($cur_row === null) {
    $cur_row = array ('id' => $row['id'], 'id_type' => $row['id_type']);
    $cur_rights = array ($row['right_name']);
  // else if it has changed
  } else if ($cur_row['id'] != $row['id'] || $cur_row['id_type'] != $row['id_type']) {
    $cur_row['rights'] = $cur_rights;
    $rows[] = $cur_row;
    $cur_row = array ('id' => $row['id'], 'id_type' => $row['id_type']);
    $cur_rights = array ($row['right_name']);
  } else {
    $cur_rights[] = $row['right_name'];
  }
}

$cur_row['rights'] = $cur_rights;
$rows[] = $cur_row;

Ich hoffe, das hat Dir ein bisschen einen Denkansatz gegeben. :-)

Ach ja: Eventuell erscheinen einige Funktionen oder Parameter überflüssig - das liegt an der Vereinfachung. Das ganze ist nämlich bei mir noch etwas komplexer.

Viele Grüße,
Christian

--
Hast Du einen Beitrag? Nur her damit!
http://aktuell.de.selfhtml.org/tippstricks/beitrag.htm
SELF-Code: (http://emmanuel.dammerer.at/selfcode.html)
sh:) fo:) ch:] rl:( br:> n4:& ie:% mo:) va:) de:] zu:) fl:( js:| ss:) ls:[