16

I would like to know how to deal with only ONE authentification process and "users" in multiple tables. I have 4 Users table: users, admins, artists, teamadmins which all have specific fields, but I would like all of these users to be able to connect via only one form on the homepage, and being redirected after that to their specific dashboards.

I think the redirections shouldn't be a problem, and some routes added should work, but I really don't know where to look/start to ake this all possible.

Cheers,
Nicolas.

EDIT: here's the final solution (thanks to deizel)

App::import('Component', 'Auth');
class SiteAuthComponent extends AuthComponent {

    function identify($user = null, $conditions = null) {
        $models = array('User', 'Admin', 'Artist');
        foreach ($models as $model) {
            $this->userModel = $model; // switch model
            $this->params["data"][$model] = $this->params["data"]["User"]; // switch model in params/data too
            $result = parent::identify($this->params["data"][$model], $conditions); // let cake do its thing
            if ($result) {
                return $result; // login success
            }
        }
        return null; // login failure
    }
}
Nicolas
  • 2,754
  • 6
  • 26
  • 41
  • why didn't you created a singe table for users. You could have easily defined a separate column in the table for 'type' of user. This way you won't need to have 4 different models and controllers for those users ? – Gaurav Sharma Jun 04 '10 at 12:35
  • 2
    @Gaurav: Hi. I didn't do that first of all because I did the analysis BEFORE choosing the framework, and second of all because there are relations between artists and teamartists, so in an analysis view you need to define 2 tables. The question here is not about changing the schema (I've already thought of that, with null columns) but trying to find a PHP solution to my schema. Cheers. – Nicolas Jun 04 '10 at 13:20
  • I am trying to achieve a very similar functionality, where each user type has a different dashboard. I was wondering where did you put that code to extend the Auth component? And also, how did you achieve the redirection? Setting the redirect variable in each controller? Thanks – AlexBrand Jul 29 '11 at 19:53
  • You just have to create a new component (called `SiteAuthComponent` in my example), add it to your app_controller in your $components array, then instead of using `$this->Auth->function()` use `$this->SiteAuth->function()` everywhere you need to make a call to the Auth component in your website. Good luck! – Nicolas Aug 02 '11 at 14:29
  • 3
    CakePHP 2.x solution: http://stackoverflow.com/questions/11135066/cakephp-2-seperate-login-tables – 472084 Jun 23 '12 at 15:25

4 Answers4

20

CakePHP's AuthComponent only supports authentication against a single "User" model at a time. The model is chosen by setting the Auth::userModel property, but it only accepts a string and not an array of models.

You can switch the userModel on the fly with the following code, but this requires you to know in advance which model to switch to (eg. your users have to choose their account type from a dropdown):

public function beforeFilter() {
    if (isset($this->data['User']['model'])) {
        $this->Auth->userModel = $this->data['User']['model'];
    }
}

You can likely extend the core AuthComponent to add the functionality you want by overwriting the AuthComponent::identify() method so it loops over and attempts authentication with each model:

App::import('Component', 'AuthComponent');
class AppAuthComponent extends AuthComponent {

    function identify($user = null, $conditions = null) {
        $models = array('User', 'Admin', 'Artist', 'TeamAdmin');
        foreach ($models as $model) {
            $this->userModel = $model; // switch model
            $result = parent::identify($user, $conditions); // let cake do it's thing
            if ($result) {
                return $result; // login success
            }
        }
        return null; // login failure
    }
}

You will have to replace occurrences of Auth in your application with AppAuth to use your extended AuthComponent, unless you use this trick.

deizel.
  • 11,042
  • 1
  • 39
  • 50
  • Thank you for your detailed answer. I'll come back to you and validate your answer as soon as it is working(if not I'll post comments, but it looks promising). Cheers. – Nicolas Jun 04 '10 at 13:24
  • So I choose the second solution, and it works perfectly with your code and a line I had to add : `$this->params["data"][$model] = $this->params["data"]["User"];` . Thanks! – Nicolas Jul 01 '10 at 14:37
  • Hi, @Nicolas, Can you get me a modified code so that I can refer it properly, here I am finding difficulty where you added the line exactly as I am learning cake currently, Thanks! – Sagar Guhe Oct 14 '14 at 06:51
  • @Nicolas ok fine you edited the question with a final solution. – Sagar Guhe Oct 14 '14 at 07:44
2

While annoying, I think the best solution is probably using Cake's built in ACL support (see http://book.cakephp.org/2.0/en/tutorials-and-examples/simple-acl-controlled-application/simple-acl-controlled-application.html).

If you do authentication the way you're talking about, you have to keep track of permissions in your controller code, checking to see what the userModel is. If you use an access control list, the permission tree will already exist in the database, which should simplify your code a great deal, and make it more modular.

It also means restructuring your data model to have a single users table and groups table instead of entity classes for each type of user.

I just went through the process of doing this myself... :(

Sadikhasan
  • 18,365
  • 21
  • 80
  • 122
mikermcneil
  • 11,141
  • 5
  • 43
  • 70
0

this is also a possibility

public function beforeFilter() {
    parent::beforeFilter();
    $this->Auth->authenticate = array(
        AuthComponent::ALL => array('userModel' => 'AnotherModel'),
        'Form',
        'Basic'
    );
}
rajesh_kw
  • 1,572
  • 16
  • 14
  • This does not allow a second auth user model, it simply changes it from the default expected "Users" table. – Zetaphor Sep 04 '15 at 21:05
0

Here is the final solution as suggested by deizel and modified by Nicolas:

App::import('Component', 'Auth');
class SiteAuthComponent extends AuthComponent {

    function identify($user = null, $conditions = null) {
        $models = array('User', 'Admin', 'Artist');
        foreach ($models as $model) {
            $this->userModel = $model; // switch model
            $this->params["data"][$model] = $this->params["data"]["User"]; // switch model in params/data too
            $result = parent::identify($this->params["data"][$model], $conditions); // let cake do its thing
            if ($result) {
                return $result; // login success
            }
        }
        return null; // login failure
    }
}
Sagar Guhe
  • 1,041
  • 1
  • 11
  • 35