Supponendo la seguente struttura del database (modificabile se necessario) ...
Sto cercando un modo carino per determinare le "autorizzazioni effettive" per un determinato utente su una determinata pagina in un modo che mi permetta di restituire una riga contenente la Pagina e le autorizzazioni effettive.
Sto pensando che la soluzione ideale possa includere una funzione che utilizza un CTE per eseguire la ricorsione necessaria per valutare le "autorizzazioni effettive" per una determinata riga di pagina per l'utente corrente.
Background e dettagli di implementazione
Lo schema sopra rappresenta un punto di partenza per un sistema di gestione dei contenuti in cui gli utenti possono ottenere le autorizzazioni aggiungendoli e rimuovendoli dai ruoli.
Le risorse nel sistema (ad es. Pagine) sono associate a ruoli per concedere al gruppo di utenti collegato a quel ruolo le autorizzazioni che concede.
L'idea è quella di essere in grado di bloccare facilmente un utente semplicemente negando tutto il ruolo e aggiungendo la pagina di livello radice nella struttura ad esso e quindi aggiungendo l'utente a quel ruolo.
Ciò consentirebbe di mantenere la struttura delle autorizzazioni quando (ad esempio) un appaltatore che lavora per l'azienda non è disponibile per lunghi periodi, ciò consentirà anche la stessa concessione delle autorizzazioni originali semplicemente rimuovendo l'utente da quel ruolo .
Le autorizzazioni si basano su regole tipiche del tipo ACL che potrebbero essere applicate al file system seguendo queste regole.
Le autorizzazioni CRUD devono essere bit nullable quindi i valori disponibili sono true, false, non definiti dove è vero quanto segue:
- falso + nulla = falso
- vero + non definito = vero
- vero + vero = vero
- non definito + non definito = non definito
Se una delle autorizzazioni è false -> false Altrimenti se uno è vero -> vero Altrimenti (tutto non definito) -> false
In altre parole, non si ottengono autorizzazioni per nulla, a meno che non vengano concessi tramite l'appartenenza al ruolo e una regola di rifiuto sovrascrive una regola di autorizzazione.
Il "set" di autorizzazioni a cui si applica sono tutte le autorizzazioni applicate all'albero fino alla pagina corrente inclusa, compresa: se un falso è in qualsiasi ruolo applicato a qualsiasi pagina dell'albero in questa pagina, il risultato è falso , ma se l'intero albero fino a qui non è definito, la pagina corrente contiene una regola vera, il risultato è vero qui ma sarebbe falso per il genitore.
Mi piacerebbe mantenere vagamente la struttura del db se possibile, anche tenere presente che il mio obiettivo qui è quello di essere in grado di fare qualcosa del genere: select * from pages where effective permissions (read = true) and user = ?
quindi qualsiasi soluzione dovrebbe essere in grado di permettermi di avere un set interrogabile con le autorizzazioni efficaci in essi contenute in qualche modo (la loro restituzione è facoltativa purché sia possibile specificare i criteri).
Supponendo che esistano 2 pagine in cui 1 è figlio dell'altro ed esistono 2 ruoli, uno per gli utenti admin e 1 per gli utenti di sola lettura, entrambi sono collegati solo alla pagina di livello principale che mi aspetto di vedere qualcosa del genere come output previsto:
Admin user:
Id, Parent, Name, Create, Read, Update, Delete
1, null, Root, True , True, True , True
2, 1, Child,True , True, True , True
Read only user:
Id, Parent, Name, Create, Read, Update, Delete
1, null, Root, False , True, False , False
2, 1, Child,False , True, False , False
Ulteriori discussioni su questa domanda sono disponibili nella chat room del sito principale a partire da qui .