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

Clean up "Audit Authority" code, at least mostly

Summary:
Ref T2393. We had three copies of this code ("which packages/projects can a user accept on behalf of?"). I removed one in D17250. This consolidates the other two.

This still isn't perfect and it should probably live in a Query or something some day, but there's some weird stuff going on with the viewer in the editor context, and at least the code handles the viewer correctly now and isn't living somewhere weird and totally unrelated to auditing, and the callsites don't need to do a bunch of extra work.

This also moves towards fixing the "re-accept if you've already accepted but then a new package you have authority over was added" bug, which we fixed recently in Differential. This should be less common in Audit, but should still be fixed.

Test Plan: Viewed and audited commits with a mixture of user, package, and project auditors. Saw actions apply to the expected set of auditors.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T2393

Differential Revision: https://secure.phabricator.com/D17251

+89 -74
-36
src/applications/audit/editor/PhabricatorAuditCommentEditor.php
··· 2 2 3 3 final class PhabricatorAuditCommentEditor extends PhabricatorEditor { 4 4 5 - /** 6 - * Load the PHIDs for all objects the user has the authority to act as an 7 - * audit for. This includes themselves, and any packages they are an owner 8 - * of. 9 - */ 10 - public static function loadAuditPHIDsForUser(PhabricatorUser $user) { 11 - $phids = array(); 12 - 13 - // TODO: This method doesn't really use the right viewer, but in practice we 14 - // never issue this query of this type on behalf of another user and are 15 - // unlikely to do so in the future. This entire method should be refactored 16 - // into a Query class, however, and then we should use a proper viewer. 17 - 18 - // The user can audit on their own behalf. 19 - $phids[$user->getPHID()] = true; 20 - 21 - $owned_packages = id(new PhabricatorOwnersPackageQuery()) 22 - ->setViewer($user) 23 - ->withAuthorityPHIDs(array($user->getPHID())) 24 - ->execute(); 25 - foreach ($owned_packages as $package) { 26 - $phids[$package->getPHID()] = true; 27 - } 28 - 29 - // The user can audit on behalf of all projects they are a member of. 30 - $projects = id(new PhabricatorProjectQuery()) 31 - ->setViewer($user) 32 - ->withMemberPHIDs(array($user->getPHID())) 33 - ->execute(); 34 - foreach ($projects as $project) { 35 - $phids[$project->getPHID()] = true; 36 - } 37 - 38 - return array_keys($phids); 39 - } 40 - 41 5 public static function getMailThreading( 42 6 PhabricatorRepository $repository, 43 7 PhabricatorRepositoryCommit $commit) {
+4
src/applications/audit/editor/PhabricatorAuditEditor.php
··· 78 78 } 79 79 } 80 80 81 + $object->loadAndAttachAuditAuthority( 82 + $this->getActor(), 83 + $this->getActingAsPHID()); 84 + 81 85 return parent::expandTransactions($object, $xactions); 82 86 } 83 87
+7 -15
src/applications/diffusion/controller/DiffusionCommitController.php
··· 4 4 5 5 const CHANGES_LIMIT = 100; 6 6 7 - private $auditAuthorityPHIDs; 8 - private $highlightedAudits; 9 - 10 7 private $commitParents; 11 8 private $commitRefs; 12 9 private $commitMerges; ··· 67 64 } 68 65 69 66 $audit_requests = $commit->getAudits(); 70 - $this->auditAuthorityPHIDs = 71 - PhabricatorAuditCommentEditor::loadAuditPHIDsForUser($viewer); 67 + $commit->loadAndAttachAuditAuthority($viewer); 72 68 73 69 $commit_data = $commit->getCommitData(); 74 70 $is_foreign = $commit_data->getCommitDetail('foreign-svn-stub'); ··· 208 204 209 205 $timeline = $this->buildComments($commit); 210 206 $merge_table = $this->buildMergesTable($commit); 211 - 212 - $highlighted_audits = $commit->getAuthorityAudits( 213 - $viewer, 214 - $this->auditAuthorityPHIDs); 215 207 216 208 $show_changesets = false; 217 209 $info_panel = null; ··· 520 512 if ($user_requests) { 521 513 $view->addProperty( 522 514 pht('Auditors'), 523 - $this->renderAuditStatusView($user_requests)); 515 + $this->renderAuditStatusView($commit, $user_requests)); 524 516 } 525 517 526 518 if ($other_requests) { 527 519 $view->addProperty( 528 520 pht('Group Auditors'), 529 - $this->renderAuditStatusView($other_requests)); 521 + $this->renderAuditStatusView($commit, $other_requests)); 530 522 } 531 523 } 532 524 ··· 848 840 return $file->getRedirectResponse(); 849 841 } 850 842 851 - private function renderAuditStatusView(array $audit_requests) { 843 + private function renderAuditStatusView( 844 + PhabricatorRepositoryCommit $commit, 845 + array $audit_requests) { 852 846 assert_instances_of($audit_requests, 'PhabricatorRepositoryAuditRequest'); 853 847 $viewer = $this->getViewer(); 854 - 855 - $authority_map = array_fill_keys($this->auditAuthorityPHIDs, true); 856 848 857 849 $view = new PHUIStatusListView(); 858 850 foreach ($audit_requests as $request) { ··· 873 865 $target = $viewer->renderHandle($auditor_phid); 874 866 $item->setTarget($target); 875 867 876 - if (isset($authority_map[$auditor_phid])) { 868 + if ($commit->hasAuditAuthority($viewer, $request)) { 877 869 $item->setHighlighted(true); 878 870 } 879 871
+5 -6
src/applications/diffusion/xaction/DiffusionCommitAuditTransaction.php
··· 91 91 $value, 92 92 $status) { 93 93 94 + $actor = $this->getActor(); 95 + $acting_phid = $this->getActingAsPHID(); 96 + 94 97 $audits = $commit->getAudits(); 95 98 $audits = mpull($audits, null, 'getAuditorPHID'); 96 99 ··· 98 101 99 102 $with_authority = ($status != PhabricatorAuditStatusConstants::RESIGNED); 100 103 if ($with_authority) { 101 - $has_authority = PhabricatorAuditCommentEditor::loadAuditPHIDsForUser( 102 - $viewer); 103 - $has_authority = array_fuse($has_authority); 104 104 foreach ($audits as $audit) { 105 - $auditor_phid = $audit->getAuditorPHID(); 106 - if (isset($has_authority[$auditor_phid])) { 107 - $map[$auditor_phid] = $status; 105 + if ($commit->hasAuditAuthority($actor, $audit, $acting_phid)) { 106 + $map[$audit->getAuditorPHID()] = $status; 108 107 } 109 108 } 110 109 }
+73 -17
src/applications/repository/storage/PhabricatorRepositoryCommit.php
··· 41 41 private $repository = self::ATTACHABLE; 42 42 private $customFields = self::ATTACHABLE; 43 43 private $drafts = array(); 44 + private $auditAuthorityPHIDs = array(); 44 45 45 46 public function attachRepository(PhabricatorRepository $repository) { 46 47 $this->repository = $repository; ··· 180 181 return $this->assertAttached($this->audits); 181 182 } 182 183 183 - public function getAuthorityAudits( 184 - PhabricatorUser $user, 185 - array $authority_phids) { 184 + public function loadAndAttachAuditAuthority( 185 + PhabricatorUser $viewer, 186 + $actor_phid = null) { 187 + 188 + if ($actor_phid === null) { 189 + $actor_phid = $viewer->getPHID(); 190 + } 191 + 192 + // TODO: This method is a little weird and sketchy, but worlds better than 193 + // what came before it. Eventually, this should probably live in a Query 194 + // class. 186 195 187 - $authority = array_fill_keys($authority_phids, true); 188 - $audits = $this->getAudits(); 189 - $authority_audits = array(); 190 - foreach ($audits as $audit) { 191 - $has_authority = !empty($authority[$audit->getAuditorPHID()]); 192 - if ($has_authority) { 193 - $commit_author = $this->getAuthorPHID(); 196 + // Figure out which requests the actor has authority over: these are user 197 + // requests where they are the auditor, and packages and projects they are 198 + // a member of. 194 199 195 - // You don't have authority over package and project audits on your 196 - // own commits. 200 + if (!$actor_phid) { 201 + $attach_key = $viewer->getCacheFragment(); 202 + $phids = array(); 203 + } else { 204 + $attach_key = $actor_phid; 205 + // At least currently, when modifying your own commits, you act only on 206 + // behalf of yourself, not your packages/projects -- the idea being that 207 + // you can't accept your own commits. This may change or depend on 208 + // config. 209 + $actor_is_author = ($actor_phid == $this->getAuthorPHID()); 210 + if ($actor_is_author) { 211 + $phids = array($actor_phid); 212 + } else { 213 + $phids = array(); 214 + $phids[$actor_phid] = true; 197 215 198 - $auditor_is_user = ($audit->getAuditorPHID() == $user->getPHID()); 199 - $user_is_author = ($commit_author == $user->getPHID()); 216 + $owned_packages = id(new PhabricatorOwnersPackageQuery()) 217 + ->setViewer($viewer) 218 + ->withAuthorityPHIDs(array($actor_phid)) 219 + ->execute(); 220 + foreach ($owned_packages as $package) { 221 + $phids[$package->getPHID()] = true; 222 + } 200 223 201 - if ($auditor_is_user || !$user_is_author) { 202 - $authority_audits[$audit->getID()] = $audit; 224 + $projects = id(new PhabricatorProjectQuery()) 225 + ->setViewer($viewer) 226 + ->withMemberPHIDs(array($actor_phid)) 227 + ->execute(); 228 + foreach ($projects as $project) { 229 + $phids[$project->getPHID()] = true; 203 230 } 231 + 232 + $phids = array_keys($phids); 204 233 } 205 234 } 206 - return $authority_audits; 235 + 236 + $this->auditAuthorityPHIDs[$attach_key] = array_fuse($phids); 237 + 238 + return $this; 239 + } 240 + 241 + public function hasAuditAuthority( 242 + PhabricatorUser $viewer, 243 + PhabricatorRepositoryAuditRequest $audit, 244 + $actor_phid = null) { 245 + 246 + if ($actor_phid === null) { 247 + $actor_phid = $viewer->getPHID(); 248 + } 249 + 250 + if (!$actor_phid) { 251 + $attach_key = $viewer->getCacheFragment(); 252 + } else { 253 + $attach_key = $actor_phid; 254 + } 255 + 256 + $map = $this->assertAttachedKey($this->auditAuthorityPHIDs, $attach_key); 257 + 258 + if (!$actor_phid) { 259 + return false; 260 + } 261 + 262 + return isset($map[$audit->getAuditorPHID()]); 207 263 } 208 264 209 265 public function getAuditorPHIDsForEdit() {