2012-11-06 22 views
8

OWAでユーザーにログインさせるためにHWIOAuthBundleを使用しています。存在しない場合にユーザーを作成するカスタムユーザープロバイダーを作成しました。Symfony2:いくつかのフィールドが見つからない場合、ログイン後にユーザー登録を完了させる

public function loadUserByOAuthUserResponse(UserResponseInterface $response) 
{ 
    $attr = $response->getResponse(); 
    switch($response->getResourceOwner()->getName()) { 
     case 'google': 
      if(!$user = $this->userRepository->findOneByGoogleId($attr['id'])) { 
       if(($user = $this->userRepository->findOneByEmail($attr['email'])) && $attr['verified_email']) { 
        $user->setGoogleId($attr['id']); 
        if(!$user->getFirstname()) { 
         $user->setFirstname($attr['given_name']); 
        } 
        if(!$user->getLastname()) { 
         $user->setLastname($attr['family_name']); 
        } 
        $user->setGoogleName($attr['name']); 
       }else{ 
        $user = new User(); 
        $user->setUsername($this->userRepository->createUsernameByEmail($attr['email'])); 
        $user->setEmail($attr['email']); 
        $user->setFirstname($attr['given_name']); 
        $user->setLastname($attr['family_name']); 
        $user->setPassword(''); 
        $user->setIsActive(true); 
        $user->setGoogleId($attr['id']); 
        $user->setGoogleName($attr['name']); 
        $user->addGroup($this->groupRepository->findOneByRole('ROLE_USER')); 
        $this->entityManager->persist($user); 
       } 
      } 
      break; 
     case 'facebook': 
      if(!$user = $this->userRepository->findOneByFacebookId($attr['id'])) { 
       if(($user = $this->userRepository->findOneByEmail($attr['email'])) && $attr['verified']) { 
        $user->setFacebookId($attr['id']); 
        if(!$user->getFirstname()) { 
         $user->setFirstname($attr['first_name']); 
        } 
        if(!$user->getLastname()) { 
         $user->setLastname($attr['last_name']); 
        } 
        $user->setFacebookUsername($attr['username']); 
       }else{ 
        $user = new User(); 
        $user->setUsername($this->userRepository->createUsernameByEmail($attr['email'])); 
        $user->setEmail($attr['email']); 
        $user->setFirstname($attr['first_name']); 
        $user->setLastname($attr['last_name']); 
        $user->setPassword(''); 
        $user->setIsActive(true); 
        $user->setFacebookId($attr['id']); 
        $user->setFacebookUsername($attr['username']); 
        $user->addGroup($this->groupRepository->findOneByRole('ROLE_USER')); 
        $this->entityManager->persist($user); 
       } 
      } 
      break; 
    } 

    $this->entityManager->flush(); 


    if (null === $user) { 
     throw new AccountNotLinkedException(sprintf("User '%s' not found.", $attr['email'])); 
    } 

    return $user; 
} 

問題は、Twitterユーザーがメールを送信しない、または新しいユーザーが作成される前にいくつかの追加フィールドを追加したいということです。作成する前にユーザーを「完全登録」フォームにリダイレクトする方法はありますか?

リクエストリスナーを追加しようとしました。リクエストごとに、ユーザーがログに記録されている場合はメールがあるかどうかをチェックし、そうでなければcomplete_registrationページにリダイレクトしますが、ユーザーがホームページに行ったり、ログアウトしたり、何か他の人にアクセスしたりする場合は、ユーザーが制限した一部のページにアクセスしようとした場合にのみリダイレクトします。

また、必要な情報をすべて入力するまで作成しないでください。

+0

@elnurあなたは何を編集しましたか? – alex88

+0

最後に編集したタイムスタンプをクリックし、自分自身で確認してください。 –

+0

今日はどんな失礼な答え、悪い気分? – alex88

答えて

6

私が自分で解決策を見つけた、私は手動で新しい例外を作成しましたユーザーが存在するかどうかをチェックするか、新しいユーザーを作成するかどうかを確認するときにカスタムOauthユーザープロバイダが必要なフィールドがないかどうかを確認します。

if (!$user->getEmail()) { 
    $e = new IncompleteUserException("Your account doesn't has a mail set"); 
    $e->setUser($user); 
    throw $e; 
} 
if($error instanceof IncompleteUserException) { 
    $session->set(SecurityContext::AUTHENTICATION_ERROR, $error); 
    return $this->redirect($this->generateUrl('register_complete')); 
} 

