@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add an "active login sessions" table to Settings

Summary: Ref T4310. Ref T3720. Partly, this makes it easier for users to understand login sessions. Partly, it makes it easier for me to make changes to login sessions for T4310 / T3720 without messing anything up.

Test Plan: {F101512}

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3720, T4310

Differential Revision: https://secure.phabricator.com/D7954

+251 -1
+10
src/__phutil_library_map__.php
··· 1202 1202 'PhabricatorAuthProviderPassword' => 'applications/auth/provider/PhabricatorAuthProviderPassword.php', 1203 1203 'PhabricatorAuthProviderPersona' => 'applications/auth/provider/PhabricatorAuthProviderPersona.php', 1204 1204 'PhabricatorAuthRegisterController' => 'applications/auth/controller/PhabricatorAuthRegisterController.php', 1205 + 'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php', 1206 + 'PhabricatorAuthSessionQuery' => 'applications/auth/query/PhabricatorAuthSessionQuery.php', 1205 1207 'PhabricatorAuthStartController' => 'applications/auth/controller/PhabricatorAuthStartController.php', 1206 1208 'PhabricatorAuthUnlinkController' => 'applications/auth/controller/PhabricatorAuthUnlinkController.php', 1207 1209 'PhabricatorAuthValidateController' => 'applications/auth/controller/PhabricatorAuthValidateController.php', ··· 1915 1917 'PhabricatorSettingsPanelPassword' => 'applications/settings/panel/PhabricatorSettingsPanelPassword.php', 1916 1918 'PhabricatorSettingsPanelSSHKeys' => 'applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php', 1917 1919 'PhabricatorSettingsPanelSearchPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelSearchPreferences.php', 1920 + 'PhabricatorSettingsPanelSessions' => 'applications/settings/panel/PhabricatorSettingsPanelSessions.php', 1918 1921 'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php', 1919 1922 'PhabricatorSetupCheckAPC' => 'applications/config/check/PhabricatorSetupCheckAPC.php', 1920 1923 'PhabricatorSetupCheckAuth' => 'applications/config/check/PhabricatorSetupCheckAuth.php', ··· 3760 3763 'PhabricatorAuthProviderPassword' => 'PhabricatorAuthProvider', 3761 3764 'PhabricatorAuthProviderPersona' => 'PhabricatorAuthProvider', 3762 3765 'PhabricatorAuthRegisterController' => 'PhabricatorAuthController', 3766 + 'PhabricatorAuthSession' => 3767 + array( 3768 + 0 => 'PhabricatorAuthDAO', 3769 + 1 => 'PhabricatorPolicyInterface', 3770 + ), 3771 + 'PhabricatorAuthSessionQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 3763 3772 'PhabricatorAuthStartController' => 'PhabricatorAuthController', 3764 3773 'PhabricatorAuthUnlinkController' => 'PhabricatorAuthController', 3765 3774 'PhabricatorAuthValidateController' => 'PhabricatorAuthController', ··· 4548 4557 'PhabricatorSettingsPanelPassword' => 'PhabricatorSettingsPanel', 4549 4558 'PhabricatorSettingsPanelSSHKeys' => 'PhabricatorSettingsPanel', 4550 4559 'PhabricatorSettingsPanelSearchPreferences' => 'PhabricatorSettingsPanel', 4560 + 'PhabricatorSettingsPanelSessions' => 'PhabricatorSettingsPanel', 4551 4561 'PhabricatorSetupCheckAPC' => 'PhabricatorSetupCheck', 4552 4562 'PhabricatorSetupCheckAuth' => 'PhabricatorSetupCheck', 4553 4563 'PhabricatorSetupCheckBaseURI' => 'PhabricatorSetupCheck',
+73
src/applications/auth/query/PhabricatorAuthSessionQuery.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthSessionQuery 4 + extends PhabricatorCursorPagedPolicyAwareQuery { 5 + 6 + private $identityPHIDs; 7 + 8 + public function withIdentityPHIDs(array $identity_phids) { 9 + $this->identityPHIDs = $identity_phids; 10 + return $this; 11 + } 12 + 13 + protected function loadPage() { 14 + $table = new PhabricatorAuthSession(); 15 + $conn_r = $table->establishConnection('r'); 16 + 17 + $data = queryfx_all( 18 + $conn_r, 19 + 'SELECT * FROM %T %Q %Q %Q', 20 + $table->getTableName(), 21 + $this->buildWhereClause($conn_r), 22 + $this->buildOrderClause($conn_r), 23 + $this->buildLimitClause($conn_r)); 24 + 25 + return $table->loadAllFromArray($data); 26 + } 27 + 28 + protected function willFilterPage(array $sessions) { 29 + $identity_phids = mpull($sessions, 'getUserPHID'); 30 + 31 + $identity_objects = id(new PhabricatorObjectQuery()) 32 + ->setViewer($this->getViewer()) 33 + ->setParentQuery($this) 34 + ->withPHIDs($identity_phids) 35 + ->execute(); 36 + $identity_objects = mpull($identity_objects, null, 'getPHID'); 37 + 38 + foreach ($sessions as $key => $session) { 39 + $identity_object = idx($identity_objects, $session->getUserPHID()); 40 + if (!$identity_object) { 41 + unset($sessions[$key]); 42 + } else { 43 + $session->attachIdentityObject($identity_object); 44 + } 45 + } 46 + 47 + return $sessions; 48 + } 49 + 50 + protected function buildWhereClause(AphrontDatabaseConnection $conn_r) { 51 + $where = array(); 52 + 53 + if ($this->identityPHIDs) { 54 + $where[] = qsprintf( 55 + $conn_r, 56 + 'userPHID IN (%Ls)', 57 + $this->identityPHIDs); 58 + } 59 + 60 + $where[] = $this->buildPagingClause($conn_r); 61 + 62 + return $this->formatWhereClause($where); 63 + } 64 + 65 + public function getPagingColumn() { 66 + return 'sessionKey'; 67 + } 68 + 69 + public function getQueryApplicationClass() { 70 + return 'PhabricatorApplicationAuth'; 71 + } 72 + 73 + }
+72
src/applications/auth/storage/PhabricatorAuthSession.php
··· 1 + <?php 2 + 3 + final class PhabricatorAuthSession extends PhabricatorAuthDAO 4 + implements PhabricatorPolicyInterface { 5 + 6 + protected $userPHID; 7 + protected $type; 8 + protected $sessionKey; 9 + protected $sessionStart; 10 + 11 + private $identityObject = self::ATTACHABLE; 12 + 13 + public function getConfiguration() { 14 + return array( 15 + self::CONFIG_IDS => self::IDS_MANUAL, 16 + self::CONFIG_TIMESTAMPS => false, 17 + ) + parent::getConfiguration(); 18 + } 19 + 20 + public function getApplicationName() { 21 + // This table predates the "Auth" application, and really all applications. 22 + return 'user'; 23 + } 24 + 25 + public function getTableName() { 26 + // This is a very old table with a nonstandard name. 27 + return PhabricatorUser::SESSION_TABLE; 28 + } 29 + 30 + public function attachIdentityObject($identity_object) { 31 + $this->identityObject = $identity_object; 32 + return $this; 33 + } 34 + 35 + public function getIdentityObject() { 36 + return $this->assertAttached($this->identityObject); 37 + } 38 + 39 + 40 + /* -( PhabricatorPolicyInterface )----------------------------------------- */ 41 + 42 + 43 + public function getCapabilities() { 44 + return array( 45 + PhabricatorPolicyCapability::CAN_VIEW, 46 + ); 47 + } 48 + 49 + public function getPolicy($capability) { 50 + return PhabricatorPolicies::POLICY_NOONE; 51 + } 52 + 53 + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { 54 + if (!$viewer->getPHID()) { 55 + return false; 56 + } 57 + 58 + $object = $this->getIdentityObject(); 59 + if ($object instanceof PhabricatorUser) { 60 + return ($object->getPHID() == $viewer->getPHID()); 61 + } else if ($object instanceof PhabricatorExternalAccount) { 62 + return ($object->getUserPHID() == $viewer->getPHID()); 63 + } 64 + 65 + return false; 66 + } 67 + 68 + public function describeAutomaticCapability($capability) { 69 + return pht('A session is visible only to its owner.'); 70 + } 71 + 72 + }
+1 -1
src/applications/base/controller/PhabricatorController.php
··· 44 44 'SELECT u.* FROM %T u JOIN %T s ON u.phid = s.userPHID 45 45 AND s.type LIKE %> AND s.sessionKey = %s', 46 46 $user->getTableName(), 47 - 'phabricator_session', 47 + PhabricatorUser::SESSION_TABLE, 48 48 'web-', 49 49 PhabricatorHash::digest($phsid)); 50 50 if ($info) {
+95
src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
··· 1 + <?php 2 + 3 + final class PhabricatorSettingsPanelSessions 4 + extends PhabricatorSettingsPanel { 5 + 6 + public function getPanelKey() { 7 + return 'sessions'; 8 + } 9 + 10 + public function getPanelName() { 11 + return pht('Sessions'); 12 + } 13 + 14 + public function getPanelGroup() { 15 + return pht('Authentication'); 16 + } 17 + 18 + public function isEnabled() { 19 + return true; 20 + } 21 + 22 + public function processRequest(AphrontRequest $request) { 23 + $viewer = $request->getUser(); 24 + 25 + $accounts = id(new PhabricatorExternalAccountQuery()) 26 + ->setViewer($viewer) 27 + ->withUserPHIDs(array($viewer->getPHID())) 28 + ->execute(); 29 + 30 + $identity_phids = mpull($accounts, 'getPHID'); 31 + $identity_phids[] = $viewer->getPHID(); 32 + 33 + $sessions = id(new PhabricatorAuthSessionQuery()) 34 + ->setViewer($viewer) 35 + ->withIdentityPHIDs($identity_phids) 36 + ->execute(); 37 + 38 + $handles = id(new PhabricatorHandleQuery()) 39 + ->setViewer($viewer) 40 + ->withPHIDs($identity_phids) 41 + ->execute(); 42 + 43 + // TODO: Once this has a real ID column, use that instead. 44 + $sessions = msort($sessions, 'getSessionStart'); 45 + $sessions = array_reverse($sessions); 46 + 47 + $current_key = PhabricatorHash::digest($request->getCookie('phsid')); 48 + 49 + $rows = array(); 50 + $rowc = array(); 51 + foreach ($sessions as $session) { 52 + if ($session->getSessionKey() == $current_key) { 53 + $rowc[] = 'highlighted'; 54 + } else { 55 + $rowc[] = null; 56 + } 57 + 58 + $rows[] = array( 59 + $handles[$session->getUserPHID()]->renderLink(), 60 + substr($session->getSessionKey(), 0, 12), 61 + $session->getType(), 62 + phabricator_datetime($session->getSessionStart(), $viewer), 63 + ); 64 + } 65 + 66 + $table = new AphrontTableView($rows); 67 + $table->setNoDataString(pht("You don't have any active sessions.")); 68 + $table->setRowClasses($rowc); 69 + $table->setHeaders( 70 + array( 71 + pht('Identity'), 72 + pht('Session'), 73 + pht('Type'), 74 + pht('Created'), 75 + )); 76 + $table->setColumnClasses( 77 + array( 78 + 'wide', 79 + 'n', 80 + '', 81 + 'right', 82 + )); 83 + 84 + 85 + $header = id(new PHUIHeaderView()) 86 + ->setHeader(pht('Active Login Sessions')); 87 + 88 + $panel = id(new PHUIObjectBoxView()) 89 + ->setHeader($header) 90 + ->appendChild($table); 91 + 92 + return $panel; 93 + } 94 + 95 + }