public final function willBeginExecution()
 {
     $request = $this->getRequest();
     $user = new PhabricatorUser();
     $phusr = $request->getCookie('phusr');
     $phsid = $request->getCookie('phsid');
     if ($phusr && $phsid) {
         $info = queryfx_one($user->establishConnection('r'), 'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
       AND s.type LIKE %> AND s.sessionKey = %s', $user->getTableName(), 'phabricator_session', 'web-', $phsid);
         if ($info) {
             $user->loadFromArray($info);
         }
     }
     $request->setUser($user);
     if ($user->getIsDisabled() && $this->shouldRequireEnabledUser()) {
         $disabled_user_controller = newv('PhabricatorDisabledUserController', array($request));
         return $this->delegateToController($disabled_user_controller);
     }
     if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) {
         if ($user->getConsoleEnabled() || PhabricatorEnv::getEnvConfig('darkconsole.always-on')) {
             $console = new DarkConsoleCore();
             $request->getApplicationConfiguration()->setConsole($console);
         }
     }
     if ($this->shouldRequireLogin() && !$user->getPHID()) {
         $login_controller = newv('PhabricatorLoginController', array($request));
         return $this->delegateToController($login_controller);
     }
     if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) {
         return new Aphront403Response();
     }
 }
 public final function willBeginExecution()
 {
     $request = $this->getRequest();
     $user = new PhabricatorUser();
     $phusr = $request->getCookie('phusr');
     $phsid = $request->getCookie('phsid');
     if (strlen($phusr) && $phsid) {
         $info = queryfx_one($user->establishConnection('r'), 'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID
       AND s.type LIKE %> AND s.sessionKey = %s', $user->getTableName(), 'phabricator_session', 'web-', $phsid);
         if ($info) {
             $user->loadFromArray($info);
         }
     }
     $translation = $user->getTranslation();
     if ($translation && $translation != PhabricatorEnv::getEnvConfig('translation.provider')) {
         $translation = newv($translation, array());
         PhutilTranslator::getInstance()->setLanguage($translation->getLanguage())->addTranslations($translation->getTranslations());
     }
     $request->setUser($user);
     if ($user->getIsDisabled() && $this->shouldRequireEnabledUser()) {
         $disabled_user_controller = new PhabricatorDisabledUserController($request);
         return $this->delegateToController($disabled_user_controller);
     }
     $event = new PhabricatorEvent(PhabricatorEventType::TYPE_CONTROLLER_CHECKREQUEST, array('request' => $request, 'controller' => get_class($this)));
     $event->setUser($user);
     PhutilEventEngine::dispatchEvent($event);
     $checker_controller = $event->getValue('controller');
     if ($checker_controller != get_class($this)) {
         return $this->delegateToController($checker_controller);
     }
     if (PhabricatorEnv::getEnvConfig('darkconsole.enabled')) {
         if ($user->getConsoleEnabled() || PhabricatorEnv::getEnvConfig('darkconsole.always-on')) {
             $console = new DarkConsoleCore();
             $request->getApplicationConfiguration()->setConsole($console);
         }
     }
     if ($this->shouldRequireLogin() && !$user->getPHID()) {
         $login_controller = new PhabricatorLoginController($request);
         return $this->delegateToController($login_controller);
     }
     if ($this->shouldRequireEmailVerification()) {
         $email = $user->loadPrimaryEmail();
         if (!$email) {
             throw new Exception("No primary email address associated with this account!");
         }
         if (!$email->getIsVerified()) {
             $verify_controller = new PhabricatorMustVerifyEmailController($request);
             return $this->delegateToController($verify_controller);
         }
     }
     if ($this->shouldRequireAdmin() && !$user->getIsAdmin()) {
         return new Aphront403Response();
     }
 }
 /**
  * Load the user identity associated with a session of a given type,
  * identified by token.
  *
  * When the user presents a session token to an API, this method verifies
  * it is of the correct type and loads the corresponding identity if the
  * session exists and is valid.
  *
  * NOTE: `$session_type` is the type of session that is required by the
  * loading context. This prevents use of a Conduit sesssion as a Web
  * session, for example.
  *
  * @param const The type of session to load.
  * @param string The session token.
  * @return PhabricatorUser|null
  * @task use
  */
 public function loadUserForSession($session_type, $session_token)
 {
     $session_kind = self::getSessionKindFromToken($session_token);
     switch ($session_kind) {
         case self::KIND_ANONYMOUS:
             // Don't bother trying to load a user for an anonymous session, since
             // neither the session nor the user exist.
             return null;
         case self::KIND_UNKNOWN:
             // If we don't know what kind of session this is, don't go looking for
             // it.
             return null;
         case self::KIND_USER:
             break;
         case self::KIND_EXTERNAL:
             // TODO: Implement these (T4310).
             return null;
     }
     $session_table = new PhabricatorAuthSession();
     $user_table = new PhabricatorUser();
     $conn_r = $session_table->establishConnection('r');
     $session_key = PhabricatorHash::digest($session_token);
     $cache_parts = $this->getUserCacheQueryParts($conn_r);
     list($cache_selects, $cache_joins, $cache_map, $types_map) = $cache_parts;
     $info = queryfx_one($conn_r, 'SELECT
       s.id AS s_id,
       s.sessionExpires AS s_sessionExpires,
       s.sessionStart AS s_sessionStart,
       s.highSecurityUntil AS s_highSecurityUntil,
       s.isPartial AS s_isPartial,
       s.signedLegalpadDocuments as s_signedLegalpadDocuments,
       u.*
       %Q
     FROM %T u JOIN %T s ON u.phid = s.userPHID
     AND s.type = %s AND s.sessionKey = %s %Q', $cache_selects, $user_table->getTableName(), $session_table->getTableName(), $session_type, $session_key, $cache_joins);
     if (!$info) {
         return null;
     }
     $session_dict = array('userPHID' => $info['phid'], 'sessionKey' => $session_key, 'type' => $session_type);
     $cache_raw = array_fill_keys($cache_map, null);
     foreach ($info as $key => $value) {
         if (strncmp($key, 's_', 2) === 0) {
             unset($info[$key]);
             $session_dict[substr($key, 2)] = $value;
             continue;
         }
         if (isset($cache_map[$key])) {
             unset($info[$key]);
             $cache_raw[$cache_map[$key]] = $value;
             continue;
         }
     }
     $user = $user_table->loadFromArray($info);
     $cache_raw = $this->filterRawCacheData($user, $types_map, $cache_raw);
     $user->attachRawCacheData($cache_raw);
     switch ($session_type) {
         case PhabricatorAuthSession::TYPE_WEB:
             // Explicitly prevent bots and mailing lists from establishing web
             // sessions. It's normally impossible to attach authentication to these
             // accounts, and likewise impossible to generate sessions, but it's
             // technically possible that a session could exist in the database. If
             // one does somehow, refuse to load it.
             if (!$user->canEstablishWebSessions()) {
                 return null;
             }
             break;
     }
     $session = id(new PhabricatorAuthSession())->loadFromArray($session_dict);
     $ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
     // If more than 20% of the time on this session has been used, refresh the
     // TTL back up to the full duration. The idea here is that sessions are
     // good forever if used regularly, but get GC'd when they fall out of use.
     // NOTE: If we begin rotating session keys when extending sessions, the
     // CSRF code needs to be updated so CSRF tokens survive session rotation.
     if (time() + 0.8 * $ttl > $session->getSessionExpires()) {
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         $conn_w = $session_table->establishConnection('w');
         queryfx($conn_w, 'UPDATE %T SET sessionExpires = UNIX_TIMESTAMP() + %d WHERE id = %d', $session->getTableName(), $ttl, $session->getID());
         unset($unguarded);
     }
     $user->attachSession($session);
     return $user;
 }
 /**
  * Load the user identity associated with a session of a given type,
  * identified by token.
  *
  * When the user presents a session token to an API, this method verifies
  * it is of the correct type and loads the corresponding identity if the
  * session exists and is valid.
  *
  * NOTE: `$session_type` is the type of session that is required by the
  * loading context. This prevents use of a Conduit sesssion as a Web
  * session, for example.
  *
  * @param const The type of session to load.
  * @param string The session token.
  * @return PhabricatorUser|null
  * @task use
  */
 public function loadUserForSession($session_type, $session_token)
 {
     $session_kind = self::getSessionKindFromToken($session_token);
     switch ($session_kind) {
         case self::KIND_ANONYMOUS:
             // Don't bother trying to load a user for an anonymous session, since
             // neither the session nor the user exist.
             return null;
         case self::KIND_UNKNOWN:
             // If we don't know what kind of session this is, don't go looking for
             // it.
             return null;
         case self::KIND_USER:
             break;
         case self::KIND_EXTERNAL:
             // TODO: Implement these (T4310).
             return null;
     }
     $session_table = new PhabricatorAuthSession();
     $user_table = new PhabricatorUser();
     $conn_r = $session_table->establishConnection('r');
     $session_key = PhabricatorHash::digest($session_token);
     // NOTE: We're being clever here because this happens on every page load,
     // and by joining we can save a query. This might be getting too clever
     // for its own good, though...
     $info = queryfx_one($conn_r, 'SELECT
       s.id AS s_id,
       s.sessionExpires AS s_sessionExpires,
       s.sessionStart AS s_sessionStart,
       s.highSecurityUntil AS s_highSecurityUntil,
       s.isPartial AS s_isPartial,
       u.*
     FROM %T u JOIN %T s ON u.phid = s.userPHID
     AND s.type = %s AND s.sessionKey = %s', $user_table->getTableName(), $session_table->getTableName(), $session_type, $session_key);
     if (!$info) {
         return null;
     }
     $session_dict = array('userPHID' => $info['phid'], 'sessionKey' => $session_key, 'type' => $session_type);
     foreach ($info as $key => $value) {
         if (strncmp($key, 's_', 2) === 0) {
             unset($info[$key]);
             $session_dict[substr($key, 2)] = $value;
         }
     }
     $session = id(new PhabricatorAuthSession())->loadFromArray($session_dict);
     $ttl = PhabricatorAuthSession::getSessionTypeTTL($session_type);
     // If more than 20% of the time on this session has been used, refresh the
     // TTL back up to the full duration. The idea here is that sessions are
     // good forever if used regularly, but get GC'd when they fall out of use.
     // NOTE: If we begin rotating session keys when extending sessions, the
     // CSRF code needs to be updated so CSRF tokens survive session rotation.
     if (time() + 0.8 * $ttl > $session->getSessionExpires()) {
         $unguarded = AphrontWriteGuard::beginScopedUnguardedWrites();
         $conn_w = $session_table->establishConnection('w');
         queryfx($conn_w, 'UPDATE %T SET sessionExpires = UNIX_TIMESTAMP() + %d WHERE id = %d', $session->getTableName(), $ttl, $session->getID());
         unset($unguarded);
     }
     $user = $user_table->loadFromArray($info);
     $user->attachSession($session);
     return $user;
 }