Moin,
ich plane gerade eine Eierlegende-Woll-Milch-Sau zu erschaffen. Prinzipiell ist die Sprache erstmal egal (ich werde es aber später dann (hoffentlich) in Ruby on Rails umsetzen).
Ganz grob geht es um Folgendes: Ich habe ein System mit vielen Usern, ein User kann einer oder mehreren Gruppen angehören und jede Gruppe hat bestimmte Rechte. Das Ganze soll vollkommen dynamisch sein, d.h. alles wird in einer Datenbank abgelegt und muss zur Laufzeit manipulierbar sein. Außerdem muss es auf dem MVC-Pattern aufbauen und somit natürlich objektorientiert geschrieben sein.
Also fangen wir mit einem kleinen Beispiel an:
Die Datenbank sieht in etwa so aus:
Jetzt lässt sich einfach festlegen, welche Gruppe auf welche Methoden der jeweiligen Klasse zugreifen darf. Die Methoden beinhalten zum einen natürlich die Logik, aber der Einfachheit halber auch gleich das nötige Formular. Es wäre ja unsinnig, wenn ich einen Eintrag erstellen kann, aber das Formular nicht sehen darf oder andersrum
Nun soll jeder Eintrag noch eine Liste von Kommentaren erhalten:
Die neue Methode gibt einfach alle zugehörigen Kommentare zurück, jetzt könnte man z.B. in der Datenbank festlegen, dass nur eingeloggte Benutzer das dürfen. Die Klasse dazu sieht im Prinzip wieder genauso aus, wie die der Einträge:
In Rails könnte man die URLs so betrachten:
Jetzt kommt das erste Problem: Die Kommentare stellen eine Eigenständige Klasse dar, d.h. ich könnte das Leserecht für die Einträge verweigern, aber innerhalb der Kommentar-Klasse trotzdem lesen. Das Problem lässt sich relativ einfach lösen: Um an die Kommentare zu gelangen MUSS man über die Einträge gehen, dabei wird in der Eintragsklasse die Methode getKommentare aufgerufen. Also sperrt man auch diese Methode über die Datenbank.
Soweit ist alles kein Problem. Nun wird es tricky und ich habe noch keine hunderprozentige Idee, wie ich es umsetzen könnte...:
Angenommen wir haben ein paar User, die in der Gruppe der Moderatoren sind. Die Moderatoren sind die einzigen, die Einträge verfassen, editieren und löschen dürfen. Jetzt kann Moderator1 einen Eintrag verfassen und Moderator2 kann diesen editieren oder löschen.
Also die Frage lautet: Wie bau ich in das Datenbankschema ein, dass in einer bestimmten Klasse, eine bestimmte Gruppe nur das editieren und/oder löschen darf, was sie auch selbst erstellt hat?
Eine Idee, die mir nach langem Überlegen kam, war, dass man dafür eine neue Methode einführt, dann sähe die Klasse quasi so aus:
Innerhalb der Methode kann man dann prüfen, ob der aktuelle User auch der Eigentümer ist. Das hat dann aber mindestens 3 Nachteile:
1. Wenn (aus Leichtsinn) 'bearbeiten' und 'eigenenBearbeiten' in der Datenbank steht, dann darf jeder in der Gruppe immernoch überall reinschreiben. Ist natürlich nur eine Konfigurationsgeschichte und nicht wirklich schwerwiegend.
2. Für das User-Interface fragt man natürlich immer in der Datenbank ab, ob nun auch der Knopf zum 'Bearbeiten' oder 'Löschen' angezeigt werden soll. Da müsste man nun immer auf 2 Variablen prüfen.
3. Das System soll dynamisch werden. D.h. ich will nicht für jede potenzielle Klasse 2 solche Methoden einbauen. Das Ganze müsste/sollte sich auch irgendwie einfach über die Datenbank regeln lassen. Klar, die Einfachste Methode wäre hier noch ein Flag einzuführen:
Das wäre soweit natürlich kein Problem und es wird vermutlich recht häufig benutzt, also sollte das eine Byte da ganz gut aufgehoben sein. Aber vielleicht gibt's ja noch eine schönere Lösung?!
Jetzt gibt's allerdings noch ein richtiges Problem:
Angenommen, wir wollen unsere Einträge noch weiter gruppieren - nach Themen. Also erstellen wir eine neue Klasse:
Jedes Thema enthält nun also eine Reihe von Einträgen. Die URLs in Rails sähen grob so aus:
Nun will ich jedem Moderator einen oder mehrere Themenbereiche zuordnen können, in denen sie arbeiten dürfen. Alle anderen Themen sind nur lesbar (oder nicht mal das, soll ja frei konfigurierbar sein)...
Aber wie stell ich das an?
Wenn ich den Moderatoren nun Schreibrechte für Themen gebe, können sie in allen Themen alles tun was sie wollen.
Eine Möglichkeit wäre 4 Methoden in die Klasse zu setzen, eine die schaut ob der Moderator da lesen darf, dann noch eine für's Schreiben, eine fürs Editieren und eine für's Löschen. Das ist natürlich wieder hässlich.
Möglichkeit 2 wäre eine Art Bedingung mit in die DB zu setzen:
Die Datenbank könnte dann so aussehen:
Um die Moderatoren einem Thema zuzuweisen muss ja eh irgendwo eine Tabelle sein mit den Zuweisungen und genau die habe ich in der Bedingung mit 'moderators_for_thema' angesprochen. Aber so wirklich zufriedenstellend finde ich das Ganze nicht...
Hoffentlich macht sich jemand die Mühe und liest den ganzen Mist und kann mir helfen.
Grüße und Danke!
ich plane gerade eine Eierlegende-Woll-Milch-Sau zu erschaffen. Prinzipiell ist die Sprache erstmal egal (ich werde es aber später dann (hoffentlich) in Ruby on Rails umsetzen).
Ganz grob geht es um Folgendes: Ich habe ein System mit vielen Usern, ein User kann einer oder mehreren Gruppen angehören und jede Gruppe hat bestimmte Rechte. Das Ganze soll vollkommen dynamisch sein, d.h. alles wird in einer Datenbank abgelegt und muss zur Laufzeit manipulierbar sein. Außerdem muss es auf dem MVC-Pattern aufbauen und somit natürlich objektorientiert geschrieben sein.
Also fangen wir mit einem kleinen Beispiel an:
Code:
CLASS Eintrag {
METHODE neu { ... }
METHODE bearbeiten { ... }
METHODE löschen { ... }
METHODE anzeigen { ... }
}
Code:
USER: id
GRUPPE: id
BERECHTIGUNG: id, klasse, methode
### VERKNÜPFUNGS TABELLEN: ###
USER_GRUPPE: user_id, gruppe_id
GRUPPE_BERECHTIGUNG: gruppe_id, berechtigung_id
Nun soll jeder Eintrag noch eine Liste von Kommentaren erhalten:
Code:
CLASS Eintrag {
METHODE neu { ... }
METHODE bearbeiten { ... }
METHODE löschen { ... }
METHODE anzeigen { ... }
METHODE getKommentare { ... }
}
Code:
CLASS Kommentar {
METHODE neu { ... }
METHODE bearbeiten { ... }
METHODE löschen { ... }
METHODE anzeigen { ... }
}
Code:
/eintraege/new # Formular für neuen Eintrag erstellen
/eintraege/{id}/edit # Formular zum Editieren von Eintrag mit der id={id}
/eintraege/{id} # URL zum Löschen von Eintrag mit der id={id}
/eintraege/{id} # URL zum Anzeigen von Eintrag mit der id={id}
/eintraege # URL zum Anzeigen von allen Einträgen
### ZUGEHÖRIGE KOMMENTARE: ###
/eintraege/{id}/kommentare/new # Formular um neuen Kommentar zum Eintrag mit id={id} zu erstellen
/eintraege/{id1}/kommentare/{id2}/edit # Formular zum Editieren von Kommentar mit id={id2} zum Eintrag mit id={id1}
/eintraege/{id1}/kommentare/{id2} # URL zum Löschen von Kommentar mit id={id2} zum Eintrag mit id={id1}
/eintraege/{id}/kommentare # URL zum Anzeigen aller Kommentare zum Eintrag mit id={id}
Soweit ist alles kein Problem. Nun wird es tricky und ich habe noch keine hunderprozentige Idee, wie ich es umsetzen könnte...:
Angenommen wir haben ein paar User, die in der Gruppe der Moderatoren sind. Die Moderatoren sind die einzigen, die Einträge verfassen, editieren und löschen dürfen. Jetzt kann Moderator1 einen Eintrag verfassen und Moderator2 kann diesen editieren oder löschen.
Also die Frage lautet: Wie bau ich in das Datenbankschema ein, dass in einer bestimmten Klasse, eine bestimmte Gruppe nur das editieren und/oder löschen darf, was sie auch selbst erstellt hat?
Eine Idee, die mir nach langem Überlegen kam, war, dass man dafür eine neue Methode einführt, dann sähe die Klasse quasi so aus:
Code:
CLASS Eintrag {
METHODE neu { ... }
METHODE bearbeiten { ... }
METHODE löschen { ... }
METHODE anzeigen { ... }
METHODE getKommentare { ... }
METHODE eigenenBearbeiten { ... }
METHODE eigenenLöschen { ... }
}
1. Wenn (aus Leichtsinn) 'bearbeiten' und 'eigenenBearbeiten' in der Datenbank steht, dann darf jeder in der Gruppe immernoch überall reinschreiben. Ist natürlich nur eine Konfigurationsgeschichte und nicht wirklich schwerwiegend.
2. Für das User-Interface fragt man natürlich immer in der Datenbank ab, ob nun auch der Knopf zum 'Bearbeiten' oder 'Löschen' angezeigt werden soll. Da müsste man nun immer auf 2 Variablen prüfen.
3. Das System soll dynamisch werden. D.h. ich will nicht für jede potenzielle Klasse 2 solche Methoden einbauen. Das Ganze müsste/sollte sich auch irgendwie einfach über die Datenbank regeln lassen. Klar, die Einfachste Methode wäre hier noch ein Flag einzuführen:
Code:
USER: id
GRUPPE: id
BERECHTIGUNG: id, klasse, methode, nur_eigene
### VERKNÜPFUNGS TABELLEN: ###
USER_GRUPPE: user_id, gruppe_id
GRUPPE_BERECHTIGUNG: gruppe_id, berechtigung_id
Jetzt gibt's allerdings noch ein richtiges Problem:
Angenommen, wir wollen unsere Einträge noch weiter gruppieren - nach Themen. Also erstellen wir eine neue Klasse:
Code:
CLASS Thema {
METHODE neu { ... }
METHODE bearbeiten { ... }
METHODE löschen { ... }
METHODE anzeigen { ... }
METHODE getEinträge { ... }
}
Code:
# Alle Themen anzeigen:
/themen/
# Alle Einträge eines Themas anzeigen:
/themen/{thema_id}/eintraege/
# Alle Kommentare eines Eintrags eines Themas:
/themen/{thema_id}/eintraege/{eintrag_id}/kommentare/
Aber wie stell ich das an?
Wenn ich den Moderatoren nun Schreibrechte für Themen gebe, können sie in allen Themen alles tun was sie wollen.
Eine Möglichkeit wäre 4 Methoden in die Klasse zu setzen, eine die schaut ob der Moderator da lesen darf, dann noch eine für's Schreiben, eine fürs Editieren und eine für's Löschen. Das ist natürlich wieder hässlich.
Möglichkeit 2 wäre eine Art Bedingung mit in die DB zu setzen:
Code:
USER: id
GRUPPE: id
BERECHTIGUNG: id, klasse, methode, bedingung
### VERKNÜPFUNGS TABELLEN: ###
USER_GRUPPE: user_id, gruppe_id
GRUPPE_BERECHTIGUNG: gruppe_id, berechtigung_id
Code:
### USER ###
id = 9
### USER_GRUPPE ###
user_id = 9
gruppe_id = 33
### GRUPPE ###
id = 33
### GRUPPE_BERECHTIGUNG ###
gruppe_id = 33
berechtigung_id = 20
### BERECHTIGUNG ###
id = 20
klasse = 'Eintrag'
methode = 'neu'
bedingung = 'IF moderators_for_thema CONTAINS user_id WHERE thema_id = eintrag.thema_id'
Hoffentlich macht sich jemand die Mühe und liest den ganzen Mist und kann mir helfen.
Grüße und Danke!