AnnaA: Ideen zu Rechtesystem in PHP

Hallo,

ich bin dabei ein Rechtesystem aufzubauen. Es wird auf Gruppen basieren denen verschiedene Rechte zugeordnet werden.
Leider sind es schon jetzt im ersten Schritt bestimmt 50 einzelne Rechte die gesetzt werden müssen...

Jetzt bin ich am überlegen, wie ich das am besten aufbaue, da mir eine Gruppentabelle nach dem Schema:

id | gruppenname | recht1 | recht2 | ... | recht50

nicht besonders gut gefällt wollte ich einmal nachfragen, ob jemand eine bessere Idee hat. Die Rechte schließen sich teilweise gegenseitig aus.

Ich hatte mit der Überlegung gespielt die Rechte zu gruppieren, also nicht 5 einzelne Spalten in der Gruppentabelle:

projekte_sehen | projekte_alle_sehen | projekte_anlegen | projekte_editieren | projekte_löschen...

Sondern dies evtl. zusammenzufügen zu einer Spalte Projekte und hier einen longint zu setzen in dem ich jeweils bits setze für die einzelnen Rechte.... bin mir aber nicht ganz sicher wie das in PHP geht und wie sicher es ist.

naja, wie auch immer... habt ihr eine evtl. noch bessere Idee???

