Ik ben bezig met het maken van een CMS/ledensysteem voor een vereniging. Aangezien de rechten van de gebruikers onderling verschillend zijn, werk ik met (gebruikers)groepen om de rechten te geven. De groep bepaalt de rechten.

Ik wil het systeem zo dynamisch mogelijk maken, en er komen zeer veel verschillende rechtensoorten (zoals 'artikel toevoegen' of 'pagina wijzigen').

Wat is de handigste manier om bij die groepen de rechten die ze krijgen op te slaan in MySQL?

Opties die ik zelf zag, maar niet echt perfect vond, waren:
1. Per recht een nieuwe rij aanmaken in MySQL (nadeel: gezien het feit dat er soms nieuwe rechten bijkomen, moet telkens het tabel aangepast worden)
2. één veld maken voor alle rechten, die hij scheidt met een | of ander teken: met explode/implode te maken/krijgen. Of dit, maar dan met serialize(PHP)
3. Een nieuw tabel maken met daarin de rijen 'gebruikersgroep (als verwijzing naar de groeepn), de rij 'recht' (bijv. 'artikel toevoegen') en de rij 'waarde' (0 voor nee, 1 voor ja). Dit wordt dan een ontzettend lang tabel met heel vaak dezelfde groepen, zelfde rechten (die weer voor andere groepen gelden. Dit dan met een SQL join.

Mijn vraag is dan ook:
Wat is het handigste systeem om de typen rechten op te slaan, en hierbij gemakkelijk nieuwe rechten-typen te kunnen toevoegen en wijzigen. Zo dynamisch mogelijk, want dit moet gebeuren in PHP zelf (je kan in de CMS wijzigen in het "register")
Optie 3 is de optie die je wilt gebruiken. Een aparte tabel voor groepen en rechten en daarnaast een koppeltabel om de rechten aan een groep te koppelen.

Maak je maar niet druk dat die tabel veel records zal bevatten, een paar miljoen records in een tabel is een peuleschil voor de database...
Ik denk dat je het best kunt gaan voor een tabel met deze rechten, neem hiervoor gewoon letters, dan kun je 52 verschillende opties houden (hoofd- en kleine letters). Deze letters kun je dan in de documentatie beschrijven, althans...zo zou ik het waarschijnlijk doen.

In de vorm van:

User | Privilege
1 | A
1 | a
1 | x
2 | b
3 | A

Ik zou het verder niet opslaan als "ja/nee", als het voorkomt in de database mag het, anders niet.
Ik zou het zo doen:

Wanneer je met groepen wilt werken:

Tabel 1:
Id | recht

Tabel 2:
Id | groep_id | recht_id

Tabel 3:
Id | groep

In tabel 1 kun je nu de rechten zetten. VB:
1 | Pagina’s bewerken
2 | Bestanden uploaden
3 | Pagina’s verwijderen

In tabel 2 kun je groepen aanmaken. VB:
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 2 | 1
5 | 2 | 2
6 | 3 | 1

In tabel 3 kun je de groepen namen geven. VB:
1 | Administrator
2 | Pagina bewerker
3 | Pagina bewerker die geen bestanden mag uploaden
eem hiervoor gewoon letters, dan kun je 52 verschillende opties houden (hoofd- en kleine letters)
Hoezo zou je hier in hemelsnaam letters voor gebruiken? Neem gewoon een aparte tabel waarin je alle verschillende rechten opslaat en koppel die rechten via het id aan een gebruiker(sgroep):

groepen
----------
id
omschrijving

rechten
---------
id
omschrijving

rechten_groepen
--------------------
id_recht
id_groep

En klaar ben je.
users:
- id (PK)
- id_rol (FK)
- naam

rollen:
- id (PK)
- naam

rechten:
- id (PK)
- naam

rol_rechten:
- id_rol (FK)
- id_recht (FK)

PK = primary key
FK = foreign key

Met deze opzet kun je per user 1 rol toekennen en per rol de juiste rechten instellen. Dit is volledig waterdicht en 100% veilig. Althans, zo veilig als dat jij jouw rollen instelt. Maar dat kun je testen en kan dus helemaal goed zijn.

Andere oplossingen leveren al snel potentieele veiligheidslekken op.

Edit: Waarom verbaast het mij niet dat Blance met dezelfde oplossing komt? ;)
Ik heb zo het idee dat Blanche, pgFrank en ik alle 3 hetzelfde idee hebben *-)
PHP Newbie schreef op 26.04.2008 16:26
Ik heb zo het idee dat Blanche, pgFrank en ik alle 3 hetzelfde idee hebben *-)
Klopt, jij hebt alleen een klein schoonheidsfoutje in tabel 2 zitten:

Tabel 2:
Id | groep_id | recht_id

Het id is hier volkomen zinloos, je doet er nooit wat mee. Gebruik groep_id en recht_id en klaar ben je. Van deze combinatie maak je een PK, dan weet je zeker dat het uniek is en heb je ook direct alle indexen goed.
Je hebt gelijk. ID is hier niet nodig.. Maar het is een beetje automatisme geworden om voor iedere tabel een ID te gooien..
Geniale oplossing.. ben ik heel blij mee

Ik probeer altijd zo weinig mogelijk tabellen te maken, maar dat is zó ingewikkeld (dan moeten er allerlei array's via serializes opgeslagen worden in velden).
Vooral als je ook nog eens dynamische formulieren maakt, die samengesteld worden afhankelijk van een tabel met de formuliervelden, en dáár nog eens zoiets in gebouwd moet worden, is dat bijna niet te doen.

Ik ga het zo doen, en volgens mij moet het dan wel lukken. Dank voor alle reacties!

Nog klein vraagje:
- wat is de handigste manier om een installatiebestand te maken voor de CMS, want er zijn al zoveel ID's die van elkaar afhangen (hier, maar ook in andere delen)... en als je een keer een recht toevoegt, bijv, dan hangen anderen er ook weer vanaf
Ik probeer altijd zo weinig mogelijk tabellen te maken
Waarom? Dat is niet echt een slimme aanpak. Ga normaliseren dan blijkt direct hoe je datamodel eruit hoort te zien...

Reageren