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:
parent
f0dc065290
commit
a4cb2bb772
6 changed files with 184 additions and 4 deletions
|
@ -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',
|
||||
|
|
|
@ -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 )----------------------------------------- */
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue