Search code examples
phpauthenticationsessioncakephp

Cakephp: choose which data to save after login


I cannot understand how to choose which user data to save after login. I have noticed that I can only change the recursivity of the model, but I cannot choose individual fields to use.

For example, normally Cakephp saves in session all user fields except the password, even the data that I don't need and I do not want stored. If I increase the recursion, Cakephp saves all the fields of related models.

Is there a way as for the "fields" parameter of the Model find method?

I know that after login I can recover the data that I miss and add them in session, merging to those already stored, but I want to avoid making another query and find a more elegant solution, if it exists.

Thanks.


Solution

  • As of Cake 2.2, you can add a contain key to your authentication options to pull related data. Since the contain key accepts a fields key, you can restrict the fields there:

    public $components = array(
      'Auth' => array(
        'authenticate' => array(
          'Form' => array(
            'contain' => array(
              'Profile' => array(
                'fields' => array('name', 'birthdate')
              )
            )
          )
        )
      )
    );
    

    If you want to change the fields the user model searches for, you can extend the authentication object you're using. Generally the users table contains a minimal amount of information, so this isn't usually necessary.

    However, I'll give an example anyway. We'll use the FormAuthenticate object here, and use most of the _findUser method code from the BaseAuthenticate class. This is the function that Cake's authentication system uses to identify the user.

    App::uses('FormAuthenticate', 'Controller/Component/Auth');
    class MyFormAuthenticate extends FormAuthenticate {
    
      // overrides BaseAuthenticate::_findUser()
      protected function _findUser($username, $password) {
        $userModel = $this->settings['userModel'];
        list($plugin, $model) = pluginSplit($userModel);
        $fields = $this->settings['fields'];
    
        $conditions = array(
          $model . '.' . $fields['username'] => $username,
          $model . '.' . $fields['password'] => $this->_password($password),
        );
        if (!empty($this->settings['scope'])) {
          $conditions = array_merge($conditions, $this->settings['scope']);
        }
        $result = ClassRegistry::init($userModel)->find('first', array(
          // below is the only line added
          'fields' => $this->settings['findFields'],
          'conditions' => $conditions,
          'recursive' => (int)$this->settings['recursive']
        ));
        if (empty($result) || empty($result[$model])) {
          return false;
        }
        unset($result[$model][$fields['password']]);
        return $result[$model];
      }
    }
    

    Then use that authentication and pass our new setting:

    public $components = array(
      'Auth' => array(
        'authenticate' => array(
          'MyForm' => array(
            'findFields' => array('username', 'email'),
            'contain' => array(
              'Profile' => array(
                'fields' => array('name', 'birthdate')
              )
            )
          )
        )
      )
    );