Skip to content

Commit a4cb2bb

Browse files
author
epriestley
committedFeb 13, 2021
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
1 parent f0dc065 commit a4cb2bb

File tree

6 files changed

+184
-4
lines changed

6 files changed

+184
-4
lines changed
 

‎resources/celerity/map.php

+3-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'names' => array(
1010
'conpherence.pkg.css' => '0e3cf785',
1111
'conpherence.pkg.js' => '020aebcf',
12-
'core.pkg.css' => '937616c0',
12+
'core.pkg.css' => '970b3ceb',
1313
'core.pkg.js' => 'adc34883',
1414
'dark-console.pkg.js' => '187792c2',
1515
'differential.pkg.css' => '5c459f92',
@@ -151,7 +151,7 @@
151151
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
152152
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
153153
'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
154-
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '12404744',
154+
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '5f752bdb',
155155
'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
156156
'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
157157
'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
@@ -845,7 +845,7 @@
845845
'phui-comment-form-css' => '68a2d99a',
846846
'phui-comment-panel-css' => 'ec4e31c0',
847847
'phui-crumbs-view-css' => '614f43cf',
848-
'phui-curtain-object-ref-view-css' => '12404744',
848+
'phui-curtain-object-ref-view-css' => '5f752bdb',
849849
'phui-curtain-view-css' => '68c5efb6',
850850
'phui-document-summary-view-css' => 'b068eed1',
851851
'phui-document-view-css' => '52b748a5',

‎src/applications/phid/PhabricatorObjectHandle.php

+63
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ final class PhabricatorObjectHandle
3232
private $tokenIcon;
3333
private $commandLineObjectName;
3434
private $mailStampName;
35+
private $capabilities = array();
3536

3637
public function setIcon($icon) {
3738
$this->icon = $icon;
@@ -388,6 +389,68 @@ protected function getPHIDType() {
388389
return idx($types, $this->getType());
389390
}
390391

392+
public function hasCapabilities() {
393+
return ($this->getType() === PhabricatorPeopleUserPHIDType::TYPECONST);
394+
}
395+
396+
public function attachCapability(
397+
PhabricatorPolicyInterface $object,
398+
$capability,
399+
$has_capability) {
400+
401+
if (!$this->hasCapabilities()) {
402+
throw new Exception(
403+
pht(
404+
'Attempting to attach capability ("%s") for object ("%s") to '.
405+
'handle, but this handle (of type "%s") can not have '.
406+
'capabilities.',
407+
$capability,
408+
get_class($object),
409+
$this->getType()));
410+
}
411+
412+
$object_key = $this->getObjectCapabilityKey($object);
413+
$this->capabilities[$object_key][$capability] = $has_capability;
414+
415+
return $this;
416+
}
417+
418+
public function hasViewCapability(PhabricatorPolicyInterface $object) {
419+
return $this->hasCapability($object, PhabricatorPolicyCapability::CAN_VIEW);
420+
}
421+
422+
private function hasCapability(
423+
PhabricatorPolicyInterface $object,
424+
$capability) {
425+
426+
$object_key = $this->getObjectCapabilityKey($object);
427+
428+
if (!isset($this->capabilities[$object_key][$capability])) {
429+
throw new Exception(
430+
pht(
431+
'Attempting to test capability "%s" for handle of type "%s", but '.
432+
'this capability has not been attached.',
433+
$capability,
434+
$this->getType()));
435+
}
436+
437+
return $this->capabilities[$object_key][$capability];
438+
}
439+
440+
private function getObjectCapabilityKey(PhabricatorPolicyInterface $object) {
441+
$object_phid = $object->getPHID();
442+
443+
if (!$object_phid) {
444+
throw new Exception(
445+
pht(
446+
'Object (of class "%s") has no PHID, so handles can not interact '.
447+
'with capabilities for it.',
448+
get_class($object)));
449+
}
450+
451+
return $object_phid;
452+
}
453+
391454

392455
/* -( PhabricatorPolicyInterface )----------------------------------------- */
393456

‎src/applications/policy/filter/PhabricatorPolicyFilterSet.php

+62
Original file line numberDiff line numberDiff line change
@@ -102,4 +102,66 @@ private function resolveCapabilities() {
102102
$this->queue = array();
103103
}
104104

105+
public static function loadHandleViewCapabilities(
106+
$viewer,
107+
$handles,
108+
array $objects) {
109+
110+
$capabilities = array(
111+
PhabricatorPolicyCapability::CAN_VIEW,
112+
);
113+
114+
assert_instances_of($objects, 'PhabricatorPolicyInterface');
115+
116+
if (!$objects) {
117+
return;
118+
}
119+
120+
$viewer_map = array();
121+
foreach ($handles as $handle_key => $handle) {
122+
if (!$handle->hasCapabilities()) {
123+
continue;
124+
}
125+
$viewer_map[$handle->getPHID()] = $handle_key;
126+
}
127+
128+
if (!$viewer_map) {
129+
return;
130+
}
131+
132+
$users = id(new PhabricatorPeopleQuery())
133+
->setViewer($viewer)
134+
->withPHIDs(array_keys($viewer_map))
135+
->execute();
136+
$users = mpull($users, null, 'getPHID');
137+
138+
$filter_set = new self();
139+
140+
foreach ($users as $user_phid => $user) {
141+
foreach ($objects as $object) {
142+
foreach ($capabilities as $capability) {
143+
$filter_set->addCapability($user, $object, $capability);
144+
}
145+
}
146+
}
147+
148+
foreach ($users as $user_phid => $user) {
149+
$handle_key = $viewer_map[$user_phid];
150+
$handle = $handles[$handle_key];
151+
foreach ($objects as $object) {
152+
foreach ($capabilities as $capability) {
153+
$has_capability = $filter_set->hasCapability(
154+
$user,
155+
$object,
156+
$capability);
157+
158+
$handle->attachCapability(
159+
$object,
160+
$capability,
161+
$has_capability);
162+
}
163+
}
164+
}
165+
}
166+
105167
}

‎src/applications/subscriptions/engineextension/PhabricatorSubscriptionsCurtainExtension.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,30 @@ public function buildCurtainPanel($object) {
6262
$handles = $viewer->loadHandles($visible_phids);
6363
}
6464

65+
PhabricatorPolicyFilterSet::loadHandleViewCapabilities(
66+
$viewer,
67+
$handles,
68+
array($object));
69+
6570
$ref_list = id(new PHUICurtainObjectRefListView())
6671
->setViewer($viewer)
6772
->setEmptyMessage(pht('None'));
6873

6974
foreach ($visible_phids as $phid) {
75+
$handle = $handles[$phid];
76+
7077
$ref = $ref_list->newObjectRefView()
71-
->setHandle($handles[$phid]);
78+
->setHandle($handle);
7279

7380
if ($phid === $viewer_phid) {
7481
$ref->setHighlighted(true);
7582
}
83+
84+
if ($handle->hasCapabilities()) {
85+
if (!$handle->hasViewCapability($object)) {
86+
$ref->setExiled(true);
87+
}
88+
}
7689
}
7790

7891
if ($show_all) {

‎src/view/phui/PHUICurtainObjectRefView.php

+29
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ final class PHUICurtainObjectRefView
66
private $handle;
77
private $epoch;
88
private $highlighted;
9+
private $exiled;
910

1011
public function setHandle(PhabricatorObjectHandle $handle) {
1112
$this->handle = $handle;
@@ -22,13 +23,23 @@ public function setHighlighted($highlighted) {
2223
return $this;
2324
}
2425

26+
public function setExiled($is_exiled) {
27+
$this->exiled = $is_exiled;
28+
return $this;
29+
}
30+
2531
protected function getTagAttributes() {
2632
$classes = array();
2733
$classes[] = 'phui-curtain-object-ref-view';
2834

2935
if ($this->highlighted) {
3036
$classes[] = 'phui-curtain-object-ref-view-highlighted';
3137
}
38+
39+
if ($this->exiled) {
40+
$classes[] = 'phui-curtain-object-ref-view-exiled';
41+
}
42+
3243
$classes = implode(' ', $classes);
3344

3445
return array(
@@ -60,6 +71,24 @@ protected function getTagContent() {
6071
$more_rows[] = phutil_tag('tr', array(), $epoch_cells);
6172
}
6273

74+
if ($this->exiled) {
75+
$exiled_view = array(
76+
id(new PHUIIconView())->setIcon('fa-eye-slash red'),
77+
' ',
78+
pht('No View Permission'),
79+
);
80+
81+
$exiled_cells = array();
82+
$exiled_cells[] = phutil_tag(
83+
'td',
84+
array(
85+
'class' => 'phui-curtain-object-ref-view-exiled-cell',
86+
),
87+
$exiled_view);
88+
89+
$more_rows[] = phutil_tag('tr', array(), $exiled_cells);
90+
}
91+
6392
$header_cells = array();
6493

6594
$image_view = $this->newImage();

‎webroot/rsrc/css/phui/phui-curtain-object-ref-view.css

+13
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
border-radius: 3px;
1313
}
1414

15+
.phui-curtain-object-ref-view + .phui-curtain-object-ref-view {
16+
margin-top: 1px;
17+
}
18+
1519
.phui-curtain-object-ref-view-image-cell {
1620
min-width: 32px;
1721
padding-bottom: 24px;
@@ -82,3 +86,12 @@
8286
.phui-curtain-object-ref-view-highlighted {
8387
background: {$bluebackground};
8488
}
89+
90+
.phui-curtain-object-ref-view-exiled {
91+
background: {$lightred};
92+
opacity: 0.75;
93+
}
94+
95+
.phui-curtain-object-ref-view-exiled-cell {
96+
color: {$red};
97+
}

0 commit comments

Comments
 (0)
Failed to load comments.