Hallo Rolf,
Duplikate dürften eigentlich nicht vorkommen, da entweder das Feld id_user, oder das Feld id_group eines Datensatzes belegt sein darf. Darum weiß ich auch nicht, ob das Design nicht noch eine Macke hat.
Das meine ich nicht. Es könnte zum Beispiel sein, dass ein User das Recht "read" im Modul "bar" des projekts "foo" hat. Darüber hinaus ist er in der Gruppe "snafu", die dieses Recht ebenfalls hat. Und dann noch in der Gruppe "hurz", die das AUCH darf. Sag mir nicht, dass das nicht vorkommt. Bei 300.000 Usern hast Du eine Menge Gruppen und dann wirst Du schneller Huddel in den Rechten haben als Du "Administratorensorgfalt" buchstabieren kannst.
Die automatische Doublettenbeseitigung durch SELECT DISTINCT oder UNION sorgt dafür, dass diese Mehrfachnennung des gleichen Rechts in deinem Rechtecontroller nicht sichtbar wird.
Deine Design-Bedenken sind natürlich berechtigt. Rein formal handelt es sich hier um drei Entitäten: User, Group und Recht, und zwischen allen dreien besteht je eine m:n Beziehung.
- Ein User kann in m Gruppen sein / Eine Gruppe kann n User enthalten
- Ein User kann m Rechte haben / Ein Recht kann n Usern erteilt werden
- Eine Gruppe kann m Rechte haben / Ein Recht kann n Gruppen erteilt werden
Ach so, und dann gibt's da noch diese neckische kleine 1:n Abhängigkeit:
- Ein Recht kann n andere Rechte implizieren
D.h. für ein KONZEPTIONELLES Modell hast Du 3 Entitäten "K_User", "K_Group" und "K_Right" und vier Beziehungen dazwischen. Die rekursive Rechtebeziehung ist aber, wenn ich das richtig verstehe, sehr eng definiert und du willst sie als Programmcode abbilden. Wenn Du das übrige konzeptionelle Modell 1:1 in die DB überträgst, entstehen demnach 6 Tabellen. "K_User", "K_Group", "K_Right", "K_UserGroup", "K_UserRight", "K_GroupRight".
Kann man so bauen. Tun auch viele. Und riskieren, bei einer großen DB in die Knie zu gehen.
Man kann durchaus ein technisches Modell designen, das weniger Tabellen nutzt und bewusst Redundanzen in Kauf nimmt, um in den häufigen Operationen performanter zu sein. Das ist bei deiner "rights" Tabelle der Fall. Sie integriert "K_Right", "K_UserRight" und "K_GroupRight" und erlaubt das Lesen von Rechten ohne Joins. Aber wenn Du ein Projekt umbenennst, änderst Du sehr viele Zeilen. Was aber nur selten vorkommt. Deswegen würde ich sagen: Ist ok, mach das so. Aber sei Dir bewusst, dass das eine technische Optimierung ist, für die Du Nachteile in Kauf nimmst.
Deine "groups" Tabelle entspricht der K_UserGroup. Eine Zusammenfassung von K_Group und K_UserGroup würde ich nicht in Betracht ziehen. Für die Gruppenverwaltung brauchst Du mit Sicherheit sowas wie einen Gruppennamen und den würde ich nicht redundant durch die groups-Tabelle streuen. Eventuell kommt ja noch was hinzu wie ein Anlegedatum oder weitere Informationen. Deswegen: Benenne die id-Spalte in groups um in "id_group" und mach eine eigene Gruppentabelle.
Dann müsstest Du ggf. noch überlegen, ob Du in "rights" mit Gültigkeitsintervallen arbeitest. Vielleicht willst Du Rechte nur zeitweilig einräumen. Ein Ablaufdatum in "rights" verhindert, dass der Admin vergisst, ein Recht zu entfernen.
Danke für die wertvollen Anregungen. Werde ich doch gleich zu meinen Unterlagen nehmen.
BTW: vielen Dank an denjenigen, der die Druckfunktion (CSS) des Forums so schön gemacht hat. Gefällt mir Daumen hoch :-)
Grüße
TS