Add a blanket "will login" event
Summary: Ref T1536. Facebook currently does a check which should be on-login in registration hooks, and this is generally a reasonable hook to provide. The "will login" event allows listeners to reject or modify a login, or just log it or whatever. NOTE: This doesn't cover non-web logins right now -- notably Conduit. That's presumably fine. (This can't land for a while, it depends on about 10 uncommitted revisions.) Test Plan: Logged out and in again. Reviewers: wez, btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1536 Differential Revision: https://secure.phabricator.com/D6202
This commit is contained in:
		| @@ -29,17 +29,54 @@ abstract class PhabricatorAuthController extends PhabricatorController { | |||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected function establishWebSession(PhabricatorUser $user) { |   /** | ||||||
|     $session_key = $user->establishSession('web'); |    * Log a user into a web session and return an @{class:AphrontResponse} which | ||||||
|  |    * corresponds to continuing the login process. | ||||||
|  |    * | ||||||
|  |    * Normally, this is a redirect to the validation controller which makes sure | ||||||
|  |    * the user's cookies are set. However, event listeners can intercept this | ||||||
|  |    * event and do something else if they prefer. | ||||||
|  |    * | ||||||
|  |    * @param   PhabricatorUser   User to log the viewer in as. | ||||||
|  |    * @return  AphrontResponse   Response which continues the login process. | ||||||
|  |    */ | ||||||
|  |   protected function loginUser(PhabricatorUser $user) { | ||||||
|  |  | ||||||
|  |     $response = $this->buildLoginValidateResponse($user); | ||||||
|  |     $session_type = 'web'; | ||||||
|  |  | ||||||
|  |     $event_type = PhabricatorEventType::TYPE_AUTH_WILLLOGINUSER; | ||||||
|  |     $event_data = array( | ||||||
|  |       'user'        => $user, | ||||||
|  |       'type'        => $session_type, | ||||||
|  |       'response'    => $response, | ||||||
|  |       'shouldLogin' => true, | ||||||
|  |     ); | ||||||
|  |  | ||||||
|  |     $event = id(new PhabricatorEvent($event_type, $event_data)) | ||||||
|  |       ->setUser($user); | ||||||
|  |     PhutilEventEngine::dispatchEvent($event); | ||||||
|  |  | ||||||
|  |     $should_login = $event->getValue('shouldLogin'); | ||||||
|  |     if ($should_login) { | ||||||
|  |       $session_key = $user->establishSession($session_type); | ||||||
|  |  | ||||||
|  |       // NOTE: We allow disabled users to login and roadblock them later, so | ||||||
|  |       // there's no check for users being disabled here. | ||||||
|  |  | ||||||
|  |       $request = $this->getRequest(); | ||||||
|  |       $request->setCookie('phusr', $user->getUsername()); | ||||||
|  |       $request->setCookie('phsid', $session_key); | ||||||
|  |  | ||||||
|  |       $this->clearRegistrationCookies(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return $event->getValue('response'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   protected function clearRegistrationCookies() { | ||||||
|     $request = $this->getRequest(); |     $request = $this->getRequest(); | ||||||
|  |  | ||||||
|     // NOTE: We allow disabled users to login and roadblock them later, so |  | ||||||
|     // there's no check for users being disabled here. |  | ||||||
|  |  | ||||||
|     $request->setCookie('phusr', $user->getUsername()); |  | ||||||
|     $request->setCookie('phsid', $session_key); |  | ||||||
|  |  | ||||||
|     // Clear the registration key. |     // Clear the registration key. | ||||||
|     $request->clearCookie('phreg'); |     $request->clearCookie('phreg'); | ||||||
|  |  | ||||||
| @@ -47,11 +84,19 @@ abstract class PhabricatorAuthController extends PhabricatorController { | |||||||
|     $request->clearCookie('phcid'); |     $request->clearCookie('phcid'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   protected function buildLoginValidateResponse(PhabricatorUser $user) { |   private function buildLoginValidateResponse(PhabricatorUser $user) { | ||||||
|     $validate_uri = new PhutilURI($this->getApplicationURI('validate/')); |     $validate_uri = new PhutilURI($this->getApplicationURI('validate/')); | ||||||
|     $validate_uri->setQueryParam('phusr', $user->getUsername()); |     $validate_uri->setQueryParam('phusr', $user->getUsername()); | ||||||
|  |  | ||||||
|     return id(new AphrontRedirectResponse())->setURI((string)$validate_uri); |     return id(new AphrontRedirectResponse())->setURI((string)$validate_uri); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   protected function renderError($message) { | ||||||
|  |     return $this->renderErrorPage( | ||||||
|  |       pht('Authentication Error'), | ||||||
|  |       array( | ||||||
|  |         $message, | ||||||
|  |       )); | ||||||
|  |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -107,9 +107,7 @@ final class PhabricatorAuthLoginController | |||||||
|           'with a valid Phabricator user.')); |           'with a valid Phabricator user.')); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $this->establishWebSession($user); |     return $this->loginUser($user); | ||||||
|  |  | ||||||
|     return $this->buildLoginValidateResponse($user); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function processRegisterUser(PhabricatorExternalAccount $account) { |   private function processRegisterUser(PhabricatorExternalAccount $account) { | ||||||
| @@ -161,7 +159,7 @@ final class PhabricatorAuthLoginController | |||||||
|     return null; |     return null; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function renderError($message) { |   protected function renderError($message) { | ||||||
|     $title = pht('Login Failed'); |     $title = pht('Login Failed'); | ||||||
|  |  | ||||||
|     $view = new AphrontErrorView(); |     $view = new AphrontErrorView(); | ||||||
|   | |||||||
| @@ -205,13 +205,11 @@ final class PhabricatorAuthRegisterController | |||||||
|  |  | ||||||
|           $user->saveTransaction(); |           $user->saveTransaction(); | ||||||
|  |  | ||||||
|           $this->establishWebSession($user); |  | ||||||
|  |  | ||||||
|           if (!$email_obj->getIsVerified()) { |           if (!$email_obj->getIsVerified()) { | ||||||
|             $email_obj->sendVerificationEmail($user); |             $email_obj->sendVerificationEmail($user); | ||||||
|           } |           } | ||||||
|  |  | ||||||
|           return $this->buildLoginValidateResponse($user); |           return $this->loginUser($user); | ||||||
|         } catch (AphrontQueryDuplicateKeyException $exception) { |         } catch (AphrontQueryDuplicateKeyException $exception) { | ||||||
|           $same_username = id(new PhabricatorUser())->loadOneWhere( |           $same_username = id(new PhabricatorUser())->loadOneWhere( | ||||||
|             'userName = %s', |             'userName = %s', | ||||||
| @@ -480,7 +478,7 @@ final class PhabricatorAuthRegisterController | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function renderError($message) { |   protected function renderError($message) { | ||||||
|     return $this->renderErrorPage( |     return $this->renderErrorPage( | ||||||
|       pht('Registration Failed'), |       pht('Registration Failed'), | ||||||
|       array($message)); |       array($message)); | ||||||
|   | |||||||
| @@ -180,7 +180,7 @@ final class PhabricatorAuthStartController | |||||||
|     return id(new AphrontPlainTextResponse())->setContent($message); |     return id(new AphrontPlainTextResponse())->setContent($message); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private function renderError($message) { |   protected function renderError($message) { | ||||||
|     return $this->renderErrorPage( |     return $this->renderErrorPage( | ||||||
|       pht('Authentication Failure'), |       pht('Authentication Failure'), | ||||||
|       array($message)); |       array($message)); | ||||||
|   | |||||||
| @@ -73,8 +73,6 @@ final class PhabricatorEmailTokenController | |||||||
|       $target_email->save(); |       $target_email->save(); | ||||||
|     unset($unguarded); |     unset($unguarded); | ||||||
|  |  | ||||||
|     $this->establishWebSession($target_user); |  | ||||||
|  |  | ||||||
|     $next = '/'; |     $next = '/'; | ||||||
|     if (!PhabricatorEnv::getEnvConfig('auth.password-auth-enabled')) { |     if (!PhabricatorEnv::getEnvConfig('auth.password-auth-enabled')) { | ||||||
|       $panels = id(new PhabricatorSettingsPanelOAuth())->buildPanels(); |       $panels = id(new PhabricatorSettingsPanelOAuth())->buildPanels(); | ||||||
| @@ -95,6 +93,6 @@ final class PhabricatorEmailTokenController | |||||||
|  |  | ||||||
|     $request->setCookie('next_uri', $next); |     $request->setCookie('next_uri', $next); | ||||||
|  |  | ||||||
|     return $this->buildLoginValidateResponse($target_user); |     return $this->loginUser($target_user); | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -90,9 +90,7 @@ final class PhabricatorLDAPLoginController extends PhabricatorAuthController { | |||||||
|  |  | ||||||
|           $this->saveLDAPInfo($ldap_info); |           $this->saveLDAPInfo($ldap_info); | ||||||
|  |  | ||||||
|           $this->establishWebSession($known_user); |           return $this->loginUser($known_user); | ||||||
|  |  | ||||||
|           return $this->buildLoginValidateResponse($known_user); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         $controller = newv('PhabricatorLDAPRegistrationController', |         $controller = newv('PhabricatorLDAPRegistrationController', | ||||||
|   | |||||||
| @@ -138,8 +138,7 @@ final class PhabricatorLoginController | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (!$errors) { |         if (!$errors) { | ||||||
|           $this->establishWebSession($user); |           return $this->loginUser($user); | ||||||
|           return $this->buildLoginValidateResponse($user); |  | ||||||
|         } else { |         } else { | ||||||
|           $log = PhabricatorUserLog::newLog( |           $log = PhabricatorUserLog::newLog( | ||||||
|             null, |             null, | ||||||
|   | |||||||
| @@ -148,9 +148,7 @@ final class PhabricatorOAuthLoginController | |||||||
|  |  | ||||||
|       $this->saveOAuthInfo($oauth_info); |       $this->saveOAuthInfo($oauth_info); | ||||||
|  |  | ||||||
|       $this->establishWebSession($known_user); |       return $this->loginUser($known_user); | ||||||
|  |  | ||||||
|       return $this->buildLoginValidateResponse($known_user); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     $oauth_email = $provider->retrieveUserEmail(); |     $oauth_email = $provider->retrieveUserEmail(); | ||||||
|   | |||||||
| @@ -37,5 +37,6 @@ final class PhabricatorEventType extends PhutilEventType { | |||||||
|  |  | ||||||
|   const TYPE_PEOPLE_DIDRENDERMENU           = 'people.didRenderMenu'; |   const TYPE_PEOPLE_DIDRENDERMENU           = 'people.didRenderMenu'; | ||||||
|   const TYPE_AUTH_WILLREGISTERUSER          = 'auth.willRegisterUser'; |   const TYPE_AUTH_WILLREGISTERUSER          = 'auth.willRegisterUser'; | ||||||
|  |   const TYPE_AUTH_WILLLOGINUSER             = 'auth.willLoginUser'; | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 epriestley
					epriestley