そして、それは例外で$ユーザーにフォームにリダイレクトされます:ログインページに私がやるように、ユーザーは、セッション中にその例外で、ログインフォームにリダイレクトされますその場合、不足している情報のみを尋ねて、ユーザーにログインすることができます。

+1

**このソリューションはあまりエレガントではありませんが、動作するはずです。 – mate64

1

sfサイトに移行中に同様の問題が発生しました。移行後、移行されたユーザーはプロフィールを完成させたいが、新しく登録したユーザーはすぐに開始できる。

私はRequestListenerを使用してあなたのアイデアに似ているが、彼のプロフィールの完成なしにユーザーが許可されているページのホワイトリストを追加しました。あなたのプロフィールの完成なしにユーザーがアクセスできるページ数に応じて、ブラックリストの使用を検討することもできます。

特定のフィールドupponの存在がプロファイル完了ページにリダイレクトされていないかどうかを確認しませんでしたが、usersdatabaseを移行するときに役割 "ROLE_MIGRATION"を追加しました。あなたの場合は、oauthを通じてユーザーを作成するときにロールを追加できます。ここで

私の要求リスナーのコードは:で、このように

<?php 

namespace Acme\UserBundle\Exception; 

use Symfony\Component\Security\Core\Exception\AuthenticationException; 
use HWI\Bundle\OAuthBundle\Security\Core\Exception\OAuthAwareExceptionInterface; 

/** 
* IncompleteUserException is thrown when the user isn't fully registered (e.g.: missing some informations). 
* 
* @author Alessandro Tagliapietra http://www.alexnetwork.it/ 
*/ 
class IncompleteUserException extends AuthenticationException implements OAuthAwareExceptionInterface 
{ 
    private $user; 
    private $accessToken; 
    private $resourceOwnerName; 

    /** 
    * {@inheritdoc} 
    */ 
    public function setAccessToken($accessToken) 
    { 
     $this->accessToken = $accessToken; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getAccessToken() 
    { 
     return $this->accessToken; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function getResourceOwnerName() 
    { 
     return $this->resourceOwnerName; 
    } 

    /** 
    * {@inheritdoc} 
    */ 
    public function setResourceOwnerName($resourceOwnerName) 
    { 
     $this->resourceOwnerName = $resourceOwnerName; 
    } 

    public function setUser($user) 
    { 
     $this->user = $user; 
    } 

    public function getUser($user) 
    { 
     return $this->user; 
    } 

    public function serialize() 
    { 
     return serialize(array(
      $this->user, 
      $this->accessToken, 
      $this->resourceOwnerName, 
      parent::serialize(), 
     )); 
    } 

    public function unserialize($str) 
    { 
     list(
      $this->user, 
      $this->accessToken, 
      $this->resourceOwnerName, 
      $parentData 
     ) = unserialize($str); 
     parent::unserialize($parentData); 
    } 
} 

public function onRequest(GetResponseEvent $evt) 
{ 

    if (HttpKernelInterface::MASTER_REQUEST !== $evt->getRequestType()) 
    { 
     return; 
    } 

    $token = $this->securityContext->getToken(); 

    if(!is_object($token)) or not migrating 
    { 
     // user is not logged in 
     return; 
    } 

    $user = $token->getUser(); 

    if(!$user instanceof User || !$user->hasRole('ROLE_MIGRATING')) 
    { 
     // different user class or already migrated 
     return; 
    } 

    $openPaths = array(
     '/start-2.0', 
     '/css', 
     '/js', 
     '/images', 
     '/media', 
     '/geo', 
     '/_wdt', 
     '/logout', or not migrating 
     '/terms', 
     '/contact', 
     '/about', 
     '/locale/set' 
    ); 

    foreach($openPaths as $p) 
    { 
     if(strpos($evt->getRequest()->getPathInfo(),$p)===0) 
     { 
      // path is open for migrating users 
      return; 
     } 
    } 



    header('Location: /start-2.0'); 
    exit; 
} 
+0

私は何か良いことがあれば、ログインは良い方法でなければならないと思う、私は今夜いくつかのテストを行い、ああ明日答えるだろう!あなたのアプローチはパブリックページを追加するたびに変更する必要があるので、私はマイグレーションを実行するだけではなく、返信に感謝します。 – alex88

関連する問題