Reputation: 87
I've encountered this issue several times and tried to avoid it by removing calling Flash method. Lately, I want to show an error flash to non-logged in user who tries to log out. However, when I test this action(by accessing localhost:8765/users/logout without being logged in), everything works fine except I get 2 error messages "You are not authorized to access this location". How can I fix this issue?
Here are my codes
In AppController:
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Auth', [
'authorize' => ['Controller'], //For User authorize checking, this tells app to let each controller decides own rules for authorize
'loginRedirect' => ['controller' => 'Articles', 'action' => 'index'],
'logoutRedirect' => ['controller' => 'Users', 'action' => 'index']
]);
}
public function beforeFilter(Event $event)
{
//this applied to every controller
$this->Auth->allow(['index', 'view', 'display']);
}
...
public function isAuthorized($user)
{
//Admin can access every action
if(isset($user['role']) && $user['role'] === 'admin'){
return true;
}
//Default deny
return false;
}
In UsersController:
public function isAuthorized($user)
{
//All registered users can add articles
if($this->request->action === 'add'){
return true;
}
//The self user can edit and delete the account
if(in_array($this->request->action, ['edit', 'delete'])){
//get id of targeted user
$targetUserId = (int)$this->request->params['pass'][0];
//check if current user is the targeted user
if($this->Users->selfUser($targetUserId, $user['id'])){
return true;
}else{
$this->Flash->error(__('You are not authorized for this action'));
}
}
return parent::isAuthorized($user);
}
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['add']);
}
...
public function logout()
{
return $this->redirect($this->Auth->logout());
}
In UsersTable
public function selfUser($targetedUserId, $userId)
{
return $targetedUserId == $userId;
}
In default.ctp
$cakeDescription = 'CakePHP: the rapid development php framework';
?>
<!DOCTYPE html>
<html>
<head>
<?= $this->Html->charset() ?>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>
<?= $cakeDescription ?>:
<?= $this->fetch('title') ?>
</title>
<?= $this->Html->meta('icon') ?>
<?= $this->Html->css('base.css') ?>
<?= $this->Html->css('cake.css') ?>
<?= $this->fetch('meta') ?>
<?= $this->fetch('css') ?>
<?= $this->fetch('script') ?>
</head>
<body>
<nav class="top-bar expanded" data-topbar role="navigation">
<ul class="title-area large-3 medium-4 columns">
<li class="name">
<h1><a href=""><?= $this->fetch('title') ?></a></h1>
</li>
</ul>
<div class="top-bar-section">
<ul class="right">
<li><a target="_blank" href="http://book.cakephp.org/3.0/">Documentation</a></li>
<li><a target="_blank" href="http://api.cakephp.org/3.0/">API</a></li>
</ul>
</div>
</nav>
<?= $this->Flash->render() ?>
<div class="container clearfix">
<?= $this->fetch('content') ?>
</div>
<footer>
</footer>
</body>
</html>
In login.ctp
<div class="users form">
<?= $this->Flash->render('auth') ?>
<?= $this->Form->create() ?>
<fieldset>
<legend><?= __('Please enter your username and password') ?></legend>
<?= $this->Form->input('username') ?>
<?= $this->Form->input('password') ?>
</fieldset>
<?= $this->Form->button(__('Login')); ?>
<?= $this->Form->end() ?>
</div>
Upvotes: 0
Views: 1288
Reputation: 30
You must add this line in your logout action:
$this->autoRender = false;
So, in your case, your UsersController should be:
public function isAuthorized($user)
{
//All registered users can add articles
if($this->request->action === 'add'){
return true;
}
//The self user can edit and delete the account
if(in_array($this->request->action, ['edit', 'delete'])){
//get id of targeted user
$targetUserId = (int)$this->request->params['pass'][0];
//check if current user is the targeted user
if($this->Users->selfUser($targetUserId, $user['id'])){
return true;
}else{
$this->Flash->error(__('You are not authorized for this action'));
}
}
return parent::isAuthorized($user);
}
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
$this->Auth->allow(['add']);
}
...
public function logout()
{
$this->autoRender = false;
return $this->redirect($this->Auth->logout());
}
Upvotes: 0
Reputation: 53
Could you also post even just an excerpt from your CTP file? It could be possible that within the page layout the Flash was rendered twice.
Upvotes: 1