Asumiendo la siguiente estructura de base de datos (modificable si es necesario) ...
Estoy buscando una buena manera de determinar los "permisos efectivos" para un usuario determinado en una página determinada de manera que me permita devolver una fila que contenga la Página y los permisos efectivos.
Estoy pensando que la solución ideal puede incluir una función que use un CTE para realizar la recursión necesaria para evaluar los "permisos efectivos" para una fila de página dada para el usuario actual.
Antecedentes y detalles de implementación
El esquema anterior representa un punto de partida para un sistema de gestión de contenido en el que los usuarios pueden obtener permisos mediante la adición y eliminación de roles.
Los recursos en el sistema (p. Ej. Páginas) están asociados con roles para otorgar al grupo de usuarios vinculados a ese rol los permisos que otorga.
La idea es poder bloquear fácilmente a un usuario simplemente haciendo que se niegue todo el rol y agregando la página de nivel raíz en el árbol a ese rol y luego agregando al usuario a ese rol.
Esto permitiría que la estructura de permisos permanezca en su lugar cuando (por ejemplo) un contratista que trabaja para la empresa no esté disponible durante largos períodos, esto también permitirá la misma concesión de sus permisos originales simplemente quitando al usuario de ese rol .
Los permisos se basan en reglas de tipo ACL típicas que podrían aplicarse al sistema de archivos siguiendo estas reglas.
Los permisos CRUD deben ser bits anulables para que los valores disponibles sean verdaderos, falsos, no definidos donde lo siguiente es verdadero:
- falso + cualquier cosa = falso
- verdadero + no definido = verdadero
- verdadero + verdadero = verdadero
- no definido + no definido = no definido
Si alguno de los permisos es falso -> falso De lo contrario, si alguno es cierto -> verdadero De lo contrario (todo no definido) -> falso
En otras palabras, no obtiene permisos sobre nada a menos que se les otorgue a través de la membresía de roles y una regla de denegación anule una regla de permiso.
El "conjunto" de permisos a los que esto se aplica es todos los permisos aplicados al árbol hasta la página actual, incluida la página actual, en otras palabras: si un falso tiene algún rol aplicado a cualquier página del árbol de esta página, entonces el resultado es falso , pero si el árbol completo hasta aquí no está definido, entonces la página actual contiene una regla verdadera, el resultado es verdadero aquí pero sería falso para el padre.
Me gustaría mantener libremente la estructura de db si es posible, también tenga en cuenta que mi objetivo aquí es poder hacer algo como: select * from pages where effective permissions (read = true) and user = ?
entonces cualquier solución debería permitirme tener un conjunto consultable con los permisos efectivos en ellos de alguna manera (devolverlos es opcional siempre que se puedan especificar los criterios).
Suponiendo que existen 2 páginas donde 1 es hijo del otro y existen 2 roles, uno para usuarios administradores y 1 para usuarios de solo lectura, ambos están vinculados solo a la página de nivel raíz. Espero ver algo como esto como resultado esperado:
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
Puede encontrar más discusión sobre esta pregunta en la sala de chat del sitio principal a partir de aquí .