@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.

Let users review their own account activity logs

Summary:
Ref T4398. This adds a settings panel for account activity so users can review activity on their own account. Some goals are:

- Make it easier for us to develop and support auth and credential information, see T4398. This is the primary driver.
- Make it easier for users to understand and review auth and credential information (see T4842 for an example -- this isn't there yet, but builds toward it).
- Improve user confidence in security by making logging more apparent and accessible.

Minor corresponding changes:

- Entering and exiting hisec mode is now logged.
- This, sessions, and OAuth authorizations have moved to a new "Sessions and Logs" area, since "Authentication" was getting huge.

Test Plan:
- Viewed new panel.
- Viewed old UI.
- Entered/exited hisec and got prompted.

Reviewers: btrahan

Reviewed By: btrahan

Subscribers: epriestley

Maniphest Tasks: T4398

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

+195 -65
+4
src/__phutil_library_map__.php
··· 2055 2055 'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php', 2056 2056 'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php', 2057 2057 'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php', 2058 + 'PhabricatorSettingsPanelActivity' => 'applications/settings/panel/PhabricatorSettingsPanelActivity.php', 2058 2059 'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php', 2059 2060 'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php', 2060 2061 'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php', ··· 2221 2222 'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php', 2222 2223 'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php', 2223 2224 'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php', 2225 + 'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php', 2224 2226 'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php', 2225 2227 'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php', 2226 2228 'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php', ··· 4950 4952 'PhabricatorSettingsAdjustController' => 'PhabricatorController', 4951 4953 'PhabricatorSettingsMainController' => 'PhabricatorController', 4952 4954 'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel', 4955 + 'PhabricatorSettingsPanelActivity' => 'PhabricatorSettingsPanel', 4953 4956 'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel', 4954 4957 'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel', 4955 4958 'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel', ··· 5131 5134 0 => 'PhabricatorUserDAO', 5132 5135 1 => 'PhabricatorPolicyInterface', 5133 5136 ), 5137 + 'PhabricatorUserLogView' => 'AphrontView', 5134 5138 'PhabricatorUserPreferences' => 'PhabricatorUserDAO', 5135 5139 'PhabricatorUserProfile' => 'PhabricatorUserDAO', 5136 5140 'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor',
+2 -5
src/applications/auth/controller/PhabricatorAuthDowngradeSessionController.php
··· 20 20 21 21 if ($request->isFormPost()) { 22 22 23 - queryfx( 24 - $session->establishConnection('w'), 25 - 'UPDATE %T SET highSecurityUntil = NULL WHERE id = %d', 26 - $session->getTableName(), 27 - $session->getID()); 23 + id(new PhabricatorAuthSessionEngine()) 24 + ->exitHighSecurity($viewer, $session); 28 25 29 26 return id(new AphrontRedirectResponse()) 30 27 ->setURI($this->getApplicationURI('session/downgrade/'));
+23
src/applications/auth/engine/PhabricatorAuthSessionEngine.php
··· 249 249 $session->getTableName(), 250 250 $until, 251 251 $session->getID()); 252 + 253 + $log = PhabricatorUserLog::initializeNewLog( 254 + $viewer, 255 + $viewer->getPHID(), 256 + PhabricatorUserLog::ACTION_ENTER_HISEC); 257 + $log->save(); 252 258 } 253 259 } 254 260 ··· 301 307 return $form; 302 308 } 303 309 310 + 311 + public function exitHighSecurity( 312 + PhabricatorUser $viewer, 313 + PhabricatorAuthSession $session) { 314 + 315 + queryfx( 316 + $session->establishConnection('w'), 317 + 'UPDATE %T SET highSecurityUntil = NULL WHERE id = %d', 318 + $session->getTableName(), 319 + $session->getID()); 320 + 321 + $log = PhabricatorUserLog::initializeNewLog( 322 + $viewer, 323 + $viewer->getPHID(), 324 + PhabricatorUserLog::ACTION_EXIT_HISEC); 325 + $log->save(); 326 + } 304 327 305 328 }
+1 -1
src/applications/oauthserver/panel/PhabricatorOAuthServerAuthorizationsSettingsPanel.php
··· 12 12 } 13 13 14 14 public function getPanelGroup() { 15 - return pht('Authentication'); 15 + return pht('Sessions and Logs'); 16 16 } 17 17 18 18 public function isEnabled() {
+5 -58
src/applications/people/controller/PhabricatorPeopleLogsController.php
··· 35 35 $phids = array_keys($phids); 36 36 $handles = $this->loadViewerHandles($phids); 37 37 38 - $action_map = PhabricatorUserLog::getActionTypeMap(); 39 - 40 - $rows = array(); 41 - foreach ($logs as $log) { 42 - 43 - $ip_href = $this->getApplicationURI( 44 - 'logs/?ip='.$log->getRemoteAddr()); 45 - 46 - $session_href = $this->getApplicationURI( 47 - 'logs/?sessions='.$log->getSession()); 48 - 49 - $action = $log->getAction(); 50 - $action_name = idx($action_map, $action, $action); 51 - 52 - $rows[] = array( 53 - phabricator_date($log->getDateCreated(), $viewer), 54 - phabricator_time($log->getDateCreated(), $viewer), 55 - $action_name, 56 - $log->getActorPHID() 57 - ? $handles[$log->getActorPHID()]->getName() 58 - : null, 59 - $handles[$log->getUserPHID()]->getName(), 60 - phutil_tag( 61 - 'a', 62 - array( 63 - 'href' => $ip_href, 64 - ), 65 - $log->getRemoteAddr()), 66 - phutil_tag( 67 - 'a', 68 - array( 69 - 'href' => $session_href, 70 - ), 71 - substr($log->getSession(), 0, 6)), 72 - ); 73 - } 74 - 75 - $table = new AphrontTableView($rows); 76 - $table->setHeaders( 77 - array( 78 - pht('Date'), 79 - pht('Time'), 80 - pht('Action'), 81 - pht('Actor'), 82 - pht('User'), 83 - pht('IP'), 84 - pht('Session'), 85 - )); 86 - $table->setColumnClasses( 87 - array( 88 - '', 89 - 'right', 90 - 'wide', 91 - '', 92 - '', 93 - '', 94 - 'n', 95 - )); 38 + $table = id(new PhabricatorUserLogView()) 39 + ->setUser($viewer) 40 + ->setLogs($logs) 41 + ->setSearchBaseURI($this->getApplicationURI('logs/')) 42 + ->setHandles($handles); 96 43 97 44 return id(new PHUIObjectBoxView()) 98 45 ->setHeaderText(pht('User Activity Logs'))
+1
src/applications/people/query/PhabricatorPeopleLogQuery.php
··· 76 76 $where[] = qsprintf( 77 77 $conn_r, 78 78 'actorPHID IN (%Ls) OR userPHID IN (%Ls)', 79 + $this->relatedPHIDs, 79 80 $this->relatedPHIDs); 80 81 } 81 82
+5
src/applications/people/storage/PhabricatorUserLog.php
··· 27 27 const ACTION_CHANGE_PASSWORD = 'change-password'; 28 28 const ACTION_CHANGE_USERNAME = 'change-username'; 29 29 30 + const ACTION_ENTER_HISEC = 'hisec-enter'; 31 + const ACTION_EXIT_HISEC = 'hisec-exit'; 32 + 30 33 protected $actorPHID; 31 34 protected $userPHID; 32 35 protected $action; ··· 58 61 self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'), 59 62 self::ACTION_CHANGE_PASSWORD => pht('Change Password'), 60 63 self::ACTION_CHANGE_USERNAME => pht('Change Username'), 64 + self::ACTION_ENTER_HISEC => pht('Hisec: Enter'), 65 + self::ACTION_EXIT_HISEC => pht('Hisec: Exit'), 61 66 ); 62 67 } 63 68
+95
src/applications/people/view/PhabricatorUserLogView.php
··· 1 + <?php 2 + 3 + final class PhabricatorUserLogView extends AphrontView { 4 + 5 + private $logs; 6 + private $handles; 7 + private $searchBaseURI; 8 + 9 + public function setSearchBaseURI($search_base_uri) { 10 + $this->searchBaseURI = $search_base_uri; 11 + return $this; 12 + } 13 + 14 + public function setLogs(array $logs) { 15 + assert_instances_of($logs, 'PhabricatorUserLog'); 16 + $this->logs = $logs; 17 + return $this; 18 + } 19 + 20 + public function setHandles(array $handles) { 21 + assert_instances_of($handles, 'PhabricatorObjectHandle'); 22 + $this->handles = $handles; 23 + return $this; 24 + } 25 + 26 + public function render() { 27 + $logs = $this->logs; 28 + $handles = $this->handles; 29 + $viewer = $this->getUser(); 30 + 31 + $action_map = PhabricatorUserLog::getActionTypeMap(); 32 + $base_uri = $this->searchBaseURI; 33 + 34 + $rows = array(); 35 + foreach ($logs as $log) { 36 + 37 + $ip = $log->getRemoteAddr(); 38 + $session = substr($log->getSession(), 0, 6); 39 + 40 + if ($base_uri) { 41 + $ip = phutil_tag( 42 + 'a', 43 + array( 44 + 'href' => $base_uri.'?ip='.$log->getRemoteAddr().'#R', 45 + ), 46 + $ip); 47 + $session = phutil_tag( 48 + 'a', 49 + array( 50 + 'href' => $base_uri.'?sessions='.$log->getSession().'#R', 51 + ), 52 + $session); 53 + } 54 + 55 + $action = $log->getAction(); 56 + $action_name = idx($action_map, $action, $action); 57 + 58 + $rows[] = array( 59 + phabricator_date($log->getDateCreated(), $viewer), 60 + phabricator_time($log->getDateCreated(), $viewer), 61 + $action_name, 62 + $log->getActorPHID() 63 + ? $handles[$log->getActorPHID()]->getName() 64 + : null, 65 + $handles[$log->getUserPHID()]->getName(), 66 + $ip, 67 + $session, 68 + ); 69 + } 70 + 71 + $table = new AphrontTableView($rows); 72 + $table->setHeaders( 73 + array( 74 + pht('Date'), 75 + pht('Time'), 76 + pht('Action'), 77 + pht('Actor'), 78 + pht('User'), 79 + pht('IP'), 80 + pht('Session'), 81 + )); 82 + $table->setColumnClasses( 83 + array( 84 + '', 85 + 'right', 86 + 'wide', 87 + '', 88 + '', 89 + '', 90 + 'n', 91 + )); 92 + 93 + return $table; 94 + } 95 + }
+58
src/applications/settings/panel/PhabricatorSettingsPanelActivity.php
··· 1 + <?php 2 + 3 + final class PhabricatorSettingsPanelActivity 4 + extends PhabricatorSettingsPanel { 5 + 6 + public function getPanelKey() { 7 + return 'activity'; 8 + } 9 + 10 + public function getPanelName() { 11 + return pht('Activity Logs'); 12 + } 13 + 14 + public function getPanelGroup() { 15 + return pht('Sessions and Logs'); 16 + } 17 + 18 + public function isEnabled() { 19 + return true; 20 + } 21 + 22 + public function processRequest(AphrontRequest $request) { 23 + $viewer = $request->getUser(); 24 + $user = $this->getUser(); 25 + 26 + $logs = id(new PhabricatorPeopleLogQuery()) 27 + ->setViewer($viewer) 28 + ->withRelatedPHIDs(array($user->getPHID())) 29 + ->execute(); 30 + 31 + $phids = array(); 32 + foreach ($logs as $log) { 33 + $phids[] = $log->getUserPHID(); 34 + $phids[] = $log->getActorPHID(); 35 + } 36 + 37 + if ($phids) { 38 + $handles = id(new PhabricatorHandleQuery()) 39 + ->setViewer($viewer) 40 + ->withPHIDs($phids) 41 + ->execute(); 42 + } else { 43 + $handles = array(); 44 + } 45 + 46 + $table = id(new PhabricatorUserLogView()) 47 + ->setUser($viewer) 48 + ->setLogs($logs) 49 + ->setHandles($handles); 50 + 51 + $panel = id(new PHUIObjectBoxView()) 52 + ->setHeaderText(pht('Account Activity Logs')) 53 + ->appendChild($table); 54 + 55 + return $panel; 56 + } 57 + 58 + }
+1 -1
src/applications/settings/panel/PhabricatorSettingsPanelSessions.php
··· 12 12 } 13 13 14 14 public function getPanelGroup() { 15 - return pht('Authentication'); 15 + return pht('Sessions and Logs'); 16 16 } 17 17 18 18 public function isEnabled() {