1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-12-22 21:40:55 +01:00

When a subscriber can't see an object, clearly show that they're missing the permission in the curtain UI

Summary:
Ref T13602. When a subscriber can't see an object, it's currently hard to figure it out.

Show this status clearly in the curtain UI.

Test Plan: {F8382865}

Maniphest Tasks: T13602

Differential Revision: https://secure.phabricator.com/D21547
This commit is contained in:
epriestley 2021-02-05 07:33:19 -08:00
parent f0dc065290
commit a4cb2bb772
6 changed files with 184 additions and 4 deletions

View file

@ -9,7 +9,7 @@ return array(
'names' => array(
'conpherence.pkg.css' => '0e3cf785',
'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => '937616c0',
'core.pkg.css' => '970b3ceb',
'core.pkg.js' => 'adc34883',
'dark-console.pkg.js' => '187792c2',
'differential.pkg.css' => '5c459f92',
@ -151,7 +151,7 @@ return array(
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '12404744',
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '5f752bdb',
'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
@ -845,7 +845,7 @@ return array(
'phui-comment-form-css' => '68a2d99a',
'phui-comment-panel-css' => 'ec4e31c0',
'phui-crumbs-view-css' => '614f43cf',
'phui-curtain-object-ref-view-css' => '12404744',
'phui-curtain-object-ref-view-css' => '5f752bdb',
'phui-curtain-view-css' => '68c5efb6',
'phui-document-summary-view-css' => 'b068eed1',
'phui-document-view-css' => '52b748a5',

View file

@ -32,6 +32,7 @@ final class PhabricatorObjectHandle
private $tokenIcon;
private $commandLineObjectName;
private $mailStampName;
private $capabilities = array();
public function setIcon($icon) {
$this->icon = $icon;
@ -388,6 +389,68 @@ final class PhabricatorObjectHandle
return idx($types, $this->getType());
}
public function hasCapabilities() {
return ($this->getType() === PhabricatorPeopleUserPHIDType::TYPECONST);
}
public function attachCapability(
PhabricatorPolicyInterface $object,
$capability,
$has_capability) {
if (!$this->hasCapabilities()) {
throw new Exception(
pht(
'Attempting to attach capability ("%s") for object ("%s") to '.
'handle, but this handle (of type "%s") can not have '.
'capabilities.',
$capability,
get_class($object),
$this->getType()));
}
$object_key = $this->getObjectCapabilityKey($object);
$this->capabilities[$object_key][$capability] = $has_capability;
return $this;
}
public function hasViewCapability(PhabricatorPolicyInterface $object) {
return $this->hasCapability($object, PhabricatorPolicyCapability::CAN_VIEW);
}
private function hasCapability(
PhabricatorPolicyInterface $object,
$capability) {
$object_key = $this->getObjectCapabilityKey($object);
if (!isset($this->capabilities[$object_key][$capability])) {
throw new Exception(
pht(
'Attempting to test capability "%s" for handle of type "%s", but '.
'this capability has not been attached.',
$capability,
$this->getType()));
}
return $this->capabilities[$object_key][$capability];
}
private function getObjectCapabilityKey(PhabricatorPolicyInterface $object) {
$object_phid = $object->getPHID();
if (!$object_phid) {
throw new Exception(
pht(
'Object (of class "%s") has no PHID, so handles can not interact '.
'with capabilities for it.',
get_class($object)));
}
return $object_phid;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */

View file

@ -102,4 +102,66 @@ final class PhabricatorPolicyFilterSet
$this->queue = array();
}
public static function loadHandleViewCapabilities(
$viewer,
$handles,
array $objects) {
$capabilities = array(
PhabricatorPolicyCapability::CAN_VIEW,
);
assert_instances_of($objects, 'PhabricatorPolicyInterface');
if (!$objects) {
return;
}
$viewer_map = array();
foreach ($handles as $handle_key => $handle) {
if (!$handle->hasCapabilities()) {
continue;
}
$viewer_map[$handle->getPHID()] = $handle_key;
}
if (!$viewer_map) {
return;
}
$users = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array_keys($viewer_map))
->execute();
$users = mpull($users, null, 'getPHID');
$filter_set = new self();
foreach ($users as $user_phid => $user) {
foreach ($objects as $object) {
foreach ($capabilities as $capability) {
$filter_set->addCapability($user, $object, $capability);
}
}
}
foreach ($users as $user_phid => $user) {
$handle_key = $viewer_map[$user_phid];
$handle = $handles[$handle_key];
foreach ($objects as $object) {
foreach ($capabilities as $capability) {
$has_capability = $filter_set->hasCapability(
$user,
$object,
$capability);
$handle->attachCapability(
$object,
$capability,
$has_capability);
}
}
}
}
}

View file

@ -62,17 +62,30 @@ final class PhabricatorSubscriptionsCurtainExtension
$handles = $viewer->loadHandles($visible_phids);
}
PhabricatorPolicyFilterSet::loadHandleViewCapabilities(
$viewer,
$handles,
array($object));
$ref_list = id(new PHUICurtainObjectRefListView())
->setViewer($viewer)
->setEmptyMessage(pht('None'));
foreach ($visible_phids as $phid) {
$handle = $handles[$phid];
$ref = $ref_list->newObjectRefView()
->setHandle($handles[$phid]);
->setHandle($handle);
if ($phid === $viewer_phid) {
$ref->setHighlighted(true);
}
if ($handle->hasCapabilities()) {
if (!$handle->hasViewCapability($object)) {
$ref->setExiled(true);
}
}
}
if ($show_all) {

View file

@ -6,6 +6,7 @@ final class PHUICurtainObjectRefView
private $handle;
private $epoch;
private $highlighted;
private $exiled;
public function setHandle(PhabricatorObjectHandle $handle) {
$this->handle = $handle;
@ -22,6 +23,11 @@ final class PHUICurtainObjectRefView
return $this;
}
public function setExiled($is_exiled) {
$this->exiled = $is_exiled;
return $this;
}
protected function getTagAttributes() {
$classes = array();
$classes[] = 'phui-curtain-object-ref-view';
@ -29,6 +35,11 @@ final class PHUICurtainObjectRefView
if ($this->highlighted) {
$classes[] = 'phui-curtain-object-ref-view-highlighted';
}
if ($this->exiled) {
$classes[] = 'phui-curtain-object-ref-view-exiled';
}
$classes = implode(' ', $classes);
return array(
@ -60,6 +71,24 @@ final class PHUICurtainObjectRefView
$more_rows[] = phutil_tag('tr', array(), $epoch_cells);
}
if ($this->exiled) {
$exiled_view = array(
id(new PHUIIconView())->setIcon('fa-eye-slash red'),
' ',
pht('No View Permission'),
);
$exiled_cells = array();
$exiled_cells[] = phutil_tag(
'td',
array(
'class' => 'phui-curtain-object-ref-view-exiled-cell',
),
$exiled_view);
$more_rows[] = phutil_tag('tr', array(), $exiled_cells);
}
$header_cells = array();
$image_view = $this->newImage();

View file

@ -12,6 +12,10 @@
border-radius: 3px;
}
.phui-curtain-object-ref-view + .phui-curtain-object-ref-view {
margin-top: 1px;
}
.phui-curtain-object-ref-view-image-cell {
min-width: 32px;
padding-bottom: 24px;
@ -82,3 +86,12 @@
.phui-curtain-object-ref-view-highlighted {
background: {$bluebackground};
}
.phui-curtain-object-ref-view-exiled {
background: {$lightred};
opacity: 0.75;
}
.phui-curtain-object-ref-view-exiled-cell {
color: {$red};
}