Boa tarde pessoal
Estou trabalhando em um sistema que, inicialmente, não é MUITO grande, mas tem uma complexidade considerável, porém, pode ir a crescer bastante com a implementação de novos módulos.
Esse sistema será multiusuário, e cada usuário só poderá acessar as áreas as quais tiver permissão.
Uma forma de implementar isso seria, na entidade Usuario, ter vários atributos boolenos, tipo:
private boolean gerenciaUsuarios;
private boolean geraRelatorioMensal;
Isso funciona, mas como o sistema tende a crescer, sendo adicionados novos módulos e funcionalidades, quando colocasse uma funcionalidade nova, teria de alterar a classe Usuario do modelo, e o banco de dados, colocando mais um boolean para aquela função. Por exemplo, se implementar uma função para gerarRelatorioAnual, teria de alterar o banco de dados e adicionar na classe Usuario:
private boolean geraRelatorioAnual;
Uma solução que encontrei, baseada na apresentada em uma apostila da Caelum, foi de implementar uma anotação Role, mas não segui a implementação utilizada lá, por diferenças de requisito mesmo, já que não tenho grupos de usuários, mas sim funções específicas.
Estou implementando da seguinte maneira: minha classe Usuario tem um atributo role:
private String role;
Nesse atributo, coloco todas as Strings das permissões do usuário, separando por espaço, por exemplo:
private String role = "gerenciaUsuario geraRelatorioAnual geraRelatorioMensal";
No meu método de geração de relatórios mensais, por exemplo, anotei da seguinte maneira:
public class Relatorio(){
@Role("geraRelatorioMensal")
public void mensal(){
...
}
}
Estou usando VRaptor, então aproveito o conceito de Interceptor. Quando recebo uma requisição, pego a lógica requisitada e verifico a anotação de Role que ela possui, no caso, geraRelatorioMensal. Ai verifico se no atributo role do usuario que esta tentando acessar, contem a String geraRelatorioMensal.
Nas telas, o ítem do menu também só deve aparecer para quem tiver a permissão. Para isso uso o seguinte:
<c:if test="${fn:contains(usuario.role, ' geraRelatorioMensal ') || fn:contains(usuario.role, ' admin ')}">
//crio o menu
</c:if>
Dessa forma, ao colocar uma nova funcionalidade no sistema, eu teria apenas de escrever no role dos usuários que irão acessá-la, mas não precisaria mecher na estrutura do banco e nas classes do modelo. Por outro lado, isso pode gerar uma String enorme, guardada na minha sessão. Uma opção foi criar um role admin, que pode fazer tudo, ai não precisa colocar todas Strings, mas se não puder fazer alguma coisa, uma única que seja, já teria que escrever todas as outras permissões.
Queria ouvir opiniões a respeito da solução que estou usando, dicas de qual seria a melhor opção e conhecer outras formas que tenham utilizado no controle de acesso.
Desde já agradeço a todos.
Abraço