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

Add an "Authority" control to Packages to support "Watcher" packages

Summary: See T13657. An install has "watcher" packages which should not allow owners to "Force Accept" other packages.

Test Plan:
- Created package A, which I own, on "/", with "Weak" authority.
- Created package B, which I do not own, on "/src".
- Created a revision which touches "/src" and added package B as a reviewer.
- Attempted to accept the revision...
- Before patch: permitted to "Force Accept" for package B.
- After patch: not allowed to "Force Accept" for package B.
- Verified that setting package "A" back to "Strong" authority allows a force-accept for package B.

Subscribers: PHID-OPKG-gm6ozazyms6q6i22gyam

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

+148
+2
resources/sql/autopatches/20210625.owners.01.authority.sql
··· 1 + ALTER TABLE {$NAMESPACE}_owners.owners_package 2 + ADD authorityMode VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT};
+3
resources/sql/autopatches/20210625.owners.02.authority-default.sql
··· 1 + UPDATE {$NAMESPACE}_owners.owners_package 2 + SET authorityMode = 'strong' 3 + WHERE authorityMode = '';
+2
src/__phutil_library_map__.php
··· 3966 3966 'PhabricatorOwnersOwner' => 'applications/owners/storage/PhabricatorOwnersOwner.php', 3967 3967 'PhabricatorOwnersPackage' => 'applications/owners/storage/PhabricatorOwnersPackage.php', 3968 3968 'PhabricatorOwnersPackageAuditingTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageAuditingTransaction.php', 3969 + 'PhabricatorOwnersPackageAuthorityTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageAuthorityTransaction.php', 3969 3970 'PhabricatorOwnersPackageAutoreviewTransaction' => 'applications/owners/xaction/PhabricatorOwnersPackageAutoreviewTransaction.php', 3970 3971 'PhabricatorOwnersPackageContextFreeGrammar' => 'applications/owners/lipsum/PhabricatorOwnersPackageContextFreeGrammar.php', 3971 3972 'PhabricatorOwnersPackageDatasource' => 'applications/owners/typeahead/PhabricatorOwnersPackageDatasource.php', ··· 10582 10583 'PhabricatorNgramsInterface', 10583 10584 ), 10584 10585 'PhabricatorOwnersPackageAuditingTransaction' => 'PhabricatorOwnersPackageTransactionType', 10586 + 'PhabricatorOwnersPackageAuthorityTransaction' => 'PhabricatorOwnersPackageTransactionType', 10585 10587 'PhabricatorOwnersPackageAutoreviewTransaction' => 'PhabricatorOwnersPackageTransactionType', 10586 10588 'PhabricatorOwnersPackageContextFreeGrammar' => 'PhutilContextFreeGrammar', 10587 10589 'PhabricatorOwnersPackageDatasource' => 'PhabricatorTypeaheadDatasource',
+8
src/applications/differential/storage/DifferentialRevision.php
··· 311 311 // which the actor may be able to use their authority over to gain the 312 312 // ability to force-accept for other packages. This query doesn't apply 313 313 // dominion rules yet, and we'll bypass those rules later on. 314 + 315 + // See T13657. We ignore "watcher" packages which don't grant their owners 316 + // permission to force accept anything. 317 + 314 318 $authority_query = id(new PhabricatorOwnersPackageQuery()) 315 319 ->setViewer($viewer) 316 320 ->withStatuses(array(PhabricatorOwnersPackage::STATUS_ACTIVE)) 321 + ->withAuthorityModes( 322 + array( 323 + PhabricatorOwnersPackage::AUTHORITY_STRONG, 324 + )) 317 325 ->withAuthorityPHIDs(array($viewer->getPHID())) 318 326 ->withControl($repository_phid, $paths); 319 327 $authority_packages = $authority_query->execute();
+6
src/applications/owners/controller/PhabricatorOwnersDetailController.php
··· 197 197 $name = idx($spec, 'short', $dominion); 198 198 $view->addProperty(pht('Dominion'), $name); 199 199 200 + $authority_mode = $package->getAuthorityMode(); 201 + $authority_map = PhabricatorOwnersPackage::getAuthorityOptionsMap(); 202 + $spec = idx($authority_map, $authority_mode, array()); 203 + $name = idx($spec, 'short', $authority_mode); 204 + $view->addProperty(pht('Authority'), $name); 205 + 200 206 $auto = $package->getAutoReview(); 201 207 $autoreview_map = PhabricatorOwnersPackage::getAutoreviewOptionsMap(); 202 208 $spec = idx($autoreview_map, $auto, array());
+13
src/applications/owners/editor/PhabricatorOwnersPackageEditEngine.php
··· 90 90 $dominion_map = PhabricatorOwnersPackage::getDominionOptionsMap(); 91 91 $dominion_map = ipull($dominion_map, 'name'); 92 92 93 + $authority_map = PhabricatorOwnersPackage::getAuthorityOptionsMap(); 94 + $authority_map = ipull($authority_map, 'name'); 95 + 93 96 return array( 94 97 id(new PhabricatorTextEditField()) 95 98 ->setKey('name') ··· 118 121 ->setIsCopyable(true) 119 122 ->setValue($object->getDominion()) 120 123 ->setOptions($dominion_map), 124 + id(new PhabricatorSelectEditField()) 125 + ->setKey('authority') 126 + ->setLabel(pht('Authority')) 127 + ->setDescription( 128 + pht('Change package authority rules.')) 129 + ->setTransactionType( 130 + PhabricatorOwnersPackageAuthorityTransaction::TRANSACTIONTYPE) 131 + ->setIsCopyable(true) 132 + ->setValue($object->getAuthorityMode()) 133 + ->setOptions($authority_map), 121 134 id(new PhabricatorSelectEditField()) 122 135 ->setKey('autoReview') 123 136 ->setLabel(pht('Auto Review'))
+13
src/applications/owners/query/PhabricatorOwnersPackageQuery.php
··· 10 10 private $repositoryPHIDs; 11 11 private $paths; 12 12 private $statuses; 13 + private $authorityModes; 13 14 14 15 private $controlMap = array(); 15 16 private $controlResults; ··· 74 75 // We need to load paths to execute control queries. 75 76 $this->needPaths = true; 76 77 78 + return $this; 79 + } 80 + 81 + public function withAuthorityModes(array $modes) { 82 + $this->authorityModes = $modes; 77 83 return $this; 78 84 } 79 85 ··· 229 235 $indexes); 230 236 } 231 237 $where[] = qsprintf($conn, '%LO', $clauses); 238 + } 239 + 240 + if ($this->authorityModes !== null) { 241 + $where[] = qsprintf( 242 + $conn, 243 + 'authorityMode IN (%Ls)', 244 + $this->authorityModes); 232 245 } 233 246 234 247 return $where;
+45
src/applications/owners/storage/PhabricatorOwnersPackage.php
··· 21 21 protected $dominion; 22 22 protected $properties = array(); 23 23 protected $auditingState; 24 + protected $authorityMode; 24 25 25 26 private $paths = self::ATTACHABLE; 26 27 private $owners = self::ATTACHABLE; ··· 41 42 const DOMINION_STRONG = 'strong'; 42 43 const DOMINION_WEAK = 'weak'; 43 44 45 + const AUTHORITY_STRONG = 'strong'; 46 + const AUTHORITY_WEAK = 'weak'; 47 + 44 48 const PROPERTY_IGNORED = 'ignored'; 45 49 46 50 public static function initializeNewPackage(PhabricatorUser $actor) { ··· 58 62 ->setAuditingState(PhabricatorOwnersAuditRule::AUDITING_NONE) 59 63 ->setAutoReview(self::AUTOREVIEW_NONE) 60 64 ->setDominion(self::DOMINION_STRONG) 65 + ->setAuthorityMode(self::AUTHORITY_STRONG) 61 66 ->setViewPolicy($view_policy) 62 67 ->setEditPolicy($edit_policy) 63 68 ->attachPaths(array()) ··· 115 120 ); 116 121 } 117 122 123 + public static function getAuthorityOptionsMap() { 124 + return array( 125 + self::AUTHORITY_STRONG => array( 126 + 'name' => pht('Strong (Package Owns Paths)'), 127 + 'short' => pht('Strong'), 128 + ), 129 + self::AUTHORITY_WEAK => array( 130 + 'name' => pht('Weak (Package Watches Paths)'), 131 + 'short' => pht('Weak'), 132 + ), 133 + ); 134 + } 135 + 118 136 protected function getConfiguration() { 119 137 return array( 120 138 // This information is better available from the history table. ··· 130 148 'status' => 'text32', 131 149 'autoReview' => 'text32', 132 150 'dominion' => 'text32', 151 + 'authorityMode' => 'text32', 133 152 ), 134 153 ) + parent::getConfiguration(); 135 154 } ··· 568 587 return PhabricatorOwnersAuditRule::newFromState($this->getAuditingState()); 569 588 } 570 589 590 + public function getHasStrongAuthority() { 591 + return ($this->getAuthorityMode() === self::AUTHORITY_STRONG); 592 + } 593 + 571 594 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 572 595 573 596 ··· 697 720 ->setType('map<string, wild>') 698 721 ->setDescription(pht('Dominion setting information.')), 699 722 id(new PhabricatorConduitSearchFieldSpecification()) 723 + ->setKey('authority') 724 + ->setType('map<string, wild>') 725 + ->setDescription(pht('Authority setting information.')), 726 + id(new PhabricatorConduitSearchFieldSpecification()) 700 727 ->setKey('ignored') 701 728 ->setType('map<string, wild>') 702 729 ->setDescription(pht('Ignored attribute information.')), ··· 747 774 'short' => $dominion_short, 748 775 ); 749 776 777 + 778 + $authority_value = $this->getAuthorityMode(); 779 + $authority_map = self::getAuthorityOptionsMap(); 780 + if (isset($authority_map[$authority_value])) { 781 + $authority_label = $authority_map[$authority_value]['name']; 782 + $authority_short = $authority_map[$authority_value]['short']; 783 + } else { 784 + $authority_label = pht('Unknown ("%s")', $authority_value); 785 + $authority_short = pht('Unknown ("%s")', $authority_value); 786 + } 787 + 788 + $authority = array( 789 + 'value' => $authority_value, 790 + 'label' => $authority_label, 791 + 'short' => $authority_short, 792 + ); 793 + 750 794 // Force this to always emit as a JSON object even if empty, never as 751 795 // a JSON list. 752 796 $ignored = $this->getIgnoredPathAttributes(); ··· 762 806 'review' => $review, 763 807 'audit' => $audit, 764 808 'dominion' => $dominion, 809 + 'authority' => $authority, 765 810 'ignored' => $ignored, 766 811 ); 767 812 }
+56
src/applications/owners/xaction/PhabricatorOwnersPackageAuthorityTransaction.php
··· 1 + <?php 2 + 3 + final class PhabricatorOwnersPackageAuthorityTransaction 4 + extends PhabricatorOwnersPackageTransactionType { 5 + 6 + const TRANSACTIONTYPE = 'owners.authority'; 7 + 8 + public function generateOldValue($object) { 9 + return $object->getAuthorityMode(); 10 + } 11 + 12 + public function validateTransactions($object, array $xactions) { 13 + $errors = array(); 14 + 15 + $map = PhabricatorOwnersPackage::getAuthorityOptionsMap(); 16 + foreach ($xactions as $xaction) { 17 + $new = $xaction->getNewValue(); 18 + 19 + if (empty($map[$new])) { 20 + $valid = array_keys($map); 21 + 22 + $errors[] = $this->newInvalidError( 23 + pht( 24 + 'Authority setting "%s" is not valid. '. 25 + 'Valid settings are: %s.', 26 + $new, 27 + implode(', ', $valid)), 28 + $xaction); 29 + } 30 + } 31 + 32 + return $errors; 33 + } 34 + 35 + public function applyInternalEffects($object, $value) { 36 + $object->setAuthorityMode($value); 37 + } 38 + 39 + public function getTitle() { 40 + $map = PhabricatorOwnersPackage::getAuthorityOptionsMap(); 41 + $map = ipull($map, 'short'); 42 + 43 + $old = $this->getOldValue(); 44 + $new = $this->getNewValue(); 45 + 46 + $old = idx($map, $old, $old); 47 + $new = idx($map, $new, $new); 48 + 49 + return pht( 50 + '%s adjusted package authority rules from %s to %s.', 51 + $this->renderAuthor(), 52 + $this->renderValue($old), 53 + $this->renderValue($new)); 54 + } 55 + 56 + }