Vielen Dank im voraus,
Eure Anna

  1. Hallo Anna,

    naja, wie auch immer... habt ihr eine evtl. noch bessere Idee???

    Hilft Dir das hier: </archiv/2003/4/43248/#m236669> weiter?

    Viele Grüße,
    Christian

    --
    Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
    1. Hi Christian!

      Hilft Dir das hier: </archiv/2003/4/43248/#m236669> weiter?

      Sorry das ich damals nicht geantwortet habe, bin leider nicht mehr zu gekommen. Bei mir ist es ja so dass ich im Prinzip 2 Gruppensysteme habe. Einmal den Usertyp, z.B. Admin, Gast... und die 2. Gruppe sind Unternehmensinterne Abteilungen, z.B. Controlling..., in der Gruppe "Controlling" kann es sowohl Admins als auch Gäste geben.

      Ich denke ich mache das jetzt so:

      Tabelle User
      User-ID....

      Tabelle Gruppen
      GID   User-ID

      Tabelle Typen
      Typ-ID   User-ID

      Tabelle Rechte
      Typ-ID   Ort-ID  Rechte(0=nix,1=lesend,2=schreibend,3=lesend+schriebend)

      Dann frage ich dann halt solche Dinge ab:

      SELECT *
        FROM table
        LEFT JOIN Typen
          ON Ort-ID = Ort-ID
        WHERE (Typen.Rechte = 1 OR Typen.Rechte = 3)
          AND table.GID = $rechte->GID

      $GID ermittele ich immer vorher, und speichere es in einer Klasse  $rechte

      Bei Inserts und Updates müsste ich dann halt vorher abfragen wie die Rechte aussehen.

      Was hälst Du davon? Irgendwie kommt mir das nicht so ganz rund vor, ich weiß nicht so Recht ob ich nicht allgemein Rechte vorher abfragen soll oder während dessen über einen JOIN?! Wie gesagt, Typ-ID, GID und User-ID habe ich zu diesesm Zeitpunkt bereits in der Klasse.

      Grüße
      Andreas

      1. Hi nochmal!

        Nur so nebenbei, was ganz anderes:

        Du erinnerst Dich an diese Rewrite-Geschichte die wir irgendwann im Forum überlegt hatten, und die dann viel einfacher ging, oder?

        Sowas in der Art:

        RewriteRule ^(.*)$            /index.php?url=$1    [L,QSA]

        ich weiß nicht ob Du es schon benutzt, oder ob das überhaupt zu empfehlen ist, aber in den Umgebungsvariablen

        $_SERVER["REQUEST_URI"]
        $_SERVER["SCRIPT_URL"]
        $_SERVER["REDIRECT_URL"]

        Steht genau dieser Wert den ich/wir damals als Parameter übergeben haben. Also muss das auch nicht mehr sein, dann läuft man auch nicht Gefahr mal aus Versehen diesen Parameter woanders zu verwenden!

        Nur welchen sollte man nehmen? Eigentlich egal, oder? Ich finde eigentlich REQUEST_URI am besten, da das em ehesten das aussagt was ich woher der Wert kommt, aber REDIRECT_URL ist auch nicht schlecht... naja. Oder gibt es da irgendwelche Argumente die für eine  der Lösungen spricht?

        Grüße
        Andreas

        1. Hallo Andreas,

          Du erinnerst Dich an diese Rewrite-Geschichte die wir irgendwann im Forum überlegt hatten, und die dann viel einfacher ging, oder?
          RewriteRule ^(.*)$            /index.php?url=$1    [L,QSA]

          Ja.

          ich weiß nicht ob Du es schon benutzt,

          Tue ich. Funktioniert wunderbar. :-)

          oder ob das überhaupt zu empfehlen ist,

          Warum sollte es das nicht sein?

          aber in den Umgebungsvariablen

          $_SERVER["REQUEST_URI"]
          $_SERVER["SCRIPT_URL"]
          $_SERVER["REDIRECT_URL"]

          Steht genau dieser Wert den ich/wir damals als Parameter übergeben haben.

          Ich verstehe nicht, was für einen Wert Du meinst... Klar, in REQUEST_URI steht /search?q=hallo - aber das ist ja wieder umständlich, da muss man dass rausfischen (hatte ich ja eine Funktion geschrieben) ist doch viel schneller, sicherer und komfortabler, das von PHP gleich in $_GET stehen zu haben - und genau das ist mit QSA möglich.

          Also muss das auch nicht mehr sein, dann läuft man auch nicht Gefahr mal aus Versehen diesen Parameter woanders zu verwenden!

          Ich verstehe nicht ganz... Was für ein Parameter? Wo woanders?

          Viele Grüße,
          Christian

          --
          Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
          1. Hi!

            Ich verstehe nicht ganz... Was für ein Parameter? Wo woanders?

            Ich habe das schon verstanden mit $_GET, ich zumindest muss aber noch den originalen REQUEST-String auseinanderpflücken um zu wissen was denn jetzt mit dem Request passieren soll. Ich habe z.B. so einen Request:

            www.server.de/language/module/command

            der wird auf script.php geleitet, wie oben beschreiben, und an diesen obigen String komme ich nicht nur über die Rewrite-Rule, sondern auch diret in PHP, halt durch obige Variablen.

            Grüße
            Andreas

            1. Hallo Andreas,

              der wird auf script.php geleitet, wie oben beschreiben, und an diesen obigen String komme ich nicht nur über die Rewrite-Rule, sondern auch diret in PHP, halt durch obige Variablen.

              Ach so meinst Du das. Klar. Wenn Du Dich immer im Top-Level-Verzeichnis der Domain befindest, ist das natürlich kein Thema. (In dem Fall empfehle ich Dir übrigens REQUEST_URI) Allerdings soll meine eigene Software auch über http://domain.example/test/bla/blub funktionieren, wenn die index.php in /test/ liegt. Und da ist es praktisch, wenn man dazu ausschließlich die .htaccess bearbeiten muss und nicht noch PHP-Scripte.

              Viele Grüße,
              Christian

              --
              Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
              1. Hi!

                Ach so meinst Du das. Klar. Wenn Du Dich immer im Top-Level-Verzeichnis der Domain befindest, ist das natürlich kein Thema. (In dem Fall empfehle ich Dir übrigens REQUEST_URI) Allerdings soll meine eigene Software auch über http://domain.example/test/bla/blub funktionieren, wenn die index.php in /test/ liegt. Und da ist es praktisch, wenn man dazu ausschließlich die .htaccess bearbeiten muss und nicht noch PHP-Scripte.

                Hm, ist zwar zur Zeit bei mir nicht geplant, aber was nicht ist kann kann ja noch werden, muss ich mal ein bisschen drüber nachdenken, aber ich denke Du hast Recht, ich muss mir nur einen besseren Parameter als "url" ausdenken ;-)

                Grüße
                Andreas

      2. Hallo Andreas,

        Tabelle User
        User-ID....

        Tabelle Gruppen
        GID   User-ID

        Tabelle Typen
        Typ-ID   User-ID

        Tabelle Rechte
        Typ-ID   Ort-ID  Rechte(0=nix,1=lesend,2=schreibend,3=lesend+schriebend)

        SELECT *
          FROM table
          LEFT JOIN Typen
            ON Ort-ID = Ort-ID
          WHERE (Typen.Rechte = 1 OR Typen.Rechte = 3)
            AND table.GID = $rechte->GID

        Sorry für das Fullquote - aber der SELECT passt absolut gar nicht zur Datenstruktur. Es gibt keine Tabelle table und die Tabelle Typen hat keine Spalte Rechte.

        Was hälst Du davon?

        Naja, ich blicke da irgendwie nicht so recht durch, wie Du das jetzt realisieren willst... daher kann ich auch noch nichts dazu sagen...

        Viele Grüße,
        Christian

        Sie haben mehr als 25% zitierte Zeilen in Ihrem Posting. Sind Sie sicher, dass Sie das Posting so abschicken wollen?

        Ja.

        --
        Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
        1. Hi Christian!

          Tabelle User
          User-ID....

          Tabelle Gruppen
          GID   User-ID

          Tabelle Typen
          Typ-ID   User-ID

          Tabelle Rechte
          Typ-ID   Ort-ID  Rechte(0=nix,1=lesend,2=schreibend,3=lesend+schriebend)

          SELECT *
            FROM table
            LEFT JOIN Typen
              ON Ort-ID = Ort-ID
            WHERE (Typen.Rechte = 1 OR Typen.Rechte = 3)
              AND table.GID = $rechte->GID

          Sorry für das Fullquote - aber der SELECT passt absolut gar nicht zur Datenstruktur. Es gibt keine Tabelle table und die Tabelle Typen hat keine Spalte Rechte.

          Ja das das nicht passt habe ich irgendwie selbst gemerkt ;-)

          table steht für irgendeine Tabelle, in der ich ich eine Aktion durchführe(lesende Abfrage) die über die Tabelle mit den Festlegungen für die verschiedenen Rechte-Typen joint und darüber klärt ob eben dieser Typ von Aktionen dort dem aktuellen User gestattet ist. Aber das ist totaler Murks.

          Ich glaube diese Logik kann ich nicht über einen JOIN direkt abfragen. Ich frage lieber vorher per SELECT ab ob diese Aktion für diesen User-Tyü erlaubt ist, und wenn das OK ist führe ich die Abfrage durch-. Was mich daran stört ist dass ich diese Prüfung dann wieder"hard-coded" überall in der Anwendung stehen habe. Aber vielleicht überlege ich mir auch dazu eine Klasse oder eine Funktion.

          Auf alle Fälle brauche ich dann vor jeder Abfrage auf so eine Tabelle wo es um Rechte geht sowas:

          if(user_has_right("bla","Typ-ID")) {
            mysql_Query...
          }
          else {
            raise_error("abc")...
          }

          Aber leider ist das ja noch nicht alles, ich muss ja nicht nur prüfen ob der User-Typ dZugriff hat, sondern ob der User auch in der Richtigen Gruppe ist um Zugriff zu bekommen, wobei ich das dann doch besser in dei Abfrage integriere.

          Sorry, leider weiß ich  hier im Augenblick nicht so wirklich weiter, irgendwie ist das halt nicht wirklich rund was ich mir hier überlege.

          Ich hoffe jetzt verstehst Du es besser. BEdenke das ich 2 verschiedene Ebenen habe, einmal user-typ(Admin...) und einem User-Gruppe (Apteilung1,2,3...), in jeder Gruppe soll jeder nur auf die Daten dieser Gruppe zugreifen können, aber in der Gruppe gibt es Admins, Gäste die verschiedend weitreichende Rchte haben(schreibend, oder nur lesend...)

          Grüße
          Andreas

          1. Hallo Andreas,

            Ich hoffe jetzt verstehst Du es besser. BEdenke das ich 2 verschiedene Ebenen habe, einmal user-typ(Admin...) und einem User-Gruppe (Apteilung1,2,3...), in jeder Gruppe soll jeder nur auf die Daten dieser Gruppe zugreifen können, aber in der Gruppe gibt es Admins, Gäste die verschiedend weitreichende Rchte haben(schreibend, oder nur lesend...)

            Ich vergesse einfach mal Dein Datenmodell und entwerfe mein eigenes dazu:

            Für den Fall Benutzer:Gruppen m:n, Benutzer:Typen n:1:

            Tabelle Gruppen
            ---------------
            GruppenID
            GruppenName

            Tabelle Typen
            ---------------
            TypID
            TypName

            Tabelle Benutzer
            ----------------
            BenutzerID
            ...
            TypID

            Tabelle Benutzer_Gruppen
            ------------------------
            BenutzerID
            GruppenID
            ...

            Tabelle Rechte (SonstigeID kann z.B. die ID eines Menüeintrages sein)
            --------------
            GruppenID
            TypID
            SonstigeID
            RechtName
            ...

            Listet alle Rechte dieses Benutzers:

            SELECT
              Rechte.RechtName as RechtName
            FROM
              Rechte,
              Benutzer_Gruppen,
              Benutzer
            WHERE
              Rechte.GruppenID = Benutzer_Gruppen.GruppenID
            AND
              Rechte.TypID = Benutzer.TypID
            AND
              Benutzer_Gruppen.BenutzerID = Benutzer.BenutzerID
            AND
              Benutzer.BenutzerID = $user_id
            AND
              Rechte.SonstigeID = $sonstige_id;

            Für den Fall Benutzer:Gruppen n:1, Benutzer:Typen n:1:

            Tabelle Gruppen
            ---------------
            GruppenID
            GruppenName
            ...

            Tabelle Typen
            ---------------
            TypID
            TypName
            ...

            Tabelle Benutzer
            ----------------
            BenutzerID
            ...
            TypID
            GruppenID

            Tabelle Rechte
            --------------
            GruppenID
            TypID
            SonstigeID
            RechtName

            Listet alle Rechte dieses Benutzers:

            SELECT
              Rechte.RechtName as RechtName
            FROM
              Rechte,
              Benutzer
            WHERE
              Rechte.GruppenID = Benutzer.GruppenID
            AND
              Rechte.TypID = Benutzer.TypID
            AND
              Benutzer.BenutzerID = $user_id
            AND
              Rechte.SonstigeID = $sonstige_id;

            RechtName kann dann z.b. "Lesen", "Schreiben", etc. sein, je nachdem, was Du halt brauchst.

            Viele Grüße,
            Christian

            --
            Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
            1. Hi Christian!

              Danke Dir! Aber wie setzt Du das jetzt in der Praxis um(sorry für meine kleinen Verständnisschwierigkeiten im Augenblick aber irgendwie ist da zur Zeit der Wurm drin...), also wenn Du jetzt halt z.B. prüfen mußt ob dem aktuellen Benutzer das Eintragen eines Datensatzes wie er vorhat erlaubt ist?

              Würdest Du dann so eine SELECT-Abfrage wie Du oben beschrieben hast starten(halt JOIN über 3 Tabellen) und so das Recht ermitteln? Also mal ein Beispiel, der Benutzer schickt Daten um eine neuen Kunden anzulegen - ich weiß aber erstmal nicht ob er das überhaupt darf. Wenn er es darf sollen diese Daten(Vorname, Nachname...) per INSERT in die Tabelle "kunden" geschrieben werden. Dann habe ich mir also vorher für genau diese Aktionen einen Datensatz in der Tabelle "Rechte" angelegt, also übergebe ich der SELECT-Abfrage an die Rechte-Tabelle(Deine von oben) die ID dieses Datemnsatzes aus der Rechte-Tabelle, was heißt dass ich diese ID definitiv da hinschreiben muss, und prüfe was bei der Abfrage rauskommt, wenn da was positives rauskommt dann mache ich mein Insert, sonst nicht. Habe ich das so etwas korrekt wiedergegen?

              Ich würde mir also eine Funktion überlegen:

              Boolean check_right(string RechtName, int user_id, int sonstige_id)

              Diese Funktion liefert mir also TRUE zurück wenn der User das Recht hat, und false wenn nicht, dann sieht das ganze etwa so aus:

              if(check_right("schreiben", 123, 4567)) {
                process_query("INSERT...");
              }
              else {
                raise_error("Berechtigungsfehler", "Zugriff nicht eraubt");
              }

              So würde das also im Quelltext aussehen und die Funktionn oben besteht also weitgehend aus der von Dir beschriebenen Query.

              Ich glaube jetzt habe ichs langsam, oder? Jedesmal wenn ich also an eine Situation komme wo ich die Aktionen nur bestimmten Usern vorenthalten will muss ich eben in die Rechte-Tabelle einen neuen Eintrag schreiben und wie oben beschrieben vorher auf das Recht prüfen.

              Danke nochmal!

              Viele Grüße
              Andreas

              1. Hallo Andreas,

                Ich glaube jetzt habe ichs langsam, oder?

                Ja. :-)

                Jedesmal wenn ich also an eine Situation komme wo ich die Aktionen nur bestimmten Usern vorenthalten will muss ich eben in die Rechte-Tabelle einen neuen Eintrag schreiben und wie oben beschrieben vorher auf das Recht prüfen.

                Genau. Das wäre _eine_ Möglichkeit, das ganze zu realisieren.

                Viele Grüße,
                Christian

                --
                Ich bin ein Bandbreitenverschwender. Meine Signatur tut mir leid. Ehrlich!
                1. Hi Christian!

                  Ich glaube jetzt habe ichs langsam, oder?

                  Ja. :-)

                  Danke Dir, hast mir sehr geholfen!

                  Grüße
                  Andreas

  2. Moin Moin !

    Leider sind es schon jetzt im ersten Schritt bestimmt 50 einzelne Rechte die gesetzt werden müssen...

    Nimm einen String, in dem jede Position ein Recht representiert, 0 schaltet das Recht aus, 1 schaltet es an. (Bis 32 Rechte hätte ich dafür einen Integer genommen, aber bei Dir scheint es ja beliebig wachsen zu wollen).

    "000" -- kann nix
    "001" -- kann lesen
    "010" -- kann schreiben
    "100" -- kann sprechen
    "111" -- kann alles
    "110" -- stumm ;-)

    Die Rechte schließen sich teilweise gegenseitig aus.

    Was passiert, wenn jemand in zwei Gruppen ist, deren Rechte sich widersprechen?

    Vergib Namen für die Rechte, und sei es auch nur zum Designen. Beschreibe die Rechte so, daß sie ausdrücken, was der User *KANN*, wenn er das Recht hat. In meinem Projekt gibt es z.B. folgende Rechte:

    can login
    can change own password
    can edit Users
    can edit groups
    can edit newsticker

    Sondern dies evtl. zusammenzufügen zu einer Spalte Projekte und hier einen longint

    64 Bit. 50 Rechte hast Du schon. Das wird knapp.

    Wie wäre es mit einem 32-Bit-Integer pro Rechtegruppe; und je einem Bit pro Recht?

    Alexander

    --
    Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
    Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
    1. Arg!

      "000" -- kann nix
      "001" -- kann lesen
      "010" -- kann schreiben
      "100" -- kann sprechen
      "111" -- kann alles
      "110" -- stumm ;-)

      Das sollte natürlich "011" sein.

      Alexander

      --
      Nein, ich beantworte keine Fragen per eMail. Dafür ist das Forum da.
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so!"
  3. Moin!

    Jetzt bin ich am überlegen, wie ich das am besten aufbaue, da mir eine Gruppentabelle nach dem Schema:

    id | gruppenname | recht1 | recht2 | ... | recht50

    nicht besonders gut gefällt wollte ich einmal nachfragen, ob jemand eine bessere Idee hat. Die Rechte schließen sich teilweise gegenseitig aus.

    Das mit dem gegenseitigen Ausschließen klingt irgendwie nicht so gut. Was wäre das denn zum Beispiel für eine Konstellation.

    Überhaupt: 50 einzelne Rechte sieht mir irgendwie danach aus, dass deine Umgebung diverse Einzelmanipulationen erlaubt oder verweigern soll. Da du leider nicht geschrieben hast, was das genau ist, kann ich nur meinen (möglicherweise die Lage vollkommen verkennenden) Tipp geben, die Dinge nach Möglichkeit zu gruppieren.

    Also konkret: Ein einzelner User kann, genau wie bei den Dateirechten auch, gewisse elementare Dinge tun: Lesen, Schreiben, Ausführen. Naja, Ausführen macht bei dir vielleicht nicht unbedingt Sinn, aber Lesen und Schreiben durchaus. Also kann er keins, eines oder beides an einer bestimmten Position machen. Das würde die Rechte insgesamt reduzieren von "darf_lesen_hier: ja/nein" und "darf_schreiben_hier: ja/nein" auf "darf_hier: lesen/schreiben".

    Dann kann man die Zugriffe auch über eine weitere Gruppe einschränken. Damit ein User an einer Position etwas darf, muß er einer bestimmten Gruppe angehören. Nun kann er natürlich mehreren Gruppen angehören - das sollte dann aber nicht in mehreren Spalten (bzw. eigentlich in sovielen Spalten, wie es Gruppen bzw. Orte gibt) abgebildet werden, sondern sich in der Tabelle als mehrere Datensätze widerspiegeln. Genauer betrachtet: Vergiß den Begriff "Gruppe" für dieses Konstrukt, mach pro Ort, an dem der User bzw. seine Gruppe mehr als "nichts"-Rechte besitzt, einen Datenbankeintrag in so einer Tabelle:
    GID   Ort-ID   Recht

    Da zu erwarten ist, dass noch mehr Orte hinzukommen, ist diese Tabelle erheblich flexibler. Abgefragt wird dann durch passende Joins auf die verbundenen Tabellen (also z.B. über die GID und die Ort-ID). Und da nicht zu erwarten ist, dass eine solche Abfrage bei der Klärung, ob ein User aktuell etwas darf oder nicht, mehr als eine UID/GID und Ort-ID hat, dürften die zu bewegenden Datenmengen ziemlich klein sein - maximal eine Ergebniszeile, wenn ein Recht gegeben ist, sonst keine Zeile. Mit passenden Indexen auf den relevanten ID-Spalten sollte das kein Thema sein.

    Sondern dies evtl. zusammenzufügen zu einer Spalte Projekte und hier einen longint zu setzen in dem ich jeweils bits setze für die einzelnen Rechte.... bin mir aber nicht ganz sicher wie das in PHP geht und wie sicher es ist.

    Ein Longint ist längenmäßig begrenzt. Das kann zu einem Problem werden. Außerdem ist er zwar schnell gelesen, und die Auswertung der gesetzten Rechte ist durch Bitmasken auch ganz simpel, aber eben nicht offensichtlich, weshalb es da durchaus zu Programmierfehlern kommen kann. Ganz grundsätzlich jedoch beeinflußt die Art der Datenspeicherung die Sicherheit nicht - es ist vollkommen egal, ob ein Bit als Bestandteil eines Longint oder eines Strings oder eines Bool-DB-Feldes gespeichert ist.

    - Sven Rautenberg

    --
    Signatur oder nicht Signatur - das ist hier die Frage!
    1. Hallo,

      danke schon mal für Eure netten Antworten.

      Vielleicht erkläre ich doch nochmals genauer, wie sich die Rechte so zusammensetzen und warum sie sich evtl. gegenseitig ausschließen können.

      Grundsätzlich gilt: Man kann nur einer Gruppe angehören.

      Die grundsätzlichen Rechte sind:

      • beschränkt sehen
      • alles sehen
      • anlegen
      • editieren
      • löschen

      Ausschließen würden sich hier logischer Weise beschränkt sehen und alles sehen, da sie gegenläufig sind. Darum hatte ich auch überlegt, ob man diese beiden Rechte evtl. zusammenfassen sollte.

      Im wesentlichen sind es eigentlich immer diese Rechte die sich in dieser Art verschiedenen Bereichen zuordnen lassen.

      Diese Bereiche wären zum Beispiel:

      • Externe_Projekte
      • Interne_Projekte
      • Kundenkontakte
      • Lieferantenkontakte
      • News
      • Kalender
      • ...

      Letztendlich werde ich wohl dann gruppieren nach den genannten Bereichen. Pro Bereich wird es nicht mehr als 10-15 verschiedene Rechtearten geben, daher macht es vielleicht Sinn pro Bereich einen LongInt zu verwenden und dann mit Bits zu arbeiten??

      Könntet ihr mir evtl. noch einen Tipp geben, wie ich ein Bit in einem Int auf true setzen kann?

      Viele Grüße,
      Anna

      1. Moin!

        Vielleicht erkläre ich doch nochmals genauer, wie sich die Rechte so zusammensetzen und warum sie sich evtl. gegenseitig ausschließen können.

        Das ist hilfreich. :)

        Grundsätzlich gilt: Man kann nur einer Gruppe angehören.

        Eine wichtige Information. Bei Unix kann man als User z.B. mehreren Gruppen angehören. Sowas würde deinen Fall aber komplizierter machen.

        Die grundsätzlichen Rechte sind:

        • beschränkt sehen
        • alles sehen
        • anlegen
        • editieren
        • löschen

        Ausschließen würden sich hier logischer Weise beschränkt sehen und alles sehen, da sie gegenläufig sind. Darum hatte ich auch überlegt, ob man diese beiden Rechte evtl. zusammenfassen sollte.

        Was ist da der Unterschied genau? Eigentlich ist "alles sehen" doch eine Erweiterung von "beschränkt sehen". Also könnte man das Recht "sehen" auf 0 (nichts sehen), 1 (beschränkt sehen) oder 2 (alles sehen) setzen. Meinetwegen auch binär auf 00 (nix), 01 (beschränkt) und 10 oder 11 (alles). Wenn man alles sehen darf, darf man auch beschränkt sehen, dieses eingeschränkte Recht ist in diesem Fall also irrelevant.

        Im wesentlichen sind es eigentlich immer diese Rechte die sich in dieser Art verschiedenen Bereichen zuordnen lassen.

        Diese Bereiche wären zum Beispiel:

        • Externe_Projekte
        • Interne_Projekte
        • Kundenkontakte
        • Lieferantenkontakte
        • News
        • Kalender
        • ...

        Wenn es nicht mehr Elementarrechte wie oben angegeben gibt (5 Stück - vielleicht fallen dir insgesamt auch 8 oder 16 ein), dann kann man die im Prinzip in einer Integer-Darstellung verwurschteln. Was im Zusammenhang mit MySQL aber wesentlich netter wäre, ist die Definition des Elementarrechte-Feldes als SET, also als Menge. Diese kann man IMHO besser behandeln, und 5, 8 oder auch 16 verschiedene Rechte sind für dieses Datenfeld kein Problem. SETs nehmen bis zu 64 verschiedene Mengenelemente auf.

        Und wie man der Doku entnehmen kann(http://www.mysql.de/doc/de/SET.html), arbeitet der Datentyp SET genau so, wie du es mit den Integer-Bits machen wolltest - nur etwas leichter menschenlesbar. Insbesondere die FIND_IN_SET-Funktion erscheint mir ganz nett, aber es ist auch grundsätzlich leichter lesbar, wenn du in der Rechte-Spalte nach 'WHERE recht LIKE "%readall%"' suchst.

        Und diese Elementarrechte verknüpfst du mit jedem existierenden Bereich und jeder existierenden Gruppe so, wie ich schon vorgeschlagen hatte:

        GID  Ort-ID  Rechte

        Letztendlich werde ich wohl dann gruppieren nach den genannten Bereichen. Pro Bereich wird es nicht mehr als 10-15 verschiedene Rechtearten geben, daher macht es vielleicht Sinn pro Bereich einen LongInt zu verwenden und dann mit Bits zu arbeiten??

        Wie gesagt: SET kann bis zu 64 verschiedene Elemente aufnehmen und verwaltet sie im Klartext. Das ist ein ganz kleinwenig mehr Overhead in der Datenbank (die schlauerweise wohl sofort in Binärdarstellung umrechnen wird), aber enorm erleichternd für die Programmierung.

        - Sven Rautenberg

        --
        Signatur oder nicht Signatur - das ist hier die Frage!
        1. Hallo Sven,

          danke für die klasse Antworten!
          Das klingt doch alles sehr vielversprechend.
          Eine Frage hätte ich noch:
          Könnte man in eine mySQL DB in einen blob ein Array schreiben?
          Das würde ja auch sehr gut meine Sache erfüllen. Ansonsten klingt das SET auch ganz gut.

          Viele Grüße,
          Anna

          1. Moin!

            Könnte man in eine mySQL DB in einen blob ein Array schreiben?
            Das würde ja auch sehr gut meine Sache erfüllen. Ansonsten klingt das SET auch ganz gut.

            In einen BLOB kannst du grundsätzlich alles schreiben, zu dem PHP in der Lage ist. Aber ein BLOB ist für ein PHP-Array eigentlich gar nicht notwendig, ein Textfeld reicht schon. Da schreibst du mit serialize() das Array rein und holst es mit unserialize() wieder heraus. Ist zugegeben auch eine gute Methode, komplexe Daten zu speichern. Allerdings verbaust du dir damit die Möglichkeit, innerhalb von Datenbankabfragen auf die Rechte zuzugreifen, sondern du mußt eigentlich immer alle in Frage kommenden Datensätze auslesen und mit PHP untersuchen. Fragestellungen wie "Zeig mir alle Gruppen, die im Bereich XYZ Leserechte haben" lassen sich damit dann nicht mehr beantworten.

            SET ist für sowas besser. Und platzsparender obendrein.

            - Sven Rautenberg

            --
            Signatur oder nicht Signatur - das ist hier die Frage!
            1. Hallo Sven,

              danke nochmals für die nützlichen Tipps. Die SETs sind klasse und genau das was ich suchte...

              Frohe Ostern noch,
              Anna