From 1667acfa5d7148b7e465649ddbd17680d0911a66 Mon Sep 17 00:00:00 2001 From: epriestley Date: Mon, 25 Nov 2019 15:01:45 -0800 Subject: [PATCH] Implement "PolicyInterface" on "UserEmail" so "EmailQuery" can load them properly Summary: See PHI1558. Ref T11860. Ref T13444. I partly implemented PHIDs for "UserEmail" objects, but they can't load on their own so you can't directly `bin/remove destroy` them yet. Allow them to actually load by implementing "PolicyInterface". Addresses are viewable and editable by the associated user, unless they are a bot/list address, in which case they are viewable and editable by administrators (in preparation for T11860). This has no real impact on anything today. Test Plan: - Used `bin/remove destroy ` to destroy an individual email address. - Before: error while loading the object by PHID in the query policy layer. - After: clean load and destroy. Maniphest Tasks: T13444, T11860 Differential Revision: https://secure.phabricator.com/D20927 --- src/__phutil_library_map__.php | 1 + .../PhabricatorPeopleUserEmailPHIDType.php | 6 +++ .../query/PhabricatorPeopleUserEmailQuery.php | 26 +++++++++++++ .../people/storage/PhabricatorUserEmail.php | 39 ++++++++++++++++++- 4 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index f26f36d52e..174c0e4876 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -11690,6 +11690,7 @@ phutil_register_library_map(array( 'PhabricatorUserEmail' => array( 'PhabricatorUserDAO', 'PhabricatorDestructibleInterface', + 'PhabricatorPolicyInterface', ), 'PhabricatorUserEmailTestCase' => 'PhabricatorTestCase', 'PhabricatorUserEmpowerTransaction' => 'PhabricatorUserTransactionType', diff --git a/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php b/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php index 0aadc149f6..e0f0478033 100644 --- a/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php +++ b/src/applications/people/phid/PhabricatorPeopleUserEmailPHIDType.php @@ -29,6 +29,12 @@ final class PhabricatorPeopleUserEmailPHIDType PhabricatorHandleQuery $query, array $handles, array $objects) { + + foreach ($handles as $phid => $handle) { + $email = $objects[$phid]; + $handle->setName($email->getAddress()); + } + return null; } diff --git a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php index f0330f34f9..6e2627a96d 100644 --- a/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php +++ b/src/applications/people/query/PhabricatorPeopleUserEmailQuery.php @@ -48,6 +48,32 @@ final class PhabricatorPeopleUserEmailQuery return $where; } + protected function willLoadPage(array $page) { + + $user_phids = mpull($page, 'getUserPHID'); + + $users = id(new PhabricatorPeopleQuery()) + ->setViewer($this->getViewer()) + ->setParentQuery($this) + ->withPHIDs($user_phids) + ->execute(); + $users = mpull($users, null, 'getPHID'); + + foreach ($page as $key => $address) { + $user = idx($users, $address->getUserPHID()); + + if (!$user) { + unset($page[$key]); + $this->didRejectResult($address); + continue; + } + + $address->attachUser($user); + } + + return $page; + } + public function getQueryApplicationClass() { return 'PhabricatorPeopleApplication'; } diff --git a/src/applications/people/storage/PhabricatorUserEmail.php b/src/applications/people/storage/PhabricatorUserEmail.php index cf2c61dc03..4e43b2fb41 100644 --- a/src/applications/people/storage/PhabricatorUserEmail.php +++ b/src/applications/people/storage/PhabricatorUserEmail.php @@ -6,7 +6,9 @@ */ final class PhabricatorUserEmail extends PhabricatorUserDAO - implements PhabricatorDestructibleInterface { + implements + PhabricatorDestructibleInterface, + PhabricatorPolicyInterface { protected $userPHID; protected $address; @@ -14,6 +16,8 @@ final class PhabricatorUserEmail protected $isPrimary; protected $verificationCode; + private $user = self::ATTACHABLE; + const MAX_ADDRESS_LENGTH = 128; protected function getConfiguration() { @@ -52,6 +56,15 @@ final class PhabricatorUserEmail return parent::save(); } + public function attachUser(PhabricatorUser $user) { + $this->user = $user; + return $this; + } + + public function getUser() { + return $this->assertAttached($this->user); + } + /* -( Domain Restrictions )------------------------------------------------ */ @@ -287,4 +300,28 @@ final class PhabricatorUserEmail $this->delete(); } + +/* -( PhabricatorPolicyInterface )----------------------------------------- */ + + public function getCapabilities() { + return array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + ); + } + + public function getPolicy($capability) { + $user = $this->getUser(); + + if ($this->getIsSystemAgent() || $this->getIsMailingList()) { + return PhabricatorPolicies::POLICY_ADMIN; + } + + return $user->getPHID(); + } + + public function hasAutomaticCapability($capability, PhabricatorUser $viewer) { + return false; + } + }