Categorias
CakePHP PHP Projetos

[Comitiva] Como utilizar controle de permissão no sistema

Como escrevi anteriormente, o PHPMS mantém um sistema para gerenciar eventos – desde a divulgação de informações, cadastro de eventos, inscrições, pagamentos, envio de mensagens para inscritos e check-in.

Mas o objetivo deste post não é dizer o que já foi dito, quero iniciar uma série de posts onde vou explicar o funcionamento de alguns recursos dentro do Comitiva, convidando todos os desenvolvedores a opinar sobre implementação e contribuir com o projeto.

O assunto de hoje é controle de acesso, então vamos ao que interessa.

Como funciona o controle de acesso no Comitiva?

Utilizamos o componente Auth do CakePHP para cuidar da autenticação (efetuar login, verificar se o usuário está logado e efetuar logout).
Mas precisávamos ir um pouco além da configuração básica, definindo diferentes opções para diferentes tipos de usuários. Para isso, consideramos duas opções iniciais: usar também o Acl Behavior ou ficar apenas com o AuthComponent e criar diferentes actions para diferentes tipos de usuários.

Como possuímos apenas dois tipos de usuários (admin e participant) decidimos pela que seria mais simples inicialmente – mesmo sabendo que a manutenção no futuro poderia ser mais complicada – que foi criar diferentes actions para os tipos de usuários.

Para criar essa funcionalidade, definimos inicialmente um prefixo para cada tipo de usuário (prefixos ‘admin‘ e ‘participant‘). Em seguida configuramos o AuthComponent desta maneira (código extraído do AppController):

//Configure AuthComponent
$this->Auth->authorize = 'controller';

if( !isset($this->params['prefix']) || !( in_array($this->params['prefix'], Configure::read('Routing.prefixes')) ) )
{
	// all non-prefixed actions are allowed
	$this->Auth->allow('*');
}

Ou seja, toda ação que não tiver prefixo ou o prefixo não estiver definido nas configurações de rota serão públicas (assim é possível, por exemplo, deixar uma página com instruções acessível à qualquer usuário).

Mas como fica essa verificação de tipos no controlador? Como definimos o método de autorização do Auth como ‘controller’, precisamos definir em todos os controladores o método isAuthorized que deve retornar true quando o acesso é aprovado e false caso contrário.
Seguindo a ideia de que cada tipo de usuário possui um prefixo próprio nas ações, nosso método isAuthorized fica desta forma:

if($this->userLogged == TRUE && $this->params['prefix'] == User::get('type'))
{
	return true;
}

return false;

Onde o atributo $this->userLogged pertence a classe AppController e sua função é reduzir chamada ao método $Auth->login() e na segunda parte da condição temos uma comparação entre o prefixo da url acessada e o tipo do usuário – se ambos forem iguais, então o acesso está liberado.

Por fim, devemos criar nossas ações para cada tipo de usuário, onde o prefixo será usado para validar o acesso à aquela ação, veja o exemplo da ação “listar pagamentos”:

// ação exclusiva para admin - tem acesso aos pagamentos de todos os outros usuários
public function admin_index($event_id = null)
{
	$this->Subscription->recursive = 0;
		
	if(is_numeric($event_id))
	{
		$this->paginate = array(
			'conditions' => array(
				'event_id' => $event_id
			)
		);
	}
		
	$this->set(compact('event_id'));
	$this->set('subscriptions', $this->paginate());
}

// ação exclusiva para participant - tem acesso somente aos próprios pagamentos
public function participant_index()
{
	$this->Subscription->recursive = 0;
	$this->set('subscriptions', $this->paginate(array('user_id' => User::get('id'))));
}

Como podem ver, isso permite a criação de diferentes regras de negócio para os diferentes tipos de usuários e embora aumente a quantidade de código “redundante” por repetir alguns procedimentos para todos os tipos de usuários, a leitura e entendimento do código é facilitada – basta ver o prefixo do método (ação) para saber quem terá acesso a ele.

Por Cauan Cabral

Desenvolvedor com 2 dígitos de experiências, especialista em PHP e CakePHP mas com bagagens em JavaEE, Node.js, Javascript (ES6, jQuery, Angular) e Python. Interessado em automação, Machine Learning e cozinha.

4 respostas em “[Comitiva] Como utilizar controle de permissão no sistema”

E se caso o mesmo usuario ser admin e participant? Ou seja, ter mais de um papel no sistema? Nao seria melhor type ser um array com todos os papeis que o usuario pode desempenhar no sistema? Assim bastaria testar se o usuario pode desempenhar aquele papel no sistema qdo acessar uma action. Algo tipo:

return $this->userLogged == TRUE &&
in_array($this->params[‘prefix’], User::get(‘type’));

Fica bem simples construir um sistema com multiplos grupos.

Até agora nós encaramos o usuário admin como alguém que pode desempenhar todas as funções do sistema – então neste caso poderia ser encarado como pertencente a todos os grupos.
Isso tem funcionado de forma satisfatória até agora, porém com a adição de novas funcionalidades (como envio de proposta de trabalho e a figura de um “speaker” – que já estão em andamento pelo Zé Ricardo e o Agripino) as coisas começam a complicar.

Essa ideia de verificar múltiplos grupos é interessante, mas acho que deveríamos partir para uma implementação mais flexível, talvez usando ACL (o componente padrão do CakePHP poderia servir bem a isso) com seus ARO’s e ACO’s.

Isso poderia eliminar a necessidade de criar uma action para cada tipo de usuário.

Deixe um comentário para Cauan Cabral Cancelar resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.