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

Distinguish between invalid/broken handles and filtered handles

Summary:
Ref T603. Currently, we render handles the user doesn't have permission to see in a manner identical to handles that don't exist. This is confusing, and not required by policies (which restrict content, but permit knowledge that an object exists).

Instead, render them in different styles. Bad/invalid objects look like:

Unknown Object (Task)

Restricted objects look like:

[o] Restricted Task

...where `[o]` is the padlock icon.

Test Plan:
{F71100}

{F71101}

It's possible this renders weird somewhere, but I wasn't immediately able to find any issues. Yell if you see something.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: chad, aran

Maniphest Tasks: T603

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

+121 -54
+46 -46
src/__celerity_resource_map__.php
··· 3523 3523 ), 3524 3524 'phabricator-standard-page-view' => 3525 3525 array( 3526 - 'uri' => '/res/59c804b1/rsrc/css/application/base/standard-page-view.css', 3526 + 'uri' => '/res/eebd59cd/rsrc/css/application/base/standard-page-view.css', 3527 3527 'type' => 'css', 3528 3528 'requires' => 3529 3529 array( ··· 4297 4297 ), array( 4298 4298 'packages' => 4299 4299 array( 4300 - 'deb31815' => 4300 + '13fde8cd' => 4301 4301 array( 4302 4302 'name' => 'core.pkg.css', 4303 4303 'symbols' => ··· 4346 4346 41 => 'phabricator-tag-view-css', 4347 4347 42 => 'phui-list-view-css', 4348 4348 ), 4349 - 'uri' => '/res/pkg/deb31815/core.pkg.css', 4349 + 'uri' => '/res/pkg/13fde8cd/core.pkg.css', 4350 4350 'type' => 'css', 4351 4351 ), 4352 4352 '6041c6c8' => ··· 4538 4538 ), 4539 4539 'reverse' => 4540 4540 array( 4541 - 'aphront-dialog-view-css' => 'deb31815', 4542 - 'aphront-error-view-css' => 'deb31815', 4543 - 'aphront-list-filter-view-css' => 'deb31815', 4544 - 'aphront-pager-view-css' => 'deb31815', 4545 - 'aphront-panel-view-css' => 'deb31815', 4546 - 'aphront-table-view-css' => 'deb31815', 4547 - 'aphront-tokenizer-control-css' => 'deb31815', 4548 - 'aphront-tooltip-css' => 'deb31815', 4549 - 'aphront-typeahead-control-css' => 'deb31815', 4541 + 'aphront-dialog-view-css' => '13fde8cd', 4542 + 'aphront-error-view-css' => '13fde8cd', 4543 + 'aphront-list-filter-view-css' => '13fde8cd', 4544 + 'aphront-pager-view-css' => '13fde8cd', 4545 + 'aphront-panel-view-css' => '13fde8cd', 4546 + 'aphront-table-view-css' => '13fde8cd', 4547 + 'aphront-tokenizer-control-css' => '13fde8cd', 4548 + 'aphront-tooltip-css' => '13fde8cd', 4549 + 'aphront-typeahead-control-css' => '13fde8cd', 4550 4550 'differential-changeset-view-css' => '7cd7e387', 4551 4551 'differential-core-view-css' => '7cd7e387', 4552 4552 'differential-inline-comment-editor' => '5e9e5c4e', ··· 4560 4560 'differential-table-of-contents-css' => '7cd7e387', 4561 4561 'diffusion-commit-view-css' => '270f4eb4', 4562 4562 'diffusion-icons-css' => '270f4eb4', 4563 - 'global-drag-and-drop-css' => 'deb31815', 4563 + 'global-drag-and-drop-css' => '13fde8cd', 4564 4564 'inline-comment-summary-css' => '7cd7e387', 4565 4565 'javelin-aphlict' => '6041c6c8', 4566 4566 'javelin-behavior' => '3e3be199', ··· 4635 4635 'javelin-util' => '3e3be199', 4636 4636 'javelin-vector' => '3e3be199', 4637 4637 'javelin-workflow' => '3e3be199', 4638 - 'lightbox-attachment-css' => 'deb31815', 4638 + 'lightbox-attachment-css' => '13fde8cd', 4639 4639 'maniphest-task-summary-css' => '49898640', 4640 - 'phabricator-action-list-view-css' => 'deb31815', 4641 - 'phabricator-application-launch-view-css' => 'deb31815', 4640 + 'phabricator-action-list-view-css' => '13fde8cd', 4641 + 'phabricator-application-launch-view-css' => '13fde8cd', 4642 4642 'phabricator-busy' => '6041c6c8', 4643 4643 'phabricator-content-source-view-css' => '7cd7e387', 4644 - 'phabricator-core-css' => 'deb31815', 4645 - 'phabricator-crumbs-view-css' => 'deb31815', 4644 + 'phabricator-core-css' => '13fde8cd', 4645 + 'phabricator-crumbs-view-css' => '13fde8cd', 4646 4646 'phabricator-drag-and-drop-file-upload' => '5e9e5c4e', 4647 4647 'phabricator-dropdown-menu' => '6041c6c8', 4648 4648 'phabricator-file-upload' => '6041c6c8', 4649 - 'phabricator-filetree-view-css' => 'deb31815', 4650 - 'phabricator-flag-css' => 'deb31815', 4649 + 'phabricator-filetree-view-css' => '13fde8cd', 4650 + 'phabricator-flag-css' => '13fde8cd', 4651 4651 'phabricator-hovercard' => '6041c6c8', 4652 - 'phabricator-jump-nav' => 'deb31815', 4652 + 'phabricator-jump-nav' => '13fde8cd', 4653 4653 'phabricator-keyboard-shortcut' => '6041c6c8', 4654 4654 'phabricator-keyboard-shortcut-manager' => '6041c6c8', 4655 - 'phabricator-main-menu-view' => 'deb31815', 4655 + 'phabricator-main-menu-view' => '13fde8cd', 4656 4656 'phabricator-menu-item' => '6041c6c8', 4657 - 'phabricator-nav-view-css' => 'deb31815', 4657 + 'phabricator-nav-view-css' => '13fde8cd', 4658 4658 'phabricator-notification' => '6041c6c8', 4659 - 'phabricator-notification-css' => 'deb31815', 4660 - 'phabricator-notification-menu-css' => 'deb31815', 4659 + 'phabricator-notification-css' => '13fde8cd', 4660 + 'phabricator-notification-menu-css' => '13fde8cd', 4661 4661 'phabricator-object-selector-css' => '7cd7e387', 4662 4662 'phabricator-phtize' => '6041c6c8', 4663 4663 'phabricator-prefab' => '6041c6c8', 4664 4664 'phabricator-project-tag-css' => '49898640', 4665 - 'phabricator-remarkup-css' => 'deb31815', 4665 + 'phabricator-remarkup-css' => '13fde8cd', 4666 4666 'phabricator-shaped-request' => '5e9e5c4e', 4667 - 'phabricator-side-menu-view-css' => 'deb31815', 4668 - 'phabricator-standard-page-view' => 'deb31815', 4669 - 'phabricator-tag-view-css' => 'deb31815', 4667 + 'phabricator-side-menu-view-css' => '13fde8cd', 4668 + 'phabricator-standard-page-view' => '13fde8cd', 4669 + 'phabricator-tag-view-css' => '13fde8cd', 4670 4670 'phabricator-textareautils' => '6041c6c8', 4671 4671 'phabricator-tooltip' => '6041c6c8', 4672 - 'phabricator-transaction-view-css' => 'deb31815', 4673 - 'phabricator-zindex-css' => 'deb31815', 4674 - 'phui-button-css' => 'deb31815', 4675 - 'phui-form-css' => 'deb31815', 4676 - 'phui-form-view-css' => 'deb31815', 4677 - 'phui-header-view-css' => 'deb31815', 4678 - 'phui-icon-view-css' => 'deb31815', 4679 - 'phui-list-view-css' => 'deb31815', 4680 - 'phui-object-item-list-view-css' => 'deb31815', 4681 - 'phui-property-list-view-css' => 'deb31815', 4682 - 'phui-spacing-css' => 'deb31815', 4683 - 'sprite-apps-large-css' => 'deb31815', 4684 - 'sprite-gradient-css' => 'deb31815', 4685 - 'sprite-icons-css' => 'deb31815', 4686 - 'sprite-menu-css' => 'deb31815', 4687 - 'sprite-status-css' => 'deb31815', 4688 - 'syntax-highlighting-css' => 'deb31815', 4672 + 'phabricator-transaction-view-css' => '13fde8cd', 4673 + 'phabricator-zindex-css' => '13fde8cd', 4674 + 'phui-button-css' => '13fde8cd', 4675 + 'phui-form-css' => '13fde8cd', 4676 + 'phui-form-view-css' => '13fde8cd', 4677 + 'phui-header-view-css' => '13fde8cd', 4678 + 'phui-icon-view-css' => '13fde8cd', 4679 + 'phui-list-view-css' => '13fde8cd', 4680 + 'phui-object-item-list-view-css' => '13fde8cd', 4681 + 'phui-property-list-view-css' => '13fde8cd', 4682 + 'phui-spacing-css' => '13fde8cd', 4683 + 'sprite-apps-large-css' => '13fde8cd', 4684 + 'sprite-gradient-css' => '13fde8cd', 4685 + 'sprite-icons-css' => '13fde8cd', 4686 + 'sprite-menu-css' => '13fde8cd', 4687 + 'sprite-status-css' => '13fde8cd', 4688 + 'syntax-highlighting-css' => '13fde8cd', 4689 4689 ), 4690 4690 ));
+29 -5
src/applications/phid/PhabricatorObjectHandle.php
··· 15 15 private $complete; 16 16 private $disabled; 17 17 private $objectName; 18 + private $policyFiltered; 19 + 20 + public function setPolicyFiltered($policy_filered) { 21 + $this->policyFiltered = $policy_filered; 22 + return $this; 23 + } 24 + 25 + public function getPolicyFiltered() { 26 + return $this->policyFiltered; 27 + } 18 28 19 29 public function setObjectName($object_name) { 20 30 $this->objectName = $object_name; ··· 53 63 54 64 public function getName() { 55 65 if ($this->name === null) { 56 - return pht('Unknown Object (%s)', $this->getTypeName()); 66 + if ($this->getPolicyFiltered()) { 67 + return pht('Restricted %s', $this->getTypeName()); 68 + } else { 69 + return pht('Unknown Object (%s)', $this->getTypeName()); 70 + } 57 71 } 58 72 return $this->name; 59 73 } ··· 186 200 $name = $this->getLinkName(); 187 201 } 188 202 $classes = array(); 203 + $classes[] = 'phui-handle'; 189 204 $title = $this->title; 190 205 191 206 if ($this->status != PhabricatorObjectHandleStatus::STATUS_OPEN) { ··· 195 210 196 211 if ($this->disabled) { 197 212 $classes[] = 'handle-disabled'; 198 - $title = 'disabled'; // Overwrite status. 213 + $title = pht('Disabled'); // Overwrite status. 199 214 } 200 215 201 216 if ($this->getType() == PhabricatorPeoplePHIDTypeUser::TYPECONST) { 202 217 $classes[] = 'phui-link-person'; 203 218 } 204 219 220 + $uri = $this->getURI(); 221 + 222 + $icon = null; 223 + if ($this->getPolicyFiltered()) { 224 + $icon = id(new PHUIIconView()) 225 + ->setSpriteSheet(PHUIIconView::SPRITE_ICONS) 226 + ->setSpriteIcon('lock-grey'); 227 + } 228 + 205 229 return phutil_tag( 206 - 'a', 230 + $uri ? 'a' : 'span', 207 231 array( 208 - 'href' => $this->getURI(), 232 + 'href' => $uri, 209 233 'class' => implode(' ', $classes), 210 234 'title' => $title, 211 235 ), 212 - $name); 236 + array($icon, $name)); 213 237 } 214 238 215 239 public function getLinkName() {
+7 -3
src/applications/phid/query/PhabricatorHandleQuery.php
··· 18 18 return array(); 19 19 } 20 20 21 - $objects = id(new PhabricatorObjectQuery()) 21 + $object_query = id(new PhabricatorObjectQuery()) 22 22 ->withPHIDs($phids) 23 - ->setViewer($this->getViewer()) 24 - ->execute(); 23 + ->setViewer($this->getViewer()); 24 + 25 + $objects = $object_query->execute(); 26 + $filtered = $object_query->getPolicyFilteredPHIDs(); 25 27 26 28 $groups = array(); 27 29 foreach ($phids as $phid) { ··· 43 45 ->setPHID($phid); 44 46 if (isset($objects[$phid])) { 45 47 $handles[$phid]->setComplete(true); 48 + } else if (isset($filtered[$phid])) { 49 + $handles[$phid]->setPolicyFiltered(true); 46 50 } 47 51 } 48 52
+34
src/infrastructure/query/policy/PhabricatorPolicyAwareQuery.php
··· 34 34 private $rawResultLimit; 35 35 private $capabilities; 36 36 private $workspace = array(); 37 + private $policyFilteredPHIDs = array(); 37 38 38 39 39 40 /* -( Query Configuration )------------------------------------------------ */ ··· 228 229 $visible = $maybe_visible; 229 230 } else { 230 231 $visible = $filter->apply($maybe_visible); 232 + 233 + $policy_filtered = array(); 234 + foreach ($maybe_visible as $key => $object) { 235 + if (empty($visible[$key])) { 236 + $phid = $object->getPHID(); 237 + if ($phid) { 238 + $policy_filtered[$phid] = $phid; 239 + } 240 + } 241 + } 242 + $this->addPolicyFilteredPHIDs($policy_filtered); 231 243 } 232 244 233 245 if ($visible) { ··· 303 315 $object, 304 316 $object->getPolicy(PhabricatorPolicyCapability::CAN_VIEW), 305 317 PhabricatorPolicyCapability::CAN_VIEW); 318 + } 319 + 320 + protected function addPolicyFilteredPHIDs(array $phids) { 321 + $this->policyFilteredPHIDs += $phids; 322 + if ($this->getParentQuery()) { 323 + $this->getParentQuery()->addPolicyFilteredPHIDs($phids); 324 + } 325 + return $this; 326 + } 327 + 328 + /** 329 + * Return a map of all object PHIDs which were loaded in the query but 330 + * filtered out by policy constraints. This allows a caller to distinguish 331 + * between objects which do not exist (or, at least, were filtered at the 332 + * content level) and objects which exist but aren't visible. 333 + * 334 + * @return map<phid, phid> Map of object PHIDs which were filtered 335 + * by policies. 336 + * @task exec 337 + */ 338 + public function getPolicyFilteredPHIDs() { 339 + return $this->policyFilteredPHIDs; 306 340 } 307 341 308 342
+5
webroot/rsrc/css/application/base/standard-page-view.css
··· 95 95 padding: 8px 16px; 96 96 background: {$lightyellow}; 97 97 } 98 + 99 + .phui-handle .phui-icon-view { 100 + display: inline-block; 101 + margin: 2px 2px -2px 0; 102 + }