views:

62

answers:

2

The idea is quite simple. If you are not logged in, you have no access to any page beside the register and login page. If you are logged in, you have access to all pages except the register page.

Now, half of this is achieved by using CakePHP's Auth Component. This restricts access when not logged, and allows access when logged.

The problem I stumbled upon when doing this was restricting access to the register page when logged. I tried different methods, all with the same result: the register page was still accessible.

Need some help, as I got stuck with this problem.

Here's part of my code (the beforeFilter() in the UsersController class; register() would be the action from within this controller):

function beforeFilter(){
    parent::beforeFilter();

    $this->Auth->allow("register");

    if($this->Auth->user()){//if user is logged in...
        $this->Auth->deny("register");//...deny his access to register and login page
    }
}
A: 

Try to do it this way:

function beforeFilter() {
    $this->Auth->authorize = 'controller';
    $this->Auth->allow('register');
}

function isAuthorized() {
    if ($this->Auth->user()) {
        $this->Auth->deny('register');
    }
}

UPDATE: Probably, the cleaner solution would be

function beforeFilter() {
    $this->Auth->authorize = 'controller';
    if(is_null($this->Auth->user())) {
        $this->Auth->allow('register');
    }
}
bancer
Tried that also. No change, unfortunately.
linkyndy
Check out this question http://stackoverflow.com/questions/768785/cakephp-isauthorized-not-being-called
bancer
Looked over that one, and it was of no help. I already have the parent::beforeFilter() and the isAuthorized() method is called. Any other ideas, as I'm starting to lose my temper over this problem...
linkyndy
Put the code above into app_controller.php and comment beforeFilter() method in UsersController.
bancer
Done this and only half of the problem has been resolved. That is, only the register page is available when not logged (good) and still the register page is available when logged (bad).
linkyndy
More info: If I add an output message in the method above, so as the code looks like this: $this->Auth->allow('register'); if($this->Auth->user()){ $this->Auth->deny("register"); $this->Session->setFlash("authed user"); } then the "authed user" is shown, but the deny() method has no effect.
linkyndy
Try to replace `$this->Auth->deny("register");` by `$this->Auth->allowedActions = array();`
bancer
Or you can even do `function beforeFilter() {$this->Auth->authorize = 'controller'; if(!$this->Auth->user()) {$this->Auth->allow('register');}}`
bancer
Or `function beforeFilter() {$this->Auth->authorize = 'controller'; if(is_null($this->Auth->user())) {$this->Auth->allow('register');}}`
bancer
The thing is that that method calls both when the user is authenticated or not (the beforeFilter() of the UsersController). What you've said works for when the user is not authed. But when the user is authed, you don't have any deny on the register action.
linkyndy
Have you tested the code I wrote?
bancer
The last ones you wrote don't work. And that is somehow logic, because the isAuthorized() method is being called when accessing an action AFTER the authentication check has been made. So then, it's obvious that $this->Auth->user()) in the isAuthorized() method always returns true. Other than this, I answered in the reply above, that if I am already logged in, by default I have access to all cotroller actions; so, your code above works only for when the user is not logged. This being said, am I missing something from what you've said?
linkyndy
If so, please submit another reply to my question in which you show me exactly what you meant to say. Thanks for your help so far :)
linkyndy
+1  A: 
function register()
{
    if ($this->Auth->user())
    {
        $this->redirect('someOtherPage');
        // or exit;
    }
    //other stuff
}
Leo
Thanks for your answer. It works, but I was looking after a more elegant solution. I don't want to mess with all controller actions when I want to allow/deny permission. I'd prefer having defined everything in a beforeFilter() method, using the allow() and deny() methods Auth provides.
linkyndy
My understanding was that this was for just one action/page. If you require more control over more pages, you should look into ACL. It really isn't that difficult once you get your head round it.
Leo
I find sometimes it is better to go with what works and get on with something else than to pursue a more elegant solution. However, I do recall having problems with the deny() function i.e. it didn't work.
Leo
The more I look at it, the more I disagree that doing it in a before filter is an elegant solution - every action on that controller will be tested against that conditional when you only want to filter one action. I argue that my solution is the elegant one especially as it works ;)
Leo
+1 I, too, think *this* is the most elegant solution. You just need to switch your thinking from "I want to **deny** the user access to the register action if he's already registered" to "In case the user is already registered, we'll just throw him back to the homepage." It makes more sense for the user too. *Denying* an action means the user will be redirected to the login page, which doesn't make any sense at all, since the user is already logged in.
deceze
I don't want to use ACL because I get complicated too much. I need only a few restrictions of access. With elegant, I was referring to do all the permission work in the beforeFilter(); That is, maybe after a while, I would like to add some actions to the allow/deny array (e.g.: beside register, say I would like to add login; this means $this->Auth->allow("register", "login"); if($this->Auth->user()) $this->Auth->deny("register", "login");This would be more 'elegant', as I would do all the "job" in only one method. Hope you understood now my point.
linkyndy
Anyway, what's the point of the allow/deny methods not working? What's the catch? As I said, the user authentication check passes, and if I add some echo string right before/after $this->Auth->deny("register"); it really works. So then why is Cake "ignoring" that line? (to mention, I tried both variants, the one displayed above and the one with the isAuthorized() method when ->authorize is set to "controller").
linkyndy