Conpherence - Implement edit rules for rooms

Summary: Fixes T7586. If you can't edit a room, the pertinent UI is greyed out. One exception is the title of the room in the full viewer; this crumb is not disabled as it would be hard to read. Otherwise though, everything is disabled nicely.

Test Plan: tried to add participants when I wasn't allowed to and got an error. added participants otherwise okay. tried to edit title when i wasn't allowed and got an error. otherwise okay. left conpherence threads / rooms successfully.

Reviewers: epriestley, chad

Reviewed By: epriestley

Subscribers: Korvin, epriestley

Maniphest Tasks: T7586

Differential Revision: https://secure.phabricator.com/D12161
This commit is contained in:
Bob Trahan
2015-03-25 11:48:22 -07:00
parent 1fd163d097
commit 42a0229a52
15 changed files with 203 additions and 82 deletions

View File

@@ -84,7 +84,12 @@ final class ConpherenceColumnViewController extends
'content' => hsprintf('%s', $durable_column),
'threadID' => $conpherence_id,
'threadPHID' => $conpherence_phid,
'latestTransactionID' => $latest_transaction_id,);
'latestTransactionID' => $latest_transaction_id,
'canEdit' => PhabricatorPolicyFilter::hasCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT),
);
return id(new AphrontAjaxResponse())->setContent($response);
}

View File

