@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
at upstream/main 287 lines 8.0 kB view raw
1<?php 2 3final class PhabricatorPolicyExplainController 4 extends PhabricatorPolicyController { 5 6 public function shouldAllowPublic() { 7 return true; 8 } 9 10 public function handleRequest(AphrontRequest $request) { 11 $viewer = $this->getViewer(); 12 13 $phid = $request->getURIData('phid'); 14 $capability = $request->getURIData('capability'); 15 16 $object = id(new PhabricatorObjectQuery()) 17 ->setViewer($viewer) 18 ->withPHIDs(array($phid)) 19 ->executeOne(); 20 if (!$object) { 21 return new Aphront404Response(); 22 } 23 24 $policies = PhabricatorPolicyQuery::loadPolicies( 25 $viewer, 26 $object); 27 28 $policy = idx($policies, $capability); 29 if (!$policy) { 30 return new Aphront404Response(); 31 } 32 33 $handle = id(new PhabricatorHandleQuery()) 34 ->setViewer($viewer) 35 ->withPHIDs(array($phid)) 36 ->executeOne(); 37 38 $object_name = $handle->getName(); 39 $object_uri = nonempty($handle->getURI(), '/'); 40 41 $dialog = id(new AphrontDialogView()) 42 ->setUser($viewer) 43 ->setClass('aphront-access-dialog aphront-policy-explain-dialog') 44 ->setTitle(pht('Policy Details: %s', $object_name)) 45 ->addCancelButton($object_uri, pht('Done')); 46 47 $space_section = $this->buildSpaceSection( 48 $object, 49 $policy, 50 $capability); 51 52 $extended_section = $this->buildExtendedSection( 53 $object, 54 $capability); 55 56 $exceptions_section = $this->buildExceptionsSection( 57 $object, 58 $capability); 59 60 $object_section = $this->buildObjectSection( 61 $object, 62 $policy, 63 $capability, 64 $handle); 65 66 $dialog->appendChild( 67 array( 68 $space_section, 69 $extended_section, 70 $exceptions_section, 71 $object_section, 72 )); 73 74 75 return $dialog; 76 } 77 78 private function buildSpaceSection( 79 PhabricatorPolicyInterface $object, 80 PhabricatorPolicy $policy, 81 $capability) { 82 $viewer = $this->getViewer(); 83 84 if (!($object instanceof PhabricatorSpacesInterface)) { 85 return null; 86 } 87 88 if (!PhabricatorSpacesNamespaceQuery::getSpacesExist()) { 89 return null; 90 } 91 92 $space_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID( 93 $object); 94 95 $spaces = PhabricatorSpacesNamespaceQuery::getViewerSpaces($viewer); 96 $space = idx($spaces, $space_phid); 97 if (!$space) { 98 return null; 99 } 100 101 $space_policies = PhabricatorPolicyQuery::loadPolicies($viewer, $space); 102 $space_policy = idx($space_policies, PhabricatorPolicyCapability::CAN_VIEW); 103 if (!$space_policy) { 104 return null; 105 } 106 107 $doc_href = PhabricatorEnv::getDoclink('Spaces User Guide'); 108 $capability_name = $this->getCapabilityName($capability); 109 110 $space_section = id(new PHUIPolicySectionView()) 111 ->setViewer($viewer) 112 ->setIcon('fa-th-large bluegrey') 113 ->setHeader(pht('Space')) 114 ->setDocumentationLink(pht('Spaces Documentation'), $doc_href) 115 ->appendList( 116 array( 117 array( 118 phutil_tag('strong', array(), pht('Space:')), 119 ' ', 120 $viewer->renderHandle($space_phid)->setAsTag(true), 121 ), 122 array( 123 phutil_tag('strong', array(), pht('%s:', $capability_name)), 124 ' ', 125 $space_policy->getShortName(), 126 ), 127 )) 128 ->appendParagraph( 129 pht( 130 'This object is in %s and can only be seen or edited by users '. 131 'with access to view objects in the space.', 132 $viewer->renderHandle($space_phid))); 133 134 $space_explanation = PhabricatorPolicy::getPolicyExplanation( 135 $viewer, 136 $space_policy->getPHID()); 137 $items = array(); 138 $items[] = $space_explanation; 139 140 $space_section 141 ->appendParagraph(pht('Users who can see objects in this space:')) 142 ->appendList($items); 143 144 $view_capability = PhabricatorPolicyCapability::CAN_VIEW; 145 if ($capability == $view_capability) { 146 $stronger = $space_policy->isStrongerThan($policy); 147 if ($stronger) { 148 $space_section->appendHint( 149 pht( 150 'The space this object is in has a more restrictive view '. 151 'policy ("%s") than the object does ("%s"), so the space\'s '. 152 'view policy is shown as a hint instead of the object policy.', 153 $space_policy->getShortName(), 154 $policy->getShortName())); 155 } 156 } 157 158 $space_section->appendHint( 159 pht( 160 'After a user passes space policy checks, they must still pass '. 161 'object policy checks.')); 162 163 return $space_section; 164 } 165 166 private function getCapabilityName($capability) { 167 $capability_name = $capability; 168 $capobj = PhabricatorPolicyCapability::getCapabilityByKey($capability); 169 if ($capobj) { 170 $capability_name = $capobj->getCapabilityName(); 171 } 172 173 return $capability_name; 174 } 175 176 private function buildExtendedSection( 177 PhabricatorPolicyInterface $object, 178 $capability) { 179 $viewer = $this->getViewer(); 180 181 if (!($object instanceof PhabricatorExtendedPolicyInterface)) { 182 return null; 183 } 184 185 $extended_rules = $object->getExtendedPolicy($capability, $viewer); 186 if (!$extended_rules) { 187 return null; 188 } 189 190 $items = array(); 191 foreach ($extended_rules as $extended_rule) { 192 $extended_target = $extended_rule[0]; 193 $extended_capabilities = (array)$extended_rule[1]; 194 if (is_object($extended_target)) { 195 $extended_target = $extended_target->getPHID(); 196 } 197 198 foreach ($extended_capabilities as $extended_capability) { 199 $ex_name = $this->getCapabilityName($extended_capability); 200 $items[] = array( 201 phutil_tag('strong', array(), pht('%s:', $ex_name)), 202 ' ', 203 $viewer->renderHandle($extended_target)->setAsTag(true), 204 ); 205 } 206 } 207 208 return id(new PHUIPolicySectionView()) 209 ->setViewer($viewer) 210 ->setIcon('fa-link') 211 ->setHeader(pht('Required Capabilities on Other Objects')) 212 ->appendParagraph( 213 pht( 214 'To access this object, users must have first have access '. 215 'capabilities on these other objects:')) 216 ->appendList($items); 217 } 218 219 private function buildExceptionsSection( 220 PhabricatorPolicyInterface $object, 221 $capability) { 222 $viewer = $this->getViewer(); 223 224 $exceptions = PhabricatorPolicy::getSpecialRules( 225 $object, 226 $viewer, 227 $capability, 228 false); 229 230 if (!$exceptions) { 231 return null; 232 } 233 234 return id(new PHUIPolicySectionView()) 235 ->setViewer($viewer) 236 ->setIcon('fa-unlock-alt red') 237 ->setHeader(pht('Special Rules')) 238 ->appendParagraph( 239 pht( 240 'This object has special rules which override normal object '. 241 'policy rules:')) 242 ->appendList($exceptions); 243 } 244 245 private function buildObjectSection( 246 PhabricatorPolicyInterface $object, 247 PhabricatorPolicy $policy, 248 $capability, 249 PhabricatorObjectHandle $handle) { 250 251 $viewer = $this->getViewer(); 252 $capability_name = $this->getCapabilityName($capability); 253 254 $object_section = id(new PHUIPolicySectionView()) 255 ->setViewer($viewer) 256 ->setIcon($handle->getIcon().' bluegrey') 257 ->setHeader(pht('Object Policy')) 258 ->appendParagraph( 259 array( 260 array( 261 phutil_tag('strong', array(), pht('%s:', $capability_name)), 262 ' ', 263 $policy->getShortName(), 264 ), 265 )) 266 ->appendParagraph( 267 pht( 268 'In detail, this means that these users can take this action, '. 269 'provided they pass all of the checks described above first:')) 270 ->appendList( 271 array( 272 PhabricatorPolicy::getPolicyExplanation( 273 $viewer, 274 $policy->getPHID()), 275 )); 276 277 if ($policy->isCustomPolicy()) { 278 $rules_view = id(new PhabricatorPolicyRulesView()) 279 ->setViewer($viewer) 280 ->setPolicy($policy); 281 $object_section->appendRulesView($rules_view); 282 } 283 284 return $object_section; 285 } 286 287}