phpauthenticationsymfony1symfony-1.4sfguard

How to override sfDoctrineGuard validators in order to allow login based on credentials


As title said I need to modify sfDoctrineGuard validators to allow login based on credentials. I've this users and credentials:

username           credential
administrator      super admin
user1              public_access
user2              
user3              public_access

I've also two applications: admin and site. So based on this data I need to achieve this:

Any help?


Solution

  • First you should copy the sfGuardValidatorUser class from plugins/sfDoctrineGuardPlugin/lib/validator into lib/validator and clear the cache.

    Than modify it's doClean method to check if a user has the required permission.

    class sfGuardValidatorUser extends sfValidatorBase
    {
      // ...
    
      protected function doClean($values)
      {
        $username = isset($values[$this->getOption('username_field')]) ? $values[$this->getOption('username_field')] : '';
        $password = isset($values[$this->getOption('password_field')]) ? $values[$this->getOption('password_field')] : '';
    
        $callable = sfConfig::get('app_sf_guard_plugin_retrieve_by_username_callable');
    
        if ($username && $callable)
        {
          $user = call_user_func_array($callable, array($username));
        }
        elseif ($username)
        {
          $user = $this->getTable()->retrieveByUsername($username);
        }
        else
        {
          $user = false;
        }
    
        /** @var $user sfGuardUser */
        if ($user && $user->isAllowedToLogIn(sfConfig::get('sf_app'), $password))
        {
          return array_merge($values, array('user' => $user));
        }
    
        if ($this->getOption('throw_global_error'))
        {
          throw new sfValidatorError($this, 'invalid');
        }
    
        throw new sfValidatorErrorSchema($this, array($this->getOption('username_field') => new sfValidatorError($this, 'invalid')));
      }
    
      // ...
    }
    

    Than add isAllowedToLogIn method to the sfGuardUser class:

    public function isAllowedToLogIn($app, $password)
    {
      if ('admin' == $app)
      {
        $hasPermission = $this->getIsSuperAdmin() || $this->hasPermission('admin');
      }
      elseif ('site' == $app)
      {
        $hasPermission = $this->hasPermission('public_access');
      }
      else
      {
        $hasPermission = true;
      }
    
      return $this->getIsActive() && $this->checkPassword($password) && $hasPermission;
    }
    

    Modify the permission check part if needed.

    I recommend to add an admin group and permission as well and if you can don't use the is_super_admin flag.