mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-26 16:52:41 +01:00
Provide a basic detail view for user activity logs
Summary: Depends on D20673. Ref T13343. Since we're now putting log IDs in email, make the UI a little better for working with log IDs. Some day, this page might have actions like "report this as suspicious" or whatever, but I'm not planning to do any of that for now. Test Plan: {F6608631} Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13343 Differential Revision: https://secure.phabricator.com/D20674
This commit is contained in:
parent
60db658d52
commit
99c864f5e6
6 changed files with 167 additions and 29 deletions
|
@ -4031,6 +4031,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
|
'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php',
|
||||||
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
|
'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php',
|
||||||
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
|
'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php',
|
||||||
|
'PhabricatorPeopleLogViewController' => 'applications/people/controller/PhabricatorPeopleLogViewController.php',
|
||||||
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
|
'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php',
|
||||||
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
|
'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php',
|
||||||
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
|
'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php',
|
||||||
|
@ -10291,6 +10292,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
'PhabricatorPeopleListController' => 'PhabricatorPeopleController',
|
||||||
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine',
|
||||||
|
'PhabricatorPeopleLogViewController' => 'PhabricatorPeopleController',
|
||||||
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
|
'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController',
|
||||||
'PhabricatorPeopleMailEngine' => 'Phobject',
|
'PhabricatorPeopleMailEngine' => 'Phobject',
|
||||||
'PhabricatorPeopleMailEngineException' => 'Exception',
|
'PhabricatorPeopleMailEngineException' => 'Exception',
|
||||||
|
|
|
@ -44,6 +44,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
|
||||||
$this->getQueryRoutePattern() => 'PhabricatorPeopleListController',
|
$this->getQueryRoutePattern() => 'PhabricatorPeopleListController',
|
||||||
'logs/' => array(
|
'logs/' => array(
|
||||||
$this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController',
|
$this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController',
|
||||||
|
'(?P<id>\d+)/' => 'PhabricatorPeopleLogViewController',
|
||||||
),
|
),
|
||||||
'invite/' => array(
|
'invite/' => array(
|
||||||
'(?:query/(?P<queryKey>[^/]+)/)?'
|
'(?:query/(?P<queryKey>[^/]+)/)?'
|
||||||
|
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorPeopleLogViewController
|
||||||
|
extends PhabricatorPeopleController {
|
||||||
|
|
||||||
|
public function shouldRequireAdmin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handleRequest(AphrontRequest $request) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$id = $request->getURIData('id');
|
||||||
|
|
||||||
|
$log = id(new PhabricatorPeopleLogQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->withIDs(array($id))
|
||||||
|
->executeOne();
|
||||||
|
if (!$log) {
|
||||||
|
return new Aphront404Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
$logs_uri = $this->getApplicationURI('logs/');
|
||||||
|
|
||||||
|
$crumbs = $this->buildApplicationCrumbs()
|
||||||
|
->addTextCrumb(pht('Activity Logs'), $logs_uri)
|
||||||
|
->addTextCrumb($log->getObjectName())
|
||||||
|
->setBorder(true);
|
||||||
|
|
||||||
|
$header = $this->buildHeaderView($log);
|
||||||
|
$properties = $this->buildPropertiesView($log);
|
||||||
|
|
||||||
|
$view = id(new PHUITwoColumnView())
|
||||||
|
->setHeader($header)
|
||||||
|
->addPropertySection(pht('Details'), $properties);
|
||||||
|
|
||||||
|
return $this->newPage()
|
||||||
|
->setCrumbs($crumbs)
|
||||||
|
->setTitle($log->getObjectName())
|
||||||
|
->appendChild($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildHeaderView(PhabricatorUserLog $log) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$view = id(new PHUIHeaderView())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setHeader($log->getObjectName());
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildPropertiesView(PhabricatorUserLog $log) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
|
||||||
|
$view = id(new PHUIPropertyListView())
|
||||||
|
->setViewer($viewer);
|
||||||
|
|
||||||
|
$type_map = PhabricatorUserLogType::getAllLogTypes();
|
||||||
|
$type_map = mpull($type_map, 'getLogTypeName', 'getLogTypeKey');
|
||||||
|
|
||||||
|
$action = $log->getAction();
|
||||||
|
$type_name = idx($type_map, $action, $action);
|
||||||
|
|
||||||
|
$view->addProperty(pht('Event Type'), $type_name);
|
||||||
|
|
||||||
|
$view->addProperty(
|
||||||
|
pht('Event Date'),
|
||||||
|
phabricator_datetime($log->getDateCreated(), $viewer));
|
||||||
|
|
||||||
|
$actor_phid = $log->getActorPHID();
|
||||||
|
if ($actor_phid) {
|
||||||
|
$view->addProperty(
|
||||||
|
pht('Acting User'),
|
||||||
|
$viewer->renderHandle($actor_phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_phid = $log->getUserPHID();
|
||||||
|
if ($user_phid) {
|
||||||
|
$view->addProperty(
|
||||||
|
pht('Affected User'),
|
||||||
|
$viewer->renderHandle($user_phid));
|
||||||
|
}
|
||||||
|
|
||||||
|
$remote_address = $log->getRemoteAddressForViewer($viewer);
|
||||||
|
if ($remote_address !== null) {
|
||||||
|
$view->addProperty(pht('Remote Address'), $remote_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
final class PhabricatorPeopleLogQuery
|
final class PhabricatorPeopleLogQuery
|
||||||
extends PhabricatorCursorPagedPolicyAwareQuery {
|
extends PhabricatorCursorPagedPolicyAwareQuery {
|
||||||
|
|
||||||
|
private $ids;
|
||||||
private $actorPHIDs;
|
private $actorPHIDs;
|
||||||
private $userPHIDs;
|
private $userPHIDs;
|
||||||
private $relatedPHIDs;
|
private $relatedPHIDs;
|
||||||
|
@ -12,6 +13,11 @@ final class PhabricatorPeopleLogQuery
|
||||||
private $dateCreatedMin;
|
private $dateCreatedMin;
|
||||||
private $dateCreatedMax;
|
private $dateCreatedMax;
|
||||||
|
|
||||||
|
public function withIDs(array $ids) {
|
||||||
|
$this->ids = $ids;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withActorPHIDs(array $actor_phids) {
|
public function withActorPHIDs(array $actor_phids) {
|
||||||
$this->actorPHIDs = $actor_phids;
|
$this->actorPHIDs = $actor_phids;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -59,6 +65,13 @@ final class PhabricatorPeopleLogQuery
|
||||||
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
|
||||||
$where = parent::buildWhereClauseParts($conn);
|
$where = parent::buildWhereClauseParts($conn);
|
||||||
|
|
||||||
|
if ($this->ids !== null) {
|
||||||
|
$where[] = qsprintf(
|
||||||
|
$conn,
|
||||||
|
'id IN (%Ld)',
|
||||||
|
$this->ids);
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->actorPHIDs !== null) {
|
if ($this->actorPHIDs !== null) {
|
||||||
$where[] = qsprintf(
|
$where[] = qsprintf(
|
||||||
$conn,
|
$conn,
|
||||||
|
|
|
@ -100,6 +100,43 @@ final class PhabricatorUserLog extends PhabricatorUserDAO
|
||||||
) + parent::getConfiguration();
|
) + parent::getConfiguration();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getURI() {
|
||||||
|
return urisprintf('/people/logs/%s/', $this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getObjectName() {
|
||||||
|
return pht('Activity Log %d', $this->getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRemoteAddressForViewer(PhabricatorUser $viewer) {
|
||||||
|
$viewer_phid = $viewer->getPHID();
|
||||||
|
$actor_phid = $this->getActorPHID();
|
||||||
|
$user_phid = $this->getUserPHID();
|
||||||
|
|
||||||
|
if (!$viewer_phid) {
|
||||||
|
$can_see_ip = false;
|
||||||
|
} else if ($viewer->getIsAdmin()) {
|
||||||
|
$can_see_ip = true;
|
||||||
|
} else if ($viewer_phid == $actor_phid) {
|
||||||
|
// You can see the address if you took the action.
|
||||||
|
$can_see_ip = true;
|
||||||
|
} else if (!$actor_phid && ($viewer_phid == $user_phid)) {
|
||||||
|
// You can see the address if it wasn't authenticated and applied
|
||||||
|
// to you (partial login).
|
||||||
|
$can_see_ip = true;
|
||||||
|
} else {
|
||||||
|
// You can't see the address when an administrator disables your
|
||||||
|
// account, since it's their address.
|
||||||
|
$can_see_ip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$can_see_ip) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getRemoteAddr();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
|
|
@ -41,33 +41,16 @@ final class PhabricatorUserLogView extends AphrontView {
|
||||||
$actor_phid = $log->getActorPHID();
|
$actor_phid = $log->getActorPHID();
|
||||||
$user_phid = $log->getUserPHID();
|
$user_phid = $log->getUserPHID();
|
||||||
|
|
||||||
if ($viewer->getIsAdmin()) {
|
$remote_address = $log->getRemoteAddressForViewer($viewer);
|
||||||
$can_see_ip = true;
|
if ($remote_address !== null) {
|
||||||
} else if ($viewer_phid == $actor_phid) {
|
|
||||||
// You can see the address if you took the action.
|
|
||||||
$can_see_ip = true;
|
|
||||||
} else if (!$actor_phid && ($viewer_phid == $user_phid)) {
|
|
||||||
// You can see the address if it wasn't authenticated and applied
|
|
||||||
// to you (partial login).
|
|
||||||
$can_see_ip = true;
|
|
||||||
} else {
|
|
||||||
// You can't see the address when an administrator disables your
|
|
||||||
// account, since it's their address.
|
|
||||||
$can_see_ip = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($can_see_ip) {
|
|
||||||
$ip = $log->getRemoteAddr();
|
|
||||||
if ($base_uri) {
|
if ($base_uri) {
|
||||||
$ip = phutil_tag(
|
$remote_address = phutil_tag(
|
||||||
'a',
|
'a',
|
||||||
array(
|
array(
|
||||||
'href' => $base_uri.'?ip='.$ip.'#R',
|
'href' => $base_uri.'?ip='.$remote_address.'#R',
|
||||||
),
|
),
|
||||||
$ip);
|
$remote_address);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
$ip = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$action = $log->getAction();
|
$action = $log->getAction();
|
||||||
|
@ -85,37 +68,47 @@ final class PhabricatorUserLogView extends AphrontView {
|
||||||
$user_name = null;
|
$user_name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$action_link = phutil_tag(
|
||||||
|
'a',
|
||||||
|
array(
|
||||||
|
'href' => $log->getURI(),
|
||||||
|
),
|
||||||
|
$action_name);
|
||||||
|
|
||||||
$rows[] = array(
|
$rows[] = array(
|
||||||
phabricator_date($log->getDateCreated(), $viewer),
|
$log->getID(),
|
||||||
phabricator_time($log->getDateCreated(), $viewer),
|
$action_link,
|
||||||
$action_name,
|
|
||||||
$actor_name,
|
$actor_name,
|
||||||
$user_name,
|
$user_name,
|
||||||
$ip,
|
$remote_address,
|
||||||
$session,
|
$session,
|
||||||
|
phabricator_date($log->getDateCreated(), $viewer),
|
||||||
|
phabricator_time($log->getDateCreated(), $viewer),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$table = new AphrontTableView($rows);
|
$table = new AphrontTableView($rows);
|
||||||
$table->setHeaders(
|
$table->setHeaders(
|
||||||
array(
|
array(
|
||||||
pht('Date'),
|
pht('ID'),
|
||||||
pht('Time'),
|
|
||||||
pht('Action'),
|
pht('Action'),
|
||||||
pht('Actor'),
|
pht('Actor'),
|
||||||
pht('User'),
|
pht('User'),
|
||||||
pht('IP'),
|
pht('IP'),
|
||||||
pht('Session'),
|
pht('Session'),
|
||||||
|
pht('Date'),
|
||||||
|
pht('Time'),
|
||||||
));
|
));
|
||||||
$table->setColumnClasses(
|
$table->setColumnClasses(
|
||||||
array(
|
array(
|
||||||
'',
|
'',
|
||||||
'right',
|
|
||||||
'wide',
|
'wide',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
'n',
|
'n',
|
||||||
|
'',
|
||||||
|
'right',
|
||||||
));
|
));
|
||||||
|
|
||||||
return $table;
|
return $table;
|
||||||
|
|
Loading…
Reference in a new issue