From 0ec83132a8ecf52109c757edf7d2d5259d6e2dc8 Mon Sep 17 00:00:00 2001 From: epriestley Date: Thu, 25 Jan 2018 17:48:42 -0800 Subject: [PATCH] Support basic export of user accounts Summary: Depends on D18934. Ref T13046. Add support for the new export flow to a second application. My goal here is mostly just to make sure that this is general enough to work in more than one place, and exporting user accounts seems plausible as a useful feature, although we do see occasional requests for this feature exactly (like ). The exported data may not truly be useful for much (no disabled/admin/verified/MFA flags, no external account data, no email addresses for policy reasons) but we can expand it as use cases arise. Test Plan: Exported user accounts in several formats. Reviewers: amckinley Reviewed By: amckinley Maniphest Tasks: T13046 Differential Revision: https://secure.phabricator.com/D18935 --- .../base/PhabricatorApplication.php | 2 +- .../PhabricatorPeopleApplication.php | 4 +- .../PhabricatorPeopleListController.php | 2 +- .../query/PhabricatorPeopleSearchEngine.php | 37 +++++++++++++++++++ ...PhabricatorApplicationSearchController.php | 9 +++-- 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/applications/base/PhabricatorApplication.php b/src/applications/base/PhabricatorApplication.php index 4062e4e2fe..420d126507 100644 --- a/src/applications/base/PhabricatorApplication.php +++ b/src/applications/base/PhabricatorApplication.php @@ -623,7 +623,7 @@ abstract class PhabricatorApplication } protected function getQueryRoutePattern($base = null) { - return $base.'(?:query/(?P[^/]+)/(?:(?P[^/]+)/))?'; + return $base.'(?:query/(?P[^/]+)/(?:(?P[^/]+)/)?)?'; } protected function getProfileMenuRouting($controller) { diff --git a/src/applications/people/application/PhabricatorPeopleApplication.php b/src/applications/people/application/PhabricatorPeopleApplication.php index dde82f1d3a..28405ca92c 100644 --- a/src/applications/people/application/PhabricatorPeopleApplication.php +++ b/src/applications/people/application/PhabricatorPeopleApplication.php @@ -41,7 +41,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { public function getRoutes() { return array( '/people/' => array( - '(query/(?P[^/]+)/)?' => 'PhabricatorPeopleListController', + $this->getQueryRoutePattern() => 'PhabricatorPeopleListController', 'logs/(?:query/(?P[^/]+)/)?' => 'PhabricatorPeopleLogsController', 'invite/' => array( @@ -76,7 +76,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication { 'PhabricatorPeopleProfilePictureController', 'manage/(?P[1-9]\d*)/' => 'PhabricatorPeopleProfileManageController', - ), + ), '/p/(?P[\w._-]+)/' => array( '' => 'PhabricatorPeopleProfileViewController', 'item/' => $this->getProfileMenuRouting( diff --git a/src/applications/people/controller/PhabricatorPeopleListController.php b/src/applications/people/controller/PhabricatorPeopleListController.php index edcfc7ba0f..511899070c 100644 --- a/src/applications/people/controller/PhabricatorPeopleListController.php +++ b/src/applications/people/controller/PhabricatorPeopleListController.php @@ -16,7 +16,7 @@ final class PhabricatorPeopleListController PeopleBrowseUserDirectoryCapability::CAPABILITY); $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($request->getURIData('key')) + ->setQueryKey($request->getURIData('queryKey')) ->setSearchEngine(new PhabricatorPeopleSearchEngine()) ->setNavigation($this->buildSideNavView()); diff --git a/src/applications/people/query/PhabricatorPeopleSearchEngine.php b/src/applications/people/query/PhabricatorPeopleSearchEngine.php index 0a4367d367..db2256a8b8 100644 --- a/src/applications/people/query/PhabricatorPeopleSearchEngine.php +++ b/src/applications/people/query/PhabricatorPeopleSearchEngine.php @@ -320,4 +320,41 @@ final class PhabricatorPeopleSearchEngine return $result; } + protected function newExportFields() { + return array( + id(new PhabricatorIDExportField()) + ->setKey('id') + ->setLabel(pht('ID')), + id(new PhabricatorPHIDExportField()) + ->setKey('phid') + ->setLabel(pht('PHID')), + id(new PhabricatorStringExportField()) + ->setKey('username') + ->setLabel(pht('Username')), + id(new PhabricatorStringExportField()) + ->setKey('realName') + ->setLabel(pht('Real Name')), + id(new PhabricatorEpochExportField()) + ->setKey('created') + ->setLabel(pht('Date Created')), + ); + } + + public function newExport(array $users) { + $viewer = $this->requireViewer(); + + $export = array(); + foreach ($users as $user) { + $export[] = array( + 'id' => $user->getID(), + 'phid' => $user->getPHID(), + 'username' => $user->getUsername(), + 'realName' => $user->getRealName(), + 'created' => $user->getDateCreated(), + ); + } + + return $export; + } + } diff --git a/src/applications/search/controller/PhabricatorApplicationSearchController.php b/src/applications/search/controller/PhabricatorApplicationSearchController.php index d241a046a1..d3b05d1e3e 100644 --- a/src/applications/search/controller/PhabricatorApplicationSearchController.php +++ b/src/applications/search/controller/PhabricatorApplicationSearchController.php @@ -396,9 +396,12 @@ final class PhabricatorApplicationSearchController ->setViewer($viewer) ->withQueryKeys(array($query_key)) ->executeOne(); - if (!$saved_query) { - return new Aphront404Response(); - } + } else { + $saved_query = null; + } + + if (!$saved_query) { + return new Aphront404Response(); } $cancel_uri = $engine->getQueryResultsPageURI($query_key);