Assumindo a seguinte estrutura de banco de dados (modificável, se necessário) ...
Estou procurando uma boa maneira de determinar as "permissões efetivas" para um determinado usuário em uma determinada página, de maneira que eu possa retornar uma linha contendo a Página e as permissões efetivas.
Eu estou pensando que a solução ideal pode incluir uma função que usa um CTE para executar a recursão necessária para avaliar as "permissões efetivas" para uma determinada linha da página para o usuário atual.
Detalhes de plano de fundo e implementação
O esquema acima representa um ponto de partida para um sistema de gerenciamento de conteúdo no qual os usuários podem receber permissões adicionando e removendo funções.
Os recursos no sistema (por exemplo, páginas) estão associados a funções para conceder ao grupo de usuários vinculados a essa função as permissões que ele concede.
A idéia é poder bloquear facilmente um usuário, simplesmente negando todas as funções e adicionando a página de nível raiz na árvore a essa função e adicionando o usuário a essa função.
Isso permitiria que a estrutura de permissão permanecesse em vigor quando (por exemplo) um contratado que trabalha para a empresa não estiver disponível por longos períodos; isso também permitirá a mesma concessão de suas permissões originais, simplesmente removendo o usuário dessa função. .
As permissões são baseadas em regras típicas do tipo ACL que podem ser aplicadas ao sistema de arquivos seguindo essas regras.
As permissões CRUD devem ser bits anuláveis para que os valores disponíveis sejam verdadeiros, falsos, não definidos onde o seguinte for verdadeiro:
- falso + qualquer coisa = falso
- verdadeiro + não definido = verdadeiro
- verdadeiro + verdadeiro = verdadeiro
- não definido + não definido = não definido
Se alguma das permissões for falsa -> false Caso contrário, se algum for verdadeiro -> verdadeiro Outro (todos não definidos) -> false
Em outras palavras, você não obtém permissões em nada, a menos que seja concedido através da associação à função e uma regra de negação substitua uma regra de permissão.
O "conjunto" de permissões às quais isso se aplica é todas as permissões aplicadas à árvore até e inclusive a página atual, em outras palavras: Se um false estiver em qualquer função aplicada a qualquer página da árvore nesta página, o resultado será falso. , mas se a árvore inteira até aqui não estiver definida, a página atual conterá uma regra verdadeira, o resultado será verdadeiro aqui, mas seria falso para o pai.
Gostaria de manter vagamente a estrutura db, se possível, lembre-se também de que meu objetivo aqui é poder fazer algo como: select * from pages where effective permissions (read = true) and user = ?
portanto, qualquer solução deve permitir que eu tenha um conjunto consultável com as permissões efetivas neles em de alguma forma (devolvê-los é opcional, desde que os critérios possam ser especificados).
Supondo que existem 2 páginas em que 1 é filho da outra e existem 2 funções, uma para usuários administrativos e uma para usuários somente leitura, ambas estão vinculadas apenas à página no nível raiz. Eu esperaria ver algo assim como a saída esperada:
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
Discussões adicionais sobre essa questão podem ser encontradas na sala de bate-papo do site principal, começando aqui .