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

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

+167 -29
+2
src/__phutil_library_map__.php
··· 4031 4031 'PhabricatorPeopleListController' => 'applications/people/controller/PhabricatorPeopleListController.php', 4032 4032 'PhabricatorPeopleLogQuery' => 'applications/people/query/PhabricatorPeopleLogQuery.php', 4033 4033 'PhabricatorPeopleLogSearchEngine' => 'applications/people/query/PhabricatorPeopleLogSearchEngine.php', 4034 + 'PhabricatorPeopleLogViewController' => 'applications/people/controller/PhabricatorPeopleLogViewController.php', 4034 4035 'PhabricatorPeopleLogsController' => 'applications/people/controller/PhabricatorPeopleLogsController.php', 4035 4036 'PhabricatorPeopleMailEngine' => 'applications/people/mail/PhabricatorPeopleMailEngine.php', 4036 4037 'PhabricatorPeopleMailEngineException' => 'applications/people/mail/PhabricatorPeopleMailEngineException.php', ··· 10291 10292 'PhabricatorPeopleListController' => 'PhabricatorPeopleController', 10292 10293 'PhabricatorPeopleLogQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', 10293 10294 'PhabricatorPeopleLogSearchEngine' => 'PhabricatorApplicationSearchEngine', 10295 + 'PhabricatorPeopleLogViewController' => 'PhabricatorPeopleController', 10294 10296 'PhabricatorPeopleLogsController' => 'PhabricatorPeopleController', 10295 10297 'PhabricatorPeopleMailEngine' => 'Phobject', 10296 10298 'PhabricatorPeopleMailEngineException' => 'Exception',
+1
src/applications/people/application/PhabricatorPeopleApplication.php
··· 44 44 $this->getQueryRoutePattern() => 'PhabricatorPeopleListController', 45 45 'logs/' => array( 46 46 $this->getQueryRoutePattern() => 'PhabricatorPeopleLogsController', 47 + '(?P<id>\d+)/' => 'PhabricatorPeopleLogViewController', 47 48 ), 48 49 'invite/' => array( 49 50 '(?:query/(?P<queryKey>[^/]+)/)?'
+92
src/applications/people/controller/PhabricatorPeopleLogViewController.php
··· 1 + <?php 2 + 3 + final class PhabricatorPeopleLogViewController 4 + extends PhabricatorPeopleController { 5 + 6 + public function shouldRequireAdmin() { 7 + return false; 8 + } 9 + 10 + public function handleRequest(AphrontRequest $request) { 11 + $viewer = $this->getViewer(); 12 + $id = $request->getURIData('id'); 13 + 14 + $log = id(new PhabricatorPeopleLogQuery()) 15 + ->setViewer($viewer) 16 + ->withIDs(array($id)) 17 + ->executeOne(); 18 + if (!$log) { 19 + return new Aphront404Response(); 20 + } 21 + 22 + $logs_uri = $this->getApplicationURI('logs/'); 23 + 24 + $crumbs = $this->buildApplicationCrumbs() 25 + ->addTextCrumb(pht('Activity Logs'), $logs_uri) 26 + ->addTextCrumb($log->getObjectName()) 27 + ->setBorder(true); 28 + 29 + $header = $this->buildHeaderView($log); 30 + $properties = $this->buildPropertiesView($log); 31 + 32 + $view = id(new PHUITwoColumnView()) 33 + ->setHeader($header) 34 + ->addPropertySection(pht('Details'), $properties); 35 + 36 + return $this->newPage() 37 + ->setCrumbs($crumbs) 38 + ->setTitle($log->getObjectName()) 39 + ->appendChild($view); 40 + } 41 + 42 + private function buildHeaderView(PhabricatorUserLog $log) { 43 + $viewer = $this->getViewer(); 44 + 45 + $view = id(new PHUIHeaderView()) 46 + ->setViewer($viewer) 47 + ->setHeader($log->getObjectName()); 48 + 49 + return $view; 50 + } 51 + 52 + private function buildPropertiesView(PhabricatorUserLog $log) { 53 + $viewer = $this->getViewer(); 54 + 55 + $view = id(new PHUIPropertyListView()) 56 + ->setViewer($viewer); 57 + 58 + $type_map = PhabricatorUserLogType::getAllLogTypes(); 59 + $type_map = mpull($type_map, 'getLogTypeName', 'getLogTypeKey'); 60 + 61 + $action = $log->getAction(); 62 + $type_name = idx($type_map, $action, $action); 63 + 64 + $view->addProperty(pht('Event Type'), $type_name); 65 + 66 + $view->addProperty( 67 + pht('Event Date'), 68 + phabricator_datetime($log->getDateCreated(), $viewer)); 69 + 70 + $actor_phid = $log->getActorPHID(); 71 + if ($actor_phid) { 72 + $view->addProperty( 73 + pht('Acting User'), 74 + $viewer->renderHandle($actor_phid)); 75 + } 76 + 77 + $user_phid = $log->getUserPHID(); 78 + if ($user_phid) { 79 + $view->addProperty( 80 + pht('Affected User'), 81 + $viewer->renderHandle($user_phid)); 82 + } 83 + 84 + $remote_address = $log->getRemoteAddressForViewer($viewer); 85 + if ($remote_address !== null) { 86 + $view->addProperty(pht('Remote Address'), $remote_address); 87 + } 88 + 89 + return $view; 90 + } 91 + 92 + }
+13
src/applications/people/query/PhabricatorPeopleLogQuery.php
··· 3 3 final class PhabricatorPeopleLogQuery 4 4 extends PhabricatorCursorPagedPolicyAwareQuery { 5 5 6 + private $ids; 6 7 private $actorPHIDs; 7 8 private $userPHIDs; 8 9 private $relatedPHIDs; ··· 11 12 private $remoteAddressPrefix; 12 13 private $dateCreatedMin; 13 14 private $dateCreatedMax; 15 + 16 + public function withIDs(array $ids) { 17 + $this->ids = $ids; 18 + return $this; 19 + } 14 20 15 21 public function withActorPHIDs(array $actor_phids) { 16 22 $this->actorPHIDs = $actor_phids; ··· 58 64 59 65 protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) { 60 66 $where = parent::buildWhereClauseParts($conn); 67 + 68 + if ($this->ids !== null) { 69 + $where[] = qsprintf( 70 + $conn, 71 + 'id IN (%Ld)', 72 + $this->ids); 73 + } 61 74 62 75 if ($this->actorPHIDs !== null) { 63 76 $where[] = qsprintf(
+37
src/applications/people/storage/PhabricatorUserLog.php
··· 100 100 ) + parent::getConfiguration(); 101 101 } 102 102 103 + public function getURI() { 104 + return urisprintf('/people/logs/%s/', $this->getID()); 105 + } 106 + 107 + public function getObjectName() { 108 + return pht('Activity Log %d', $this->getID()); 109 + } 110 + 111 + public function getRemoteAddressForViewer(PhabricatorUser $viewer) { 112 + $viewer_phid = $viewer->getPHID(); 113 + $actor_phid = $this->getActorPHID(); 114 + $user_phid = $this->getUserPHID(); 115 + 116 + if (!$viewer_phid) { 117 + $can_see_ip = false; 118 + } else if ($viewer->getIsAdmin()) { 119 + $can_see_ip = true; 120 + } else if ($viewer_phid == $actor_phid) { 121 + // You can see the address if you took the action. 122 + $can_see_ip = true; 123 + } else if (!$actor_phid && ($viewer_phid == $user_phid)) { 124 + // You can see the address if it wasn't authenticated and applied 125 + // to you (partial login). 126 + $can_see_ip = true; 127 + } else { 128 + // You can't see the address when an administrator disables your 129 + // account, since it's their address. 130 + $can_see_ip = false; 131 + } 132 + 133 + if (!$can_see_ip) { 134 + return null; 135 + } 136 + 137 + return $this->getRemoteAddr(); 138 + } 139 + 103 140 104 141 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 105 142
+22 -29
src/applications/people/view/PhabricatorUserLogView.php
··· 41 41 $actor_phid = $log->getActorPHID(); 42 42 $user_phid = $log->getUserPHID(); 43 43 44 - if ($viewer->getIsAdmin()) { 45 - $can_see_ip = true; 46 - } else if ($viewer_phid == $actor_phid) { 47 - // You can see the address if you took the action. 48 - $can_see_ip = true; 49 - } else if (!$actor_phid && ($viewer_phid == $user_phid)) { 50 - // You can see the address if it wasn't authenticated and applied 51 - // to you (partial login). 52 - $can_see_ip = true; 53 - } else { 54 - // You can't see the address when an administrator disables your 55 - // account, since it's their address. 56 - $can_see_ip = false; 57 - } 58 - 59 - if ($can_see_ip) { 60 - $ip = $log->getRemoteAddr(); 44 + $remote_address = $log->getRemoteAddressForViewer($viewer); 45 + if ($remote_address !== null) { 61 46 if ($base_uri) { 62 - $ip = phutil_tag( 47 + $remote_address = phutil_tag( 63 48 'a', 64 49 array( 65 - 'href' => $base_uri.'?ip='.$ip.'#R', 50 + 'href' => $base_uri.'?ip='.$remote_address.'#R', 66 51 ), 67 - $ip); 52 + $remote_address); 68 53 } 69 - } else { 70 - $ip = null; 71 54 } 72 55 73 56 $action = $log->getAction(); ··· 85 68 $user_name = null; 86 69 } 87 70 71 + $action_link = phutil_tag( 72 + 'a', 73 + array( 74 + 'href' => $log->getURI(), 75 + ), 76 + $action_name); 77 + 88 78 $rows[] = array( 89 - phabricator_date($log->getDateCreated(), $viewer), 90 - phabricator_time($log->getDateCreated(), $viewer), 91 - $action_name, 79 + $log->getID(), 80 + $action_link, 92 81 $actor_name, 93 82 $user_name, 94 - $ip, 83 + $remote_address, 95 84 $session, 85 + phabricator_date($log->getDateCreated(), $viewer), 86 + phabricator_time($log->getDateCreated(), $viewer), 96 87 ); 97 88 } 98 89 99 90 $table = new AphrontTableView($rows); 100 91 $table->setHeaders( 101 92 array( 102 - pht('Date'), 103 - pht('Time'), 93 + pht('ID'), 104 94 pht('Action'), 105 95 pht('Actor'), 106 96 pht('User'), 107 97 pht('IP'), 108 98 pht('Session'), 99 + pht('Date'), 100 + pht('Time'), 109 101 )); 110 102 $table->setColumnClasses( 111 103 array( 112 104 '', 113 - 'right', 114 105 'wide', 115 106 '', 116 107 '', 117 108 '', 118 109 'n', 110 + '', 111 + 'right', 119 112 )); 120 113 121 114 return $table;