Skip to content

Commit 0a0ac13

Browse files
author
epriestley
committedMar 3, 2017
Prevent users from taking "edit"-like actions via comment forms if they don't have edit permission
Summary: Ref T12335. Fixes T11207. Edit-like interactions which are not performed via "Edit <object>" are a bit of a grey area, policy-wise. For example, you can correctly do these things to an object you can't edit: - Comment on it. - Award tokens. - Subscribe or unsubscribe. - Subscribe other users by mentioning them. - Perform review. - Perform audit. - (Maybe some other stuff.) These behaviors are all desirable and correct. But, particularly now that we offer stacked actions, you can do a bunch of other stuff which you shouldn't really be able to, like changing the status and priority of tasks you can't edit, as long as you submit the change via the comment form. (Before the advent of stacked actions there were fewer things you could do via the comment form, and more of them were very "grey area", especially since "Change Subscribers" was just "Add Subscribers", which you can do via mentions.) This isn't too much of a problem in practice because we won't //show// you those actions if the edit form you'd end up on doesn't have those fields. So on intalls like ours where we've created simple + advanced flows, users who shouldn't be changing task priorities generally don't see an option to do so, even though they technically could if they mucked with the HTML. Change this behavior to be more strict: unless an action explicitly says that it doesn't need edit permission (comment, review, audit) don't show it to users who don't have edit permission and don't let them take the action. Test Plan: - As a user who could not edit a task, tried to change status via comment form; received policy exception. - As a user who could not edit a task, viewed a comment form: no actions available (just "comment"). - As a user who could not edit a revision, viewed a revision form: only "review" actions available (accept, resign, etc). - Viewed a commit form but these are kind of moot because there's no separate edit permission. Reviewers: chad Reviewed By: chad Maniphest Tasks: T12335, T11207 Differential Revision: https://secure.phabricator.com/D17452
1 parent 08b18ac commit 0a0ac13

File tree

5 files changed

+58
-0
lines changed

5 files changed

+58
-0
lines changed
 

‎src/applications/differential/xaction/DifferentialRevisionActionTransaction.php

+6
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,15 @@ public function newEditField(
7474
DifferentialRevision $revision,
7575
PhabricatorUser $viewer) {
7676

77+
// Actions in the "review" group, like "Accept Revision", do not require
78+
// that the actor be able to edit the revision.
79+
$group_review = DifferentialRevisionEditEngine::ACTIONGROUP_REVIEW;
80+
$is_review = ($this->getRevisionActionGroupKey() == $group_review);
81+
7782
$field = id(new PhabricatorApplyEditField())
7883
->setKey($this->getRevisionActionKey())
7984
->setTransactionType($this->getTransactionTypeConstant())
85+
->setCanApplyWithoutEditCapability($is_review)
8086
->setValue(true);
8187

8288
if ($this->isActionAvailable($revision, $viewer)) {

‎src/applications/diffusion/xaction/DiffusionCommitActionTransaction.php

+6
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,15 @@ public function newEditField(
7070
PhabricatorRepositoryCommit $commit,
7171
PhabricatorUser $viewer) {
7272

73+
// Actions in the "audit" group, like "Accept Commit", do not require
74+
// that the actor be able to edit the commit.
75+
$group_audit = DiffusionCommitEditEngine::ACTIONGROUP_AUDIT;
76+
$is_audit = ($this->getCommitActionGroupKey() == $group_audit);
77+
7378
$field = id(new PhabricatorApplyEditField())
7479
->setKey($this->getCommitActionKey())
7580
->setTransactionType($this->getTransactionTypeConstant())
81+
->setCanApplyWithoutEditCapability($is_audit)
7682
->setValue(true);
7783

7884
if ($this->isActionAvailable($commit, $viewer)) {

‎src/applications/transactions/editengine/PhabricatorEditEngine.php

+31
Original file line numberDiff line numberDiff line change
@@ -1586,12 +1586,23 @@ final public function buildEditEngineCommentView($object) {
15861586

15871587
$fields = $this->buildEditFields($object);
15881588

1589+
$can_edit = PhabricatorPolicyFilter::hasCapability(
1590+
$viewer,
1591+
$object,
1592+
PhabricatorPolicyCapability::CAN_EDIT);
1593+
15891594
$comment_actions = array();
15901595
foreach ($fields as $field) {
15911596
if (!$field->shouldGenerateTransactionsFromComment()) {
15921597
continue;
15931598
}
15941599

1600+
if (!$can_edit) {
1601+
if (!$field->getCanApplyWithoutEditCapability()) {
1602+
continue;
1603+
}
1604+
}
1605+
15951606
$comment_action = $field->getCommentAction();
15961607
if (!$comment_action) {
15971608
continue;
@@ -1812,6 +1823,11 @@ private function buildCommentResponse($object) {
18121823

18131824
$xactions = array();
18141825

1826+
$can_edit = PhabricatorPolicyFilter::hasCapability(
1827+
$viewer,
1828+
$object,
1829+
PhabricatorPolicyCapability::CAN_EDIT);
1830+
18151831
if ($actions) {
18161832
$action_map = array();
18171833
foreach ($actions as $action) {
@@ -1834,6 +1850,21 @@ private function buildCommentResponse($object) {
18341850
continue;
18351851
}
18361852

1853+
// If you don't have edit permission on the object, you're limited in
1854+
// which actions you can take via the comment form. Most actions
1855+
// need edit permission, but some actions (like "Accept Revision")
1856+
// can be applied by anyone with view permission.
1857+
if (!$can_edit) {
1858+
if (!$field->getCanApplyWithoutEditCapability()) {
1859+
// We know the user doesn't have the capability, so this will
1860+
// raise a policy exception.
1861+
PhabricatorPolicyFilter::requireCapability(
1862+
$viewer,
1863+
$object,
1864+
PhabricatorPolicyCapability::CAN_EDIT);
1865+
}
1866+
}
1867+
18371868
if (array_key_exists('initialValue', $action)) {
18381869
$field->setInitialValue($action['initialValue']);
18391870
}

‎src/applications/transactions/editfield/PhabricatorEditField.php

+10
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ abstract class PhabricatorEditField extends Phobject {
3636
private $isEditDefaults;
3737
private $isSubmittedForm;
3838
private $controlError;
39+
private $canApplyWithoutEditCapability = false;
3940

4041
private $isReorderable = true;
4142
private $isDefaultable = true;
@@ -292,6 +293,15 @@ public function getControlInstructions() {
292293
return $this->controlInstructions;
293294
}
294295

296+
public function setCanApplyWithoutEditCapability($can_apply) {
297+
$this->canApplyWithoutEditCapability = $can_apply;
298+
return $this;
299+
}
300+
301+
public function getCanApplyWithoutEditCapability() {
302+
return $this->canApplyWithoutEditCapability;
303+
}
304+
295305
protected function newControl() {
296306
throw new PhutilMethodNotImplementedException();
297307
}

‎src/applications/transactions/engineextension/PhabricatorCommentEditEngineExtension.php

+5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ public function buildCustomEditFields(
3939

4040
$comment_type = PhabricatorTransactions::TYPE_COMMENT;
4141

42+
// Comments have a lot of special behavior which doesn't always check
43+
// this flag, but we set it for consistency.
44+
$is_interact = true;
45+
4246
$comment_field = id(new PhabricatorCommentEditField())
4347
->setKey(self::EDITKEY)
4448
->setLabel(pht('Comments'))
@@ -47,6 +51,7 @@ public function buildCustomEditFields(
4751
->setIsReorderable(false)
4852
->setIsDefaultable(false)
4953
->setIsLockable(false)
54+
->setCanApplyWithoutEditCapability($is_interact)
5055
->setTransactionType($comment_type)
5156
->setConduitDescription(pht('Make comments.'))
5257
->setConduitTypeDescription(

0 commit comments

Comments
 (0)
Failed to load comments.