I'm doing policy authorization in CakePHP. For all CRUD methods, I have to test if the user has the right to execute them. So I create that method to use in all the methods:
Code in SchoolsController
private function authorize(School $s){
try{
$this->Authorization->authorize($s);
} catch(ForbiddenException $e){
$this->Flash->error("You don't have permission.");
return $this->redirect(['controller' => 'Schools', 'action' => 'index']);
}
}
I'm testing the code for a user who wouldn't have permission. This should work but the code after calling this method is still called.
public function delete($id = null) {
$school = $this->Schools->get($id);
$this->authorize($school);
$this->request->allowMethod(['post', 'delete']);
if ($this->Schools->delete($school)) {
$this->Flash->success(__("School has been successfully removed."));
} else {
$this->Flash->error(__("The school could not be deleted. Please try again."));
}
return $this->redirect(['action' => 'index']);
}
I'm redirected and I get the two messages: "You don't have permission." "School has been successfully removed."
Here my SchoolPolicy
public function canDelete(IdentityInterface $user, School $school)
{
return $this->isAuthor($user,$school);
}
protected function isAuthor(IdentityInterface $user, School $school)
{
return $school->userId === $user->id;
}
CodePudding user response:
If you catch an exception, then it will of course not halt execution, that's the whole point of catching it. And if you then return a value from your method (Controller::redirect()
will return the response object with the Location
header configured accordingly), you'll need to do something with that value, otherwise it will just vanish into the void, so for example:
$response = $this->authorize($school);
if ($response) {
return $response;
}
It's a bit hidden in the docs, but the easier approach would be to throw a redirect exception from your authorize()
method. Also, if you do not actually make any use of the forbidden exception and the information that it holds, then you could simply use the can()
method, which returns a boolean, eg:
if (!$this->Authorization->can($s)) {
$this->Flash->error("You don't have permission.");
throw new \Cake\Http\Exception\RedirectException(
\Cake\Routing\Router::url([
'controller' => 'Schools',
'action' => 'index',
])
);
}
You may also want to consider using a custom unauthorized handler instead.