mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-23 14:00:56 +01:00
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
This commit is contained in:
parent
320be1a1b8
commit
3f5a55fa6e
10 changed files with 195 additions and 65 deletions
|
@ -2055,6 +2055,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
|
||||
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
|
||||
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
|
||||
'PhabricatorSettingsPanelActivity' => 'applications/settings/panel/PhabricatorSettingsPanelActivity.php',
|
||||
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
|
||||
'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php',
|
||||
'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php',
|
||||
|
@ -2221,6 +2222,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
||||
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
||||
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
|
||||
'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php',
|
||||
'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php',
|
||||
'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php',
|
||||
'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php',
|
||||
|
@ -4950,6 +4952,7 @@ phutil_register_library_map(array(
|
|||
'PhabricatorSettingsAdjustController' => 'PhabricatorController',
|
||||
'PhabricatorSettingsMainController' => 'PhabricatorController',
|
||||
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelActivity' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel',
|
||||
'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel',
|
||||
|
@ -5131,6 +5134,7 @@ phutil_register_library_map(array(
|
|||
0 => 'PhabricatorUserDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'PhabricatorUserLogView' => 'AphrontView',
|
||||
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
|
||||
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
|
||||
'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
|
|
|
@ -20,11 +20,8 @@ final class PhabricatorAuthDowngradeSessionController
|
|||
|
||||
if ($request->isFormPost()) {
|
||||
|
||||
queryfx(
|
||||
$session->establishConnection('w'),
|
||||
'UPDATE %T SET highSecurityUntil = NULL WHERE id = %d',
|
||||
$session->getTableName(),
|
||||
$session->getID());
|
||||
id(new PhabricatorAuthSessionEngine())
|
||||
->exitHighSecurity($viewer, $session);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($this->getApplicationURI('session/downgrade/'));
|
||||
|
|
|
@ -249,6 +249,12 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
$session->getTableName(),
|
||||
$until,
|
||||
$session->getID());
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_ENTER_HISEC);
|
||||
$log->save();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -302,4 +308,21 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
|||
}
|
||||
|
||||
|
||||
public function exitHighSecurity(
|
||||
PhabricatorUser $viewer,
|
||||
PhabricatorAuthSession $session) {
|
||||
|
||||
queryfx(
|
||||
$session->establishConnection('w'),
|
||||
'UPDATE %T SET highSecurityUntil = NULL WHERE id = %d',
|
||||
$session->getTableName(),
|
||||
$session->getID());
|
||||
|
||||
$log = PhabricatorUserLog::initializeNewLog(
|
||||
$viewer,
|
||||
$viewer->getPHID(),
|
||||
PhabricatorUserLog::ACTION_EXIT_HISEC);
|
||||
$log->save();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ final class PhabricatorOAuthServerAuthorizationsSettingsPanel
|
|||
}
|
||||
|
||||
public function getPanelGroup() {
|
||||
return pht('Authentication');
|
||||
return pht('Sessions and Logs');
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
|
|
|
@ -35,64 +35,11 @@ final class PhabricatorPeopleLogsController extends PhabricatorPeopleController
|
|||
$phids = array_keys($phids);
|
||||
$handles = $this->loadViewerHandles($phids);
|
||||
|
||||
$action_map = PhabricatorUserLog::getActionTypeMap();
|
||||
|
||||
$rows = array();
|
||||
foreach ($logs as $log) {
|
||||
|
||||
$ip_href = $this->getApplicationURI(
|
||||
'logs/?ip='.$log->getRemoteAddr());
|
||||
|
||||
$session_href = $this->getApplicationURI(
|
||||
'logs/?sessions='.$log->getSession());
|
||||
|
||||
$action = $log->getAction();
|
||||
$action_name = idx($action_map, $action, $action);
|
||||
|
||||
$rows[] = array(
|
||||
phabricator_date($log->getDateCreated(), $viewer),
|
||||
phabricator_time($log->getDateCreated(), $viewer),
|
||||
$action_name,
|
||||
$log->getActorPHID()
|
||||
? $handles[$log->getActorPHID()]->getName()
|
||||
: null,
|
||||
$handles[$log->getUserPHID()]->getName(),
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $ip_href,
|
||||
),
|
||||
$log->getRemoteAddr()),
|
||||
phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $session_href,
|
||||
),
|
||||
substr($log->getSession(), 0, 6)),
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Date'),
|
||||
pht('Time'),
|
||||
pht('Action'),
|
||||
pht('Actor'),
|
||||
pht('User'),
|
||||
pht('IP'),
|
||||
pht('Session'),
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'right',
|
||||
'wide',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'n',
|
||||
));
|
||||
$table = id(new PhabricatorUserLogView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->setSearchBaseURI($this->getApplicationURI('logs/'))
|
||||
->setHandles($handles);
|
||||
|
||||
return id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('User Activity Logs'))
|
||||
|
|
|
@ -76,6 +76,7 @@ final class PhabricatorPeopleLogQuery
|
|||
$where[] = qsprintf(
|
||||
$conn_r,
|
||||
'actorPHID IN (%Ls) OR userPHID IN (%Ls)',
|
||||
$this->relatedPHIDs,
|
||||
$this->relatedPHIDs);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
|||
const ACTION_CHANGE_PASSWORD = 'change-password';
|
||||
const ACTION_CHANGE_USERNAME = 'change-username';
|
||||
|
||||
const ACTION_ENTER_HISEC = 'hisec-enter';
|
||||
const ACTION_EXIT_HISEC = 'hisec-exit';
|
||||
|
||||
protected $actorPHID;
|
||||
protected $userPHID;
|
||||
protected $action;
|
||||
|
@ -58,6 +61,8 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
|||
self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'),
|
||||
self::ACTION_CHANGE_PASSWORD => pht('Change Password'),
|
||||
self::ACTION_CHANGE_USERNAME => pht('Change Username'),
|
||||
self::ACTION_ENTER_HISEC => pht('Hisec: Enter'),
|
||||
self::ACTION_EXIT_HISEC => pht('Hisec: Exit'),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
95
src/applications/people/view/PhabricatorUserLogView.php
Normal file
95
src/applications/people/view/PhabricatorUserLogView.php
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorUserLogView extends AphrontView {
|
||||
|
||||
private $logs;
|
||||
private $handles;
|
||||
private $searchBaseURI;
|
||||
|
||||
public function setSearchBaseURI($search_base_uri) {
|
||||
$this->searchBaseURI = $search_base_uri;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setLogs(array $logs) {
|
||||
assert_instances_of($logs, 'PhabricatorUserLog');
|
||||
$this->logs = $logs;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setHandles(array $handles) {
|
||||
assert_instances_of($handles, 'PhabricatorObjectHandle');
|
||||
$this->handles = $handles;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$logs = $this->logs;
|
||||
$handles = $this->handles;
|
||||
$viewer = $this->getUser();
|
||||
|
||||
$action_map = PhabricatorUserLog::getActionTypeMap();
|
||||
$base_uri = $this->searchBaseURI;
|
||||
|
||||
$rows = array();
|
||||
foreach ($logs as $log) {
|
||||
|
||||
$ip = $log->getRemoteAddr();
|
||||
$session = substr($log->getSession(), 0, 6);
|
||||
|
||||
if ($base_uri) {
|
||||
$ip = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $base_uri.'?ip='.$log->getRemoteAddr().'#R',
|
||||
),
|
||||
$ip);
|
||||
$session = phutil_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => $base_uri.'?sessions='.$log->getSession().'#R',
|
||||
),
|
||||
$session);
|
||||
}
|
||||
|
||||
$action = $log->getAction();
|
||||
$action_name = idx($action_map, $action, $action);
|
||||
|
||||
$rows[] = array(
|
||||
phabricator_date($log->getDateCreated(), $viewer),
|
||||
phabricator_time($log->getDateCreated(), $viewer),
|
||||
$action_name,
|
||||
$log->getActorPHID()
|
||||
? $handles[$log->getActorPHID()]->getName()
|
||||
: null,
|
||||
$handles[$log->getUserPHID()]->getName(),
|
||||
$ip,
|
||||
$session,
|
||||
);
|
||||
}
|
||||
|
||||
$table = new AphrontTableView($rows);
|
||||
$table->setHeaders(
|
||||
array(
|
||||
pht('Date'),
|
||||
pht('Time'),
|
||||
pht('Action'),
|
||||
pht('Actor'),
|
||||
pht('User'),
|
||||
pht('IP'),
|
||||
pht('Session'),
|
||||
));
|
||||
$table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'right',
|
||||
'wide',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'n',
|
||||
));
|
||||
|
||||
return $table;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
final class PhabricatorSettingsPanelActivity
|
||||
extends PhabricatorSettingsPanel {
|
||||
|
||||
public function getPanelKey() {
|
||||
return 'activity';
|
||||
}
|
||||
|
||||
public function getPanelName() {
|
||||
return pht('Activity Logs');
|
||||
}
|
||||
|
||||
public function getPanelGroup() {
|
||||
return pht('Sessions and Logs');
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function processRequest(AphrontRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
$user = $this->getUser();
|
||||
|
||||
$logs = id(new PhabricatorPeopleLogQuery())
|
||||
->setViewer($viewer)
|
||||
->withRelatedPHIDs(array($user->getPHID()))
|
||||
->execute();
|
||||
|
||||
$phids = array();
|
||||
foreach ($logs as $log) {
|
||||
$phids[] = $log->getUserPHID();
|
||||
$phids[] = $log->getActorPHID();
|
||||
}
|
||||
|
||||
if ($phids) {
|
||||
$handles = id(new PhabricatorHandleQuery())
|
||||
->setViewer($viewer)
|
||||
->withPHIDs($phids)
|
||||
->execute();
|
||||
} else {
|
||||
$handles = array();
|
||||
}
|
||||
|
||||
$table = id(new PhabricatorUserLogView())
|
||||
->setUser($viewer)
|
||||
->setLogs($logs)
|
||||
->setHandles($handles);
|
||||
|
||||
$panel = id(new PHUIObjectBoxView())
|
||||
->setHeaderText(pht('Account Activity Logs'))
|
||||
->appendChild($table);
|
||||
|
||||
return $panel;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ final class PhabricatorSettingsPanelSessions
|
|||
}
|
||||
|
||||
public function getPanelGroup() {
|
||||
return pht('Authentication');
|
||||
return pht('Sessions and Logs');
|
||||
}
|
||||
|
||||
public function isEnabled() {
|
||||
|
|
Loading…
Reference in a new issue