mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-24 22:40:55 +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',
|
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
|
||||||
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
|
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
|
||||||
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
|
'PhabricatorSettingsPanelAccount' => 'applications/settings/panel/PhabricatorSettingsPanelAccount.php',
|
||||||
|
'PhabricatorSettingsPanelActivity' => 'applications/settings/panel/PhabricatorSettingsPanelActivity.php',
|
||||||
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
|
'PhabricatorSettingsPanelConduit' => 'applications/settings/panel/PhabricatorSettingsPanelConduit.php',
|
||||||
'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php',
|
'PhabricatorSettingsPanelConpherencePreferences' => 'applications/settings/panel/PhabricatorSettingsPanelConpherencePreferences.php',
|
||||||
'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php',
|
'PhabricatorSettingsPanelDeveloperPreferences' => 'applications/settings/panel/PhabricatorSettingsPanelDeveloperPreferences.php',
|
||||||
|
@ -2221,6 +2222,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
'PhabricatorUserEmail' => 'applications/people/storage/PhabricatorUserEmail.php',
|
||||||
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
'PhabricatorUserEmailTestCase' => 'applications/people/storage/__tests__/PhabricatorUserEmailTestCase.php',
|
||||||
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
|
'PhabricatorUserLog' => 'applications/people/storage/PhabricatorUserLog.php',
|
||||||
|
'PhabricatorUserLogView' => 'applications/people/view/PhabricatorUserLogView.php',
|
||||||
'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php',
|
'PhabricatorUserPreferences' => 'applications/settings/storage/PhabricatorUserPreferences.php',
|
||||||
'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php',
|
'PhabricatorUserProfile' => 'applications/people/storage/PhabricatorUserProfile.php',
|
||||||
'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php',
|
'PhabricatorUserProfileEditor' => 'applications/people/editor/PhabricatorUserProfileEditor.php',
|
||||||
|
@ -4950,6 +4952,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorSettingsAdjustController' => 'PhabricatorController',
|
'PhabricatorSettingsAdjustController' => 'PhabricatorController',
|
||||||
'PhabricatorSettingsMainController' => 'PhabricatorController',
|
'PhabricatorSettingsMainController' => 'PhabricatorController',
|
||||||
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelAccount' => 'PhabricatorSettingsPanel',
|
||||||
|
'PhabricatorSettingsPanelActivity' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelConduit' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelConpherencePreferences' => 'PhabricatorSettingsPanel',
|
||||||
'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel',
|
'PhabricatorSettingsPanelDeveloperPreferences' => 'PhabricatorSettingsPanel',
|
||||||
|
@ -5131,6 +5134,7 @@ phutil_register_library_map(array(
|
||||||
0 => 'PhabricatorUserDAO',
|
0 => 'PhabricatorUserDAO',
|
||||||
1 => 'PhabricatorPolicyInterface',
|
1 => 'PhabricatorPolicyInterface',
|
||||||
),
|
),
|
||||||
|
'PhabricatorUserLogView' => 'AphrontView',
|
||||||
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
|
'PhabricatorUserPreferences' => 'PhabricatorUserDAO',
|
||||||
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
|
'PhabricatorUserProfile' => 'PhabricatorUserDAO',
|
||||||
'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor',
|
'PhabricatorUserProfileEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
|
|
|
@ -20,11 +20,8 @@ final class PhabricatorAuthDowngradeSessionController
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
|
||||||
queryfx(
|
id(new PhabricatorAuthSessionEngine())
|
||||||
$session->establishConnection('w'),
|
->exitHighSecurity($viewer, $session);
|
||||||
'UPDATE %T SET highSecurityUntil = NULL WHERE id = %d',
|
|
||||||
$session->getTableName(),
|
|
||||||
$session->getID());
|
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
->setURI($this->getApplicationURI('session/downgrade/'));
|
->setURI($this->getApplicationURI('session/downgrade/'));
|
||||||
|
|
|
@ -249,6 +249,12 @@ final class PhabricatorAuthSessionEngine extends Phobject {
|
||||||
$session->getTableName(),
|
$session->getTableName(),
|
||||||
$until,
|
$until,
|
||||||
$session->getID());
|
$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() {
|
public function getPanelGroup() {
|
||||||
return pht('Authentication');
|
return pht('Sessions and Logs');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEnabled() {
|
public function isEnabled() {
|
||||||
|
|
|
@ -35,64 +35,11 @@ final class PhabricatorPeopleLogsController extends PhabricatorPeopleController
|
||||||
$phids = array_keys($phids);
|
$phids = array_keys($phids);
|
||||||
$handles = $this->loadViewerHandles($phids);
|
$handles = $this->loadViewerHandles($phids);
|
||||||
|
|
||||||
$action_map = PhabricatorUserLog::getActionTypeMap();
|
$table = id(new PhabricatorUserLogView())
|
||||||
|
->setUser($viewer)
|
||||||
$rows = array();
|
->setLogs($logs)
|
||||||
foreach ($logs as $log) {
|
->setSearchBaseURI($this->getApplicationURI('logs/'))
|
||||||
|
->setHandles($handles);
|
||||||
$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',
|
|
||||||
));
|
|
||||||
|
|
||||||
return id(new PHUIObjectBoxView())
|
return id(new PHUIObjectBoxView())
|
||||||
->setHeaderText(pht('User Activity Logs'))
|
->setHeaderText(pht('User Activity Logs'))
|
||||||
|
|
|
@ -76,6 +76,7 @@ final class PhabricatorPeopleLogQuery
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn_r,
|
$conn_r,
|
||||||
'actorPHID IN (%Ls) OR userPHID IN (%Ls)',
|
'actorPHID IN (%Ls) OR userPHID IN (%Ls)',
|
||||||
|
$this->relatedPHIDs,
|
||||||
$this->relatedPHIDs);
|
$this->relatedPHIDs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||||
const ACTION_CHANGE_PASSWORD = 'change-password';
|
const ACTION_CHANGE_PASSWORD = 'change-password';
|
||||||
const ACTION_CHANGE_USERNAME = 'change-username';
|
const ACTION_CHANGE_USERNAME = 'change-username';
|
||||||
|
|
||||||
|
const ACTION_ENTER_HISEC = 'hisec-enter';
|
||||||
|
const ACTION_EXIT_HISEC = 'hisec-exit';
|
||||||
|
|
||||||
protected $actorPHID;
|
protected $actorPHID;
|
||||||
protected $userPHID;
|
protected $userPHID;
|
||||||
protected $action;
|
protected $action;
|
||||||
|
@ -58,6 +61,8 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||||
self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'),
|
self::ACTION_EMAIL_REMOVE => pht('Email: Remove Address'),
|
||||||
self::ACTION_CHANGE_PASSWORD => pht('Change Password'),
|
self::ACTION_CHANGE_PASSWORD => pht('Change Password'),
|
||||||
self::ACTION_CHANGE_USERNAME => pht('Change Username'),
|
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() {
|
public function getPanelGroup() {
|
||||||
return pht('Authentication');
|
return pht('Sessions and Logs');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isEnabled() {
|
public function isEnabled() {
|
||||||
|
|
Loading…
Reference in a new issue