I want to protect certain methods in my application such as publish, unpublish, and close. By protection I don't mean user authorisation but rather the ability to call the method in a certain way.
I have thought about FORCING the methods to be called using POST rather than GET so that a person can't just paste the URL in the address (even though I could just check the user id of the person doing it). However this means wrapping each button in a different form for each method call.
Alternatively I could use a GUID to allow the GET method but make sure it only allows the correct person to do the function.
Any thoughts ideas on this?
So far I have tried:
function publish($id = null)
{
$post = $this->Post->find('first',array('conditions'=>array('Post.id'=>Tiny::reverseTiny($id))));
if ($this->request->is('post') || $this->request->is('put'))
{
$this->Post->id = $post['Post']['id'];
$this->Post->saveField('status', 1);
$this->Session->setFlash('Your post has been published!');
$this->redirect(array('controller'=>'posts','action'=>'view','id'=>Tiny::toTiny($post['Post']['id'])));
}
else
{
die('GET METHOD NOT ALLOWED');
}
}
But as stated above that means the link/button for this method would need be in a form containing the action call to this method. And If I have several methods I would need several forms...
Cheers
One way I have thought about is allowing the get method and then checking the user id of the post compared with the logged in user id like so:
if ($this->request->is('get'))
{
if($post['Post']['user_id'] != $this->Auth->user('id'))
{
$this->Session->setFlash('You don\'t have permission to edit that post!');
$this->redirect(array('controller' => 'posts', 'action' => 'index'));
}
else
{
$this->Post->id = $post['Post']['id'];
$this->Post->saveField('status', 1);
$this->Session->setFlash('Your post has been published!');
$this->redirect(array('controller'=>'posts','action'=>'view','id'=>Tiny::toTiny($post['Post']['id'])));
}
}
Is this good practice?
(Assuming CakePHP 2.0 here)
Firstly, rather than calling die on a Post/Get check. Throw an exception, exceptions in cake are wonderful (Exceptions):
if (!$this->request->is('get')) {
throw new MethodNotAllowedException();
}
Cake also provides a way to generate a link to delete (via post) in your template.
<?php echo $this->Form->postLink('Delete',
array('action' => 'delete', $post['Post']['id']),
array('confirm' => 'Are you sure?'));
?>
Edit (Link): postLink
This is my first answer in a Stack Overflow. Hope it was helpful.
It sounds like you need ACL or some form of permissions if you want to only allow certain users to perform the function. The reason you wouldn't use something like you have posted ( if($post['Post']['user_id'] != $this->Auth->user('id'))
) is because you will end up replicating that code in a lot of functions through out your code base. That is very sloppy.
However, you only want to make sure that the submission was submitted in a specific manner, then the throw error method is the way to go. And you should be able to keep the submission inside the same function like so:
public function publish($id = null) {
if (!$id || !$this->request->is('get') || !$this->request->is('post') || !$this->request->is('put')) {
throw new MethodNotAllowedException();
}
if ($this->request->is('post') || $this->request->is('put')) {
$this->Post->id = $post['Post']['id'];
$this->Post->saveField('status', 1);
$this->Session->setFlash('Your post has been published!');
$this->redirect(array('controller'=>'posts','action'=>'view','id'=>Tiny::toTiny($post['Post']['id'])));
}
if ($this->request->is('get')) {
// perform your get request here
}
}
With minimal code $this->request->allowMethod('post');