diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index bee0bb7c38..0f687ca681 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4031,6 +4031,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php', 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', + 'PhabricatorPeopleLogViewController' => 'applications/people/controller/PhabricatorPeopleLogViewController.php', 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php', 'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php', @@ -10291,6 +10292,7 @@ phutil_register_library_map(array( 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', + 'PhabricatorPeopleLogViewController' => 'PhabricatorPeopleController', 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 'PhabricatorPeopleMailEngine' => 'Phobject', 'PhabricatorPeopleMailEngineException' => 'Exception', diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index 9cc3607930..ec6892d022 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -44,6 +44,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { $this->getQueryRoutePattern() => 'PhabricatorPeopleListController', 'logs/' => array( $this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController', + '(?P\d+)/' => 'PhabricatorPeopleLogViewController', ), 'invite/' => array( '(?:query/(?P[^/]+)/)?' diff --git a/src/applications/people/controller/PhabricatorPeopleLogViewController.php b/src/applications/people/controller/PhabricatorPeopleLogViewController.php new file mode 100644 index 0000000000..faaf4fd5ca --- /dev/null +++ b/src/applications/people/controller/PhabricatorPeopleLogViewController.php @@ -0,0 +1,92 @@ +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; + } + +} diff --git a/src/applications/people/query/PhabricatorPeopleLogQuery.php b/src/applications/people/query/PhabricatorPeopleLogQuery.php index fc6a87b335..203f79579a 100644 --- a/src/applications/people/query/PhabricatorPeopleLogQuery.php +++ b/src/applications/people/query/PhabricatorPeopleLogQuery.php @@ -3,6 +3,7 @@ final class PhabricatorPeopleLogQuery extends PhabricatorCursorPagedPolicyAwareQuery { + private $ids; private $actorPHIDs; private $userPHIDs; private $relatedPHIDs; @@ -12,6 +13,11 @@ final class PhabricatorPeopleLogQuery private $dateCreatedMin; private $dateCreatedMax; + public function withIDs(array $ids) { + $this->ids = $ids; + return $this; + } + public function withActorPHIDs(array $actor_phids) { $this->actorPHIDs = $actor_phids; return $this; @@ -59,6 +65,13 @@ final class PhabricatorPeopleLogQuery protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { $where = parent::buildWhereClauseParts($conn); + if ($this->ids !== null) { + $where[] = qsprintf( + $conn, + 'id IN (%Ld)', + $this->ids); + } + if ($this->actorPHIDs !== null) { $where[] = qsprintf( $conn, diff --git a/src/applications/people/storage/PhabricatorUserLog.php b/src/applications/people/storage/PhabricatorUserLog.php index d433ebca07..61ccaff1ed 100644 --- a/src/applications/people/storage/PhabricatorUserLog.php +++ b/src/applications/people/storage/PhabricatorUserLog.php @@ -100,6 +100,43 @@ final class PhabricatorUserLog extends PhabricatorUserDAO ) + 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 )----------------------------------------- */ diff --git a/src/applications/people/view/PhabricatorUserLogView.php b/src/applications/people/view/PhabricatorUserLogView.php index 5c7e2ac1be..cf728af973 100644 --- a/src/applications/people/view/PhabricatorUserLogView.php +++ b/src/applications/people/view/PhabricatorUserLogView.php @@ -41,33 +41,16 @@ final class PhabricatorUserLogView extends AphrontView { $actor_phid = $log->getActorPHID(); $user_phid = $log->getUserPHID(); - 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) { - $ip = $log->getRemoteAddr(); + $remote_address = $log->getRemoteAddressForViewer($viewer); + if ($remote_address !== null) { if ($base_uri) { - $ip = phutil_tag( + $remote_address = phutil_tag( 'a', array( - 'href' => $base_uri.'?ip='.$ip.'#R', + 'href' => $base_uri.'?ip='.$remote_address.'#R', ), - $ip); + $remote_address); } - } else { - $ip = null; } $action = $log->getAction(); @@ -85,37 +68,47 @@ final class PhabricatorUserLogView extends AphrontView { $user_name = null; } + $action_link = phutil_tag( + 'a', + array( + 'href' => $log->getURI(), + ), + $action_name); + $rows[] = array( - phabricator_date($log->getDateCreated(), $viewer), - phabricator_time($log->getDateCreated(), $viewer), - $action_name, + $log->getID(), + $action_link, $actor_name, $user_name, - $ip, + $remote_address, $session, + phabricator_date($log->getDateCreated(), $viewer), + phabricator_time($log->getDateCreated(), $viewer), ); } $table = new AphrontTableView($rows); $table->setHeaders( array( - pht('Date'), - pht('Time'), + pht('ID'), pht('Action'), pht('Actor'), pht('User'), pht('IP'), pht('Session'), + pht('Date'), + pht('Time'), )); $table->setColumnClasses( array( '', - 'right', 'wide', '', '', '', 'n', + '', + 'right', )); return $table;