2016-07-06 4 views
1

私が作成したマルチサイトプラットフォームでFOS User Bundleを使用しています。 私は、ユーザーの役割(管理者の方のより強い正規表現チェック)に応じてパスワードチェックのカスタム制約を設定する必要があります。Symfony2 FOSユーザパスワードチェックコールバック制約

これを安全に行うにはどのように、どこで行えますか? Assert/Constraintは、ユーザのエンティティでは使用できません。たとえば、ロールに関する異なるチェックを許可しないthis answerです。あなたの答えのための

おかげで、

ニコラス

+0

ユーザーが登録したことを意味しますか?その場合、私は単にregistrationControllerのregisterActionを上書きします。 –

+0

あなたの質問をありがとう:私はどこでも(登録、パスワードリセット、BOユーザープロフィールの更新...)、それは私が制約を考えた理由です。 – nbonniot

+0

アクションを上書きすることが最後に行うことです。他のどこかでロジックを実装できない限り(モデル、ビュー、制約、リスナー)、それをしないでください。 –

答えて

2

カスタム検証制約を作成し、クラスではなく、プロパティに添付できます。 PasswordForRoleRegex

namespace Acme\UserBundle\Validator\Constraints; 

/** 
* @Annotation 
* @Target({"CLASS", "ANNOTATION"}) 
*/ 
class PasswordForRoleRegex extends Constraint 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function getTargets() 
    { 
     return self::CLASS_CONSTRAINT; 
    } 
} 

アクメ\ UserBundle \バリ\制約あなたが、その後のようなあなたの検証に使用することができます\ PasswordForRoleRegexValidator

namespace Acme\UserBundle\Validator\Constraints; 

class PasswordForRoleRegexValidator extends ConstraintValidator 
{ 
    const REGEX_SUPER_ADMIN = '/..../'; 
    // or an actual message if you don't use translations 
    const MESSAGE_SUPER_ADMIN = 'acme.user.password.regex.super_admin'; 

    const REGEX_ADMIN = '/..../'; 
    const MESSAGE_ADMIN = 'acme.user.password.regex.admin'; 

    /// and so on 

    const REGEX_NORMAL_USER = '/..../'; 
    const MESSAGE_NORMAL_USER = 'acme.user.password.regex.normal_user'; 


    public function validate($user, Constraint $constraint) 
    { 
     if (!$constraint instanceof PasswordForRoleRegex) { 
      throw new UnexpectedTypeException($constraint, PasswordForRoleRegex::class); 
     } 

     if (!$user instanceof UserInterface) { 
      throw new UnexpectedTypeException($user, UserInterface::class); 
     } 

     if (null === $password = $user->getPlainPassword()) { 
      return; 
     } 

     if (preg_match($this->getPasswordRegexForUserRole($user), $password) { 
      return; 
     } 

     $this->context->buildViolation($this->getErrorMessageForUserRole($user)) 
      ->atPath('plainPassword') 
      ->addViolation(); 
    } 

    /** 
    * @param UserInterface $user 
    * @return string 
    */ 
    private function getPasswordRegexForUserRole(UserInterface $user) 
    { 
     if ($user->hasRole('ROLE_SUPER_ADMIN')) { 
      return self::REGEX_SUPER_ADMIN; 
     } 

     if ($user->hasRole('ROLE_ADMIN')) { 
      return self::REGEX_ADMIN; 
     } 

     // and so on 

     return self::REGEX_NORMAL_USER; 
    } 

    /** 
    * @param UserInterface $user 
    * @return string 
    */ 
    private function getErrorMessageForUserRole(UserInterface $user) 
    { 
     if ($user->hasRole('ROLE_SUPER_ADMIN')) { 
      return self::MESSAGE_SUPER_ADMIN; 
     } 

     if ($user->hasRole('ROLE_ADMIN')) { 
      return self::MESSAGE_ADMIN; 
     } 

     // and so on 

     return self::MESSAGE_NORMAL_USER; 
    } 
} 

\

アクメ\ UserBundle \バリ\制約。 ..

アクメ\ UserBundle \モデル\ユーザー

namespace Acme\UserBundle\Model; 

use Acme\UserBundle\Validator\Constraints\PasswordForRoleRegex; 
use FOS\UserBundle\Model\User as BaseUser; 

/** 
* @PasswordForRoleRegex(groups={"Registration", "ChangePassword", ....}) 
*/ 
class User extends BaseUser 
{ 
    //... 
} 

または@ ..

AcmeUserBundle /リソース/設定/ validation.yml

Acme\UserBundle\Model\User: 
    properties: 
     Acme\UserBundle\Validator\Constraints\PasswordForRoleRegex: 
      groups: ["Registration", "ChangePassword", ....] 

またはXML私はできないこと気にする。

私はこれがうまくいくかなり確信しているが、それは100%ではないかもしれないので、それはテストされていません。

関連する問題