[VRaptor] Controle de acesso via action

Bom dia Pessoal.

Estou em um projeto novo com VRaptor 3 e, até aqui, está indo tudo muito bem.

Estou montando a logica de acesso a páginas e funcionalidades do sistema.

Basicamente me baseio nas actions para definir acesso no sistema.

Basicamente: Um usuário tem um list de actions que pode acessar.

As models já foram construídas, o cadastro de actions e controllers também.

Do que preciso:

Meu plano é comparar a action que o usuário está tentando acessar com seu mapa.

  in array ( action corrente, mapa action usuario ) ? abrir pagina : nao abrir pagina 

Estou usando interceptors (@Interceptor) para algumas rotinas e sei como ele funciona.

Alguem tem idéia de como recuperar o nome do controller a partir do ResourceMethod

Meu interceptor (ainda em debug esta ficando assim)


package br.com.brabus.epico.interceptor;

import java.lang.annotation.Annotation;

import br.com.caelum.vraptor.InterceptionException;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.core.InterceptorStack;
import br.com.caelum.vraptor.interceptor.Interceptor;
import br.com.caelum.vraptor.resource.ResourceMethod;

public class CaminhoInterceptor implements Interceptor{
	
	private final Result result;
	
	public CaminhoInterceptor(Result result) {
		this.result	=	result;
	}

	public boolean accepts(ResourceMethod method) {
		return true;
	}

	public void intercept(InterceptorStack stack, ResourceMethod method, Object resourceInstance) throws InterceptionException {
		
		System.out.println( "METHOD :: " + method.getMethod().getName() );
		
		System.out.println( "CONTROLLER :: " + method. ????????????? ); // como chegar na controller 
		
		for (Annotation annotation : method.getMethod().getAnnotations()) { 
			
			System.out.println( "ANNOTATION:: " + annotation.getClass().getName() );
			
			
		}
		
		stack.next(method, resourceInstance);
	}
	
}

Valeu pessoal.

A propósito, estou com o VRaptor a duas semanas,
Já tenho um help desk funcionando,
cadastro de usuarios,
cadastro de departamentos,
cadastro de serviços,
interceptors de controle e migração de dados entre diferentes bases/sistemas (oracle => mysql) => substituindo os famosos crons

Não é uma crítica mas ia me fu… com JSF com EJB
O time entre aprendizado x aplicação com o VRaptor é absurdo.

Ainda estou aprendo alguma coisa com o Vraptor 3, o tutorial é pouco ilustrativo e estou usando o MyEclipse Blue 8.6, para evitar excesso de configuração.

Obrigado Marcelo Lauter.

O V|Raptor quase não tem configuração.
O V|Raptor usa o conceito de Convention of configuration, ou seja, configurar na maioria dos casos é algo opcional.

Alguém tem alguma idéia de como localizar a Controller a partir do ResourceMethod em um interceptor?
[]s
Jsign

diretamente seria:

method.getResource().getType().getSimpleName();

resource é o que representa o controller, type é a Class dele.

essa classe tem um exemplo de como usar isso:

[]'s

Obrigado Lucas.
[]s

Pessoal, aproveitando o tópico gostaria de pontuar um aparente problema que ocorre com o VRaptor em injeção de dependencias bidirecional.

" Uma dependencia pode chamar outra por composição/injeção e esta por sua vez pode fazer o mesmo "

Tenho o cenário :

Minha controller : SiteControllerController
é composta de uma DAO : SiteControllerDAO

Esta DAO : SiteControllerDAO
é composta por outra DAO : SiteActionDAO que por sua vez é composta por uma SiteControllerDAO

Assim consigo manter as interações (merge/persist) separadas por dao e interadas por uma ou outra controller.

Controller

@Component
public class SiteControllerDAO {

	private final Session session;
	private final SiteActionDAO siteActionDAO;

	public SiteControllerDAO(Session session, SiteActionDAO siteActionDAO) {
		this.session = session;
		this.siteActionDAO = siteActionDAO;
	}
...

DAO_01

@Component
public class SiteActionDAO {

	private final Session session;
	private final SiteControllerDAO siteControllerDAO;

	public SiteActionDAO(Session session, SiteControllerDAO siteControllerDAO) {
		this.session = session;
		this.siteControllerDAO = siteControllerDAO;
	}
...

DAO_02

@Component
public class SiteControllerDAO {

	private final Session session;
	private final SiteActionDAO siteActionDAO;

	public SiteControllerDAO(Session session, SiteActionDAO siteActionDAO) {
		this.session = session;
		this.siteActionDAO = siteActionDAO;
	}
...

Bom resolvi da seguinte forma:


public class SiteControllerController {

	private final SiteActionDAO dao;
	private final Result result;
	private final Validator validator;
	private String msg;

	public SiteControllerController(SiteActionDAO dao, Result result, Validator validator){
		this.dao = dao;
		this.result = result;
		this.validator = validator;
	}

A Controller de controllers não chama mais a dao SiteControllerDAO, e sim a SiteActionDAO
esta ultima tem por conposicao a SiteControllerDAO, assim, podendo acessa-la.

Não sei se é a melhor navegação, afinal, estou chamado uma dao x para manipular objetos y a partir de uma controller y.

Para ter uma idéia, meu metodo de listagem ficou assim:

@Get @Path("/controllers") public List<SiteController> lista() { return dao.getSiteControllerDAO().listarTudo(); }

[]s
Jsign

só por curiosidade, esses Controllers não são os mesmos controllers do VRaptor, certo?

São controllers do VRaptor sim.

A maneira mais higienica que encontrei foi injetar mais de uma dao no controller, assim, dividindo bem os metodos entre as daos (nao replicando metodos entre as dao’s).


@Resource
public class SiteActionModeloController {

	private final SiteActionModeloDAO dao;
	private final SiteActionDAO siteActionDAO;
	private final Result result;
	private final Validator validator;

	public SiteActionModeloController(SiteActionModeloDAO dao, SiteActionDAO siteActionDAO, Result result, Validator validator){
		this.dao = dao;
		this.result = result;
		this.siteActionDAO	=	siteActionDAO;
		this.validator = validator;
	}

...

Achei interessante a possibilidade de uma DAO ter injetada outra, aparentemente o vraptor permite isso.

Mas quando há bidirecionalidade ( ambas daos injetas entre as mesmas ) ele reclama.

Até entendo.

Não sei se é uma questão de design, o que você acha : Uma dao pode chamar outra ? Esta outra pode chamar quem também a injeta ?

[]'s
Jsign

 List<SiteController> lista() 

SiteController é um controller do VRaptor?

não dá pra fazer dependências circulares com injeção por construtor, mas dá com injeção por setter ou field.

Em todo caso se o DAO1 depende do DAO2 e vice-versa, isso pode indicar que eles deveriam ser um único dao, ou pelo menos que algum método do DAO1 deveria estar no DAO2 ou vice-versa.

Sim, estou trabalhando com Controllers do VRaptor.

Estou isolando as ações de cada bean em uma dao, exemplo: Todo metodo que utilize ‘Pessoa’ pode ser encontrado na dao ‘PessoaDAO’.
Assim, antes de contruir qualquer novo metodo sobre ‘Pessoa’ verifico se já existe na sua respectiva DAO.
No modelo que estou trabalhando tenho as entidades Controller, Action, ActionModelo…
As DAO’s respectivas.
Na controller ActionController preciso listar as ‘Controller’ para relacionar a action a ser criada/persistida.
Por isso tenho mais de uma dao na controller.
Gostei do modelo de injecao por setter.
Obrigado Lucas.

[]s
JSign.

desculpa a intromissão, mas não entendi porque que isso é útil. Se os controllers e métodos respectivos já estão em arquivos java, por que guardá-los no banco de dados?

ou isso é algum tipo de autorização?

Não tem problema Lucas.
Se derrepente ver outra ótica sobre a lógica por favor pontue.

Bom, tenho o cadastro de controllers e actions do sistema para controlar acesso dos usuários.

Um usuário (SessionScoped) tem n actions que pode acessar.

Seu menu (SessionScoped) é montado com base nas actions que pode alcançar.

Um interceptor valida a cada nova requisição o acesso do usuário à action solicitada (caso tente forçar acesso via url e não por link de menu).

Registro também os eventos do usuário em um log (UsuarioLog) que registra as actions por ele operadas.

[]s
Jsign

certo,

talvez criar uma entidade que represente isso e ter só o dao dessa entidade facilitaria seu trabalho, assim vc não usa os controllers diretamente

Lucas.
Terminei os cruds ontem, não ficou difícil de chamar usando a injeção por setter ou mais de uma injeção de dao’s por construtor na controller.
Era mais uma questão de saber quanto a possibilidade de injeção de dependencias de forma circular.

Obrigado.
[]s
Jsign

Talvez se ao invés de você validar permissão do usuário por controllers e actions, você poderia fazer isso pela URL + método HTTP.
Acho que fica mais claro.

Outra coisa que talvez seja legal, é você fazer a validação por anotations, tem um camarada aqui do fórum que já fez isso, da uma pesquisada na area de frameworks e bibliotecas brasileiros.
Fica legal por anotações também, só que ai caso vc precise mudar a regra, vai precisar mexer no fonte.

Abraços

Olá Nicolas,

Bom, não sei se conhece o V|Raptor, não sou nenhum especialista, mas o caso é que um dos grandes atrativos de simples aplicação do V|Raptor é poder trabalhar actions diferentes e uma mesma chamada.


        @Get @Path("/chamados") // url: /chamados 
	public List<Chamado> lista() {
		
		if(atendente.getUsuario().getHelpDeskAdm() == true){
		
			return dao.listar();
		
		}
		
		return null;
	}

        @Post @Path("/chamados") // via post: /chamados 
	public void altera(Chamado chamado) {

	...

        }

O V|Raptor tem anotações que definem o tipo da requisição : protocolo HTTP.

Assim, a tratativa de trabalhar só com a url usando o VRaptor me dá duas opções:

  • liberar acesso para todas as actions que respondam a mesma url por usuário (liberar ver e editar chamdos por exemplo por que é a mesma url)

  • ignorar esta funcionalidade do V|Raptor e trabalhar com verbos na url: chamdos/ver/1, chamdos/editar/1, chamdos/alterar

Outro diferencial, usando esta estratégia é que eu monto o menu do usuário com base no tipo de acesso, ou seja, apenas para requisições do tipo GET.

Tipos POST, DELETE, PUT não me importam para montar o menu, os links de menu geralmente são páginas de listagems (readAll) que direcionam para sublinks via opções de listagem, estes ultimos compoem o crud.

Falando assim parece complicado, mas é muito simples.

Eu tenho um interceptor que monta o menu do usuário uma vez só por sessao, o que no V|Raptor é tratado como Scopo de sessão (cache), baseando-se nas actions (get) que este usuário possui, ou pode acessar.

Para facilitar o gerenciamento criei grupos de actions que podem ser copiados (incorporados) a permissao do usuário.

Além disso, no cadastro da action informo se ela é um módulo, ou seja, se vai aparecer em uma página de atalhos do sistema ou não.

Outro detalhe no cadastro das actions é que posso informar quem é a action pai, assim, na montagem do menu, consigo controlar os sublinks em até 5 gerações: pai > filho > netos > bisnetos > tataranetos.

Fiz para 5 gerações, acho que passar disso já é exagero nehh, pouco ergonômico.

Outra coisa: O trabalho de cadastros teria de ser feito de qualquer forma, seja controlando actions ou url’s.

De qualquer forma valeu,

Quando vai pegar sua xicara mlk.
Tava com vc no ultimo FJ91.

Abçs
Davi.

[quote=jsign]Obrigado Marcelo Lauter.

O V|Raptor quase não tem configuração.
O V|Raptor usa o conceito de Convention of configuration, ou seja, configurar na maioria dos casos é algo opcional.

Alguém tem alguma idéia de como localizar a Controller a partir do ResourceMethod em um interceptor?
[]s
Jsign[/quote]

Ok.Pode deixar um demo da sua aplicação pra entender esse conceito funcional, colocando no Github pra download, já lhe agradeceria enormemente, https://github.com/caelum/vraptor-scala-mydvds

Valeuu !!!

To te devendo essa Marcelo, eu ainda não consegui tempo para montar/melhorar esta demo, eu melhorei ela um pouquinho mais usando uma interface para acesso publico.
Vou faze-la, assim que o fizer aviso.

[]s
Davi