@@ -152,6 +152,7 @@ final class ConpherenceListController extends ConpherenceController {
case self::UNSELECTED_MODE:
default:
$layout = id(new ConpherenceLayoutView())
->setUser($user)
->setBaseURI($this->getApplicationURI())
->setThreadView($thread_view)
->setRole('list');

View File

@@ -3,35 +3,37 @@
final class ConpherenceUpdateController
extends ConpherenceController {
private $conpherenceID;
public function setConpherenceID($conpherence_id) {
$this->conpherenceID = $conpherence_id;
return $this;
}
public function getConpherenceID() {
return $this->conpherenceID;
}
public function willProcessRequest(array $data) {
$this->setConpherenceID(idx($data, 'id'));
}
public function processRequest() {
$request = $this->getRequest();
public function handleRequest(AphrontRequest $request) {
$user = $request->getUser();
$conpherence_id = $this->getConpherenceID();
$conpherence_id = $request->getURIData('id');
if (!$conpherence_id) {
return new Aphront404Response();
}
$needed_capabilities = array(PhabricatorPolicyCapability::CAN_VIEW);
$action = $request->getStr('action', ConpherenceUpdateActions::METADATA);
switch ($action) {
case ConpherenceUpdateActions::REMOVE_PERSON:
$person_phid = $request->getStr('remove_person');
if ($person_phid != $user->getPHID()) {
$needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
}
break;
case ConpherenceUpdateActions::ADD_PERSON:
case ConpherenceUpdateActions::METADATA:
$needed_capabilities[] = PhabricatorPolicyCapability::CAN_EDIT;
break;
case ConpherenceUpdateActions::JOIN_ROOM:
$needed_capabilities[] = PhabricatorPolicyCapability::CAN_JOIN;
break;
}
$conpherence = id(new ConpherenceThreadQuery())
->setViewer($user)
->withIDs(array($conpherence_id))
->needFilePHIDs(true)
->requireCapabilities($needed_capabilities)
->executeOne();
$action = $request->getStr('action', ConpherenceUpdateActions::METADATA);
$latest_transaction_id = null;
$response_mode = $request->isAjax() ? 'ajax' : 'redirect';
$error_view = null;
@@ -54,10 +56,6 @@ final class ConpherenceUpdateController
$draft->replaceOrDelete();
return new AphrontAjaxResponse();
case ConpherenceUpdateActions::JOIN_ROOM:
PhabricatorPolicyFilter::requireCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_JOIN);
$xactions[] = id(new ConpherenceTransaction())
->setTransactionType(
ConpherenceTransactionType::TYPE_PARTICIPANTS)
@@ -257,14 +255,19 @@ final class ConpherenceUpdateController
$user = $request->getUser();
$remove_person = $request->getStr('remove_person');
$participants = $conpherence->getParticipants();
$message = pht(
'Are you sure you want to remove yourself from this conpherence? ');
if (count($participants) == 1) {
$message .= pht(
'The conpherence will be inaccessible forever and ever.');
if ($conpherence->getIsRoom()) {
$message = pht(
'Are you sure you want to remove yourself from this room?');
} else {
$message .= pht(
'Someone else in the conpherence can add you back later.');
$message = pht(
'Are you sure you want to remove yourself from this thread?');
if (count($participants) == 1) {
$message .= pht(
'The thread will be inaccessible forever and ever.');
} else {
$message .= pht(
'Someone else in the thread can add you back later.');
}
}
$body = phutil_tag(
'p',

View File

@@ -63,10 +63,15 @@ final class ConpherenceViewController extends
$content['threadID'] = $conpherence->getID();
$content['threadPHID'] = $conpherence->getPHID();
$content['latestTransactionID'] = $data['latest_transaction_id'];
$content['canEdit'] = PhabricatorPolicyFilter::hasCapability(
$user,
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT);
return id(new AphrontAjaxResponse())->setContent($content);
}
$layout = id(new ConpherenceLayoutView())
->setUser($user)
->setBaseURI($this->getApplicationURI())
->setThread($conpherence)
->setHeader($header)

View File

@@ -369,6 +369,51 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
return $xactions;
}
protected function requireCapabilities(
PhabricatorLiskDAO $object,
PhabricatorApplicationTransaction $xaction) {
parent::requireCapabilities($object, $xaction);
switch ($xaction->getTransactionType()) {
case ConpherenceTransactionType::TYPE_PARTICIPANTS:
$old_map = array_fuse($xaction->getOldValue());
$new_map = array_fuse($xaction->getNewValue());
$add = array_keys(array_diff_key($new_map, $old_map));
$rem = array_keys(array_diff_key($old_map, $new_map));
$actor_phid = $this->requireActor()->getPHID();
$is_join = (($add === array($actor_phid)) && !$rem);
$is_leave = (($rem === array($actor_phid)) && !$add);
if ($is_join) {
// You need CAN_JOIN to join a thread / room.
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_JOIN);
} else if ($is_leave) {
// You don't need any capabilities to leave a conpherence thread.
} else {
// You need CAN_EDIT to change participants other than yourself.
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
}
break;
case ConpherenceTransactionType::TYPE_FILES:
case ConpherenceTransactionType::TYPE_TITLE:
PhabricatorPolicyFilter::requireCapability(
$this->requireActor(),
$object,
PhabricatorPolicyCapability::CAN_EDIT);
break;
}
}
protected function mergeTransactions(
PhabricatorApplicationTransaction $u,
PhabricatorApplicationTransaction $v) {
@@ -496,7 +541,7 @@ final class ConpherenceEditor extends PhabricatorApplicationTransactionEditor {
switch ($type) {
case ConpherenceTransactionType::TYPE_TITLE:
if (!$object->getIsRoom() && $this->getIsNewObject()) {
if (!$object->getIsRoom()) {
continue;
}
$missing = $this->validateIsEmptyTextField(

View File

@@ -266,7 +266,15 @@ final class ConpherenceThread extends ConpherenceDAO
}
public function describeAutomaticCapability($capability) {
return pht('Participants in a thread can always view and edit it.');
if ($this->getIsRoom()) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return pht('Participants in a room can always view it.');
break;
}
} else {
return pht('Participants in a thread can always view and edit it.');
}
}
}

View File

@@ -237,6 +237,7 @@ final class ConpherenceDurableColumnView extends AphrontTagView {
->setHref($action['href'])
->setName($action['name'])
->setIcon($action['icon'])
->setDisabled($action['disabled'])
->addSigil('conpherence-durable-column-header-action')
->setMetadata(array(
'action' => $action['key'],
@@ -303,27 +304,41 @@ final class ConpherenceDurableColumnView extends AphrontTagView {
}
private function getHeaderActionsConfig(ConpherenceThread $conpherence) {
if ($conpherence->getIsRoom()) {
$rename_label = pht('Rename Room');
} else {
$rename_label = pht('Rename Thread');
}
$can_edit = PhabricatorPolicyFilter::hasCapability(
$this->getUser(),
$conpherence,
PhabricatorPolicyCapability::CAN_EDIT);
return array(
array(
'name' => pht('Add Participants'),
'disabled' => !$can_edit,
'href' => '/conpherence/update/'.$conpherence->getID().'/',
'icon' => 'fa-plus',
'key' => ConpherenceUpdateActions::ADD_PERSON,
),
array(
'name' => pht('Rename Thread'),
'name' => $rename_label,
'disabled' => !$can_edit,
'href' => '/conpherence/update/'.$conpherence->getID().'/',
'icon' => 'fa-pencil',
'key' => ConpherenceUpdateActions::METADATA,
),
array(
'name' => pht('View in Conpherence'),
'disabled' => false,
'href' => '/conpherence/'.$conpherence->getID().'/',
'icon' => 'fa-comments',
'key' => 'go_conpherence',
),
array(
'name' => pht('Hide Column'),
'disabled' => false,
'href' => '#',
'icon' => 'fa-times',
'key' => 'hide_column',

View File

@@ -68,10 +68,15 @@ final class ConpherenceLayoutView extends AphrontView {
$selected_id = null;
$selected_thread_id = null;
$selected_thread_phid = null;
$can_edit_selected = null;
if ($this->thread) {
$selected_id = $this->thread->getPHID().'-nav-item';
$selected_thread_id = $this->thread->getID();
$selected_thread_phid = $this->thread->getPHID();
$can_edit_selected = PhabricatorPolicyFilter::hasCapability(
$this->getUser(),
$this->thread,
PhabricatorPolicyCapability::CAN_EDIT);
}
$this->initBehavior('conpherence-menu',
array(
@@ -80,6 +85,7 @@ final class ConpherenceLayoutView extends AphrontView {
'selectedID' => $selected_id,
'selectedThreadID' => $selected_thread_id,
'selectedThreadPHID' => $selected_thread_phid,
'canEditSelectedThread' => $can_edit_selected,
'latestTransactionID' => $this->latestTransactionID,
'role' => $this->role,
'hasThreadList' => (bool)$this->threadView,

View File

@@ -146,6 +146,10 @@ final class PHUIListItemView extends AphrontTagView {
$classes[] = 'phui-list-item-selected';
}
if ($this->disabled) {
$classes[] = 'phui-list-item-disabled';
}
if ($this->statusColor) {
$classes[] = $this->statusColor;
}