Changeset View
Changeset View
Standalone View
Standalone View
src/applications/auth/engine/PhabricatorAuthSessionEngine.php
| <?php | <?php | ||||
| /** | /** | ||||
| * | * | ||||
| * @task use Using Sessions | * @task use Using Sessions | ||||
| * @task new Creating Sessions | * @task new Creating Sessions | ||||
| * @task hisec High Security | * @task hisec High Security | ||||
| * @task partial Partial Sessions | * @task partial Partial Sessions | ||||
| * @task onetime One Time Login URIs | * @task onetime One Time Login URIs | ||||
| * @task cache User Cache | |||||
| */ | */ | ||||
| final class PhabricatorAuthSessionEngine extends Phobject { | final class PhabricatorAuthSessionEngine extends Phobject { | ||||
| /** | /** | ||||
| * Session issued to normal users after they login through a standard channel. | * Session issued to normal users after they login through a standard channel. | ||||
| * Associates the client with a standard user identity. | * Associates the client with a standard user identity. | ||||
| */ | */ | ||||
| const KIND_USER = 'U'; | const KIND_USER = 'U'; | ||||
| ▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | switch ($session_kind) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| $session_table = new PhabricatorAuthSession(); | $session_table = new PhabricatorAuthSession(); | ||||
| $user_table = new PhabricatorUser(); | $user_table = new PhabricatorUser(); | ||||
| $conn_r = $session_table->establishConnection('r'); | $conn_r = $session_table->establishConnection('r'); | ||||
| $session_key = PhabricatorHash::digest($session_token); | $session_key = PhabricatorHash::digest($session_token); | ||||
| // NOTE: We're being clever here because this happens on every page load, | $cache_parts = $this->getUserCacheQueryParts($conn_r); | ||||
| // and by joining we can save a query. This might be getting too clever | list($cache_selects, $cache_joins, $cache_map) = $cache_parts; | ||||
| // for its own good, though... | |||||
epriestley: I removed this comment because I have made the query even //more// clever. | |||||
| $info = queryfx_one( | $info = queryfx_one( | ||||
| $conn_r, | $conn_r, | ||||
| 'SELECT | 'SELECT | ||||
| s.id AS s_id, | s.id AS s_id, | ||||
| s.sessionExpires AS s_sessionExpires, | s.sessionExpires AS s_sessionExpires, | ||||
| s.sessionStart AS s_sessionStart, | s.sessionStart AS s_sessionStart, | ||||
| s.highSecurityUntil AS s_highSecurityUntil, | s.highSecurityUntil AS s_highSecurityUntil, | ||||
| s.isPartial AS s_isPartial, | s.isPartial AS s_isPartial, | ||||
| s.signedLegalpadDocuments as s_signedLegalpadDocuments, | s.signedLegalpadDocuments as s_signedLegalpadDocuments, | ||||
| u.* | u.* | ||||
| %Q | |||||
| FROM %T u JOIN %T s ON u.phid = s.userPHID | FROM %T u JOIN %T s ON u.phid = s.userPHID | ||||
| AND s.type = %s AND s.sessionKey = %s', | AND s.type = %s AND s.sessionKey = %s %Q', | ||||
| $cache_selects, | |||||
| $user_table->getTableName(), | $user_table->getTableName(), | ||||
| $session_table->getTableName(), | $session_table->getTableName(), | ||||
| $session_type, | $session_type, | ||||
| $session_key); | $session_key, | ||||
| $cache_joins); | |||||
| if (!$info) { | if (!$info) { | ||||
| return null; | return null; | ||||
| } | } | ||||
| $session_dict = array( | $session_dict = array( | ||||
| 'userPHID' => $info['phid'], | 'userPHID' => $info['phid'], | ||||
| 'sessionKey' => $session_key, | 'sessionKey' => $session_key, | ||||
| 'type' => $session_type, | 'type' => $session_type, | ||||
| ); | ); | ||||
| $cache_raw = array_fill_keys($cache_map, null); | |||||
| foreach ($info as $key => $value) { | foreach ($info as $key => $value) { | ||||
| if (strncmp($key, 's_', 2) === 0) { | if (strncmp($key, 's_', 2) === 0) { | ||||
| unset($info[$key]); | unset($info[$key]); | ||||
| $session_dict[substr($key, 2)] = $value; | $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); | $user = $user_table->loadFromArray($info); | ||||
| $user->attachRawCacheData($cache_raw); | |||||
| switch ($session_type) { | switch ($session_type) { | ||||
| case PhabricatorAuthSession::TYPE_WEB: | case PhabricatorAuthSession::TYPE_WEB: | ||||
| // Explicitly prevent bots and mailing lists from establishing web | // Explicitly prevent bots and mailing lists from establishing web | ||||
| // sessions. It's normally impossible to attach authentication to these | // sessions. It's normally impossible to attach authentication to these | ||||
| // accounts, and likewise impossible to generate sessions, but it's | // accounts, and likewise impossible to generate sessions, but it's | ||||
| // technically possible that a session could exist in the database. If | // technically possible that a session could exist in the database. If | ||||
| // one does somehow, refuse to load it. | // one does somehow, refuse to load it. | ||||
| if (!$user->canEstablishWebSessions()) { | if (!$user->canEstablishWebSessions()) { | ||||
| ▲ Show 20 Lines • Show All 567 Lines • ▼ Show 20 Lines | private function getOneTimeLoginKeyHash( | ||||
| if ($email) { | if ($email) { | ||||
| $parts[] = $email->getVerificationCode(); | $parts[] = $email->getVerificationCode(); | ||||
| } | } | ||||
| return PhabricatorHash::digest(implode(':', $parts)); | return PhabricatorHash::digest(implode(':', $parts)); | ||||
| } | } | ||||
| /* -( User Cache )--------------------------------------------------------- */ | |||||
| /** | |||||
| * @task cache | |||||
| */ | |||||
| private function getUserCacheQueryParts(AphrontDatabaseConnection $conn) { | |||||
| $cache_selects = array(); | |||||
| $cache_joins = array(); | |||||
| $cache_map = array(); | |||||
| $keys = array(); | |||||
| $cache_types = PhabricatorUserCacheType::getAllCacheTypes(); | |||||
| foreach ($cache_types as $cache_type) { | |||||
| foreach ($cache_type->getAutoloadKeys() as $autoload_key) { | |||||
| $keys[] = $autoload_key; | |||||
| } | |||||
| } | |||||
| $cache_table = id(new PhabricatorUserCache())->getTableName(); | |||||
| $cache_idx = 1; | |||||
| foreach ($keys as $key) { | |||||
| $join_as = 'ucache_'.$cache_idx; | |||||
| $select_as = 'ucache_'.$cache_idx.'_v'; | |||||
| $cache_selects[] = qsprintf( | |||||
| $conn, | |||||
| '%T.cacheData %T', | |||||
| $join_as, | |||||
| $select_as); | |||||
| $cache_joins[] = qsprintf( | |||||
| $conn, | |||||
| 'LEFT JOIN %T AS %T ON u.phid = %T.userPHID | |||||
| AND %T.cacheIndex = %s', | |||||
| $cache_table, | |||||
| $join_as, | |||||
| $join_as, | |||||
| $join_as, | |||||
| PhabricatorHash::digestForIndex($key)); | |||||
| $cache_map[$select_as] = $key; | |||||
| $cache_idx++; | |||||
| } | |||||
| if ($cache_selects) { | |||||
| $cache_selects = ', '.implode(', ', $cache_selects); | |||||
| } else { | |||||
| $cache_selects = ''; | |||||
| } | |||||
| if ($cache_joins) { | |||||
| $cache_joins = implode(' ', $cache_joins); | |||||
| } else { | |||||
| $cache_joins = ''; | |||||
| } | |||||
| return array($cache_selects, $cache_joins, $cache_map); | |||||
| } | |||||
| } | } | ||||
I removed this comment because I have made the query even more clever.