diff --git a/src/applications/tokens/controller/PhabricatorTokenGiveController.php b/src/applications/tokens/controller/PhabricatorTokenGiveController.php index c5d172ee64..c7c47c41f3 100644 --- a/src/applications/tokens/controller/PhabricatorTokenGiveController.php +++ b/src/applications/tokens/controller/PhabricatorTokenGiveController.php @@ -1,124 +1,142 @@ getViewer(); $phid = $request->getURIData('phid'); $handle = id(new PhabricatorHandleQuery()) ->setViewer($viewer) ->withPHIDs(array($phid)) ->executeOne(); if (!$handle->isComplete()) { return new Aphront404Response(); } + $object = id(new PhabricatorObjectQuery()) + ->setViewer($viewer) + ->withPHIDs(array($phid)) + ->executeOne(); + + if (!($object instanceof PhabricatorTokenReceiverInterface)) { + return new Aphront400Response(); + } + + if (!PhabricatorPolicyFilter::canInteract($viewer, $object)) { + $lock = PhabricatorEditEngineLock::newForObject($viewer, $object); + + $dialog = $this->newDialog() + ->addCancelButton($handle->getURI()); + + return $lock->willBlockUserInteractionWithDialog($dialog); + } + $current = id(new PhabricatorTokenGivenQuery()) ->setViewer($viewer) ->withAuthorPHIDs(array($viewer->getPHID())) ->withObjectPHIDs(array($handle->getPHID())) ->execute(); if ($current) { $is_give = false; $title = pht('Rescind Token'); } else { $is_give = true; $title = pht('Give Token'); } $done_uri = $handle->getURI(); if ($request->isDialogFormPost()) { $content_source = PhabricatorContentSource::newFromRequest($request); $editor = id(new PhabricatorTokenGivenEditor()) ->setActor($viewer) ->setContentSource($content_source); if ($is_give) { $token_phid = $request->getStr('tokenPHID'); $editor->addToken($handle->getPHID(), $token_phid); } else { $editor->deleteToken($handle->getPHID()); } return id(new AphrontReloadResponse())->setURI($done_uri); } if ($is_give) { $dialog = $this->buildGiveTokenDialog(); } else { $dialog = $this->buildRescindTokenDialog(head($current)); } $dialog->setUser($viewer); $dialog->addCancelButton($done_uri); return id(new AphrontDialogResponse())->setDialog($dialog); } private function buildGiveTokenDialog() { $viewer = $this->getViewer(); $tokens = id(new PhabricatorTokenQuery()) ->setViewer($viewer) ->execute(); $buttons = array(); $ii = 0; foreach ($tokens as $token) { $aural = javelin_tag( 'span', array( 'aural' => true, ), pht('Award "%s" Token', $token->getName())); $buttons[] = javelin_tag( 'button', array( 'class' => 'token-button', 'name' => 'tokenPHID', 'value' => $token->getPHID(), 'type' => 'submit', 'sigil' => 'has-tooltip', 'meta' => array( 'tip' => $token->getName(), ), ), array( $aural, $token->renderIcon(), )); if ((++$ii % 6) == 0) { $buttons[] = phutil_tag('br'); } } $buttons = phutil_tag( 'div', array( 'class' => 'token-grid', ), $buttons); $dialog = new AphrontDialogView(); $dialog->setTitle(pht('Give Token')); $dialog->appendChild($buttons); return $dialog; } private function buildRescindTokenDialog(PhabricatorTokenGiven $token_given) { $dialog = new AphrontDialogView(); $dialog->setTitle(pht('Rescind Token')); $dialog->appendChild( pht('Really rescind this lovely token?')); $dialog->addSubmitButton(pht('Rescind Token')); return $dialog; } } diff --git a/src/applications/tokens/event/PhabricatorTokenUIEventListener.php b/src/applications/tokens/event/PhabricatorTokenUIEventListener.php index 8a3ecc4396..bbf3438b62 100644 --- a/src/applications/tokens/event/PhabricatorTokenUIEventListener.php +++ b/src/applications/tokens/event/PhabricatorTokenUIEventListener.php @@ -1,147 +1,152 @@ listen(PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS); $this->listen(PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES); } public function handleEvent(PhutilEvent $event) { switch ($event->getType()) { case PhabricatorEventType::TYPE_UI_DIDRENDERACTIONS: $this->handleActionEvent($event); break; case PhabricatorEventType::TYPE_UI_WILLRENDERPROPERTIES: $this->handlePropertyEvent($event); break; } } private function handleActionEvent($event) { $user = $event->getUser(); $object = $event->getValue('object'); if (!$object || !$object->getPHID()) { // No object, or the object has no PHID yet.. return; } if (!($object instanceof PhabricatorTokenReceiverInterface)) { // This object isn't a token receiver. return; } if (!$this->canUseApplication($event->getUser())) { return null; } + $can_interact = PhabricatorPolicyFilter::canInteract($user, $object); + $current = id(new PhabricatorTokenGivenQuery()) ->setViewer($user) ->withAuthorPHIDs(array($user->getPHID())) ->withObjectPHIDs(array($object->getPHID())) ->execute(); if (!$current) { $token_action = id(new PhabricatorActionView()) ->setWorkflow(true) ->setHref('/token/give/'.$object->getPHID().'/') ->setName(pht('Award Token')) - ->setIcon('fa-trophy'); + ->setIcon('fa-trophy') + ->setDisabled(!$can_interact); } else { $token_action = id(new PhabricatorActionView()) ->setWorkflow(true) ->setHref('/token/give/'.$object->getPHID().'/') ->setName(pht('Rescind Token')) - ->setIcon('fa-trophy'); + ->setIcon('fa-trophy') + ->setDisabled(!$can_interact); } + if (!$user->isLoggedIn()) { $token_action->setDisabled(true); } $actions = $event->getValue('actions'); $actions[] = $token_action; $event->setValue('actions', $actions); } private function handlePropertyEvent($event) { $user = $event->getUser(); $object = $event->getValue('object'); if (!$object || !$object->getPHID()) { // No object, or the object has no PHID yet.. return; } if (!($object instanceof PhabricatorTokenReceiverInterface)) { // This object isn't a token receiver. return; } if (!$this->canUseApplication($event->getUser())) { return null; } $limit = 1; $tokens_given = id(new PhabricatorTokenGivenQuery()) ->setViewer($user) ->withObjectPHIDs(array($object->getPHID())) ->execute(); if (!$tokens_given) { return; } $tokens = id(new PhabricatorTokenQuery()) ->setViewer($user) ->withPHIDs(mpull($tokens_given, 'getTokenPHID')) ->execute(); $tokens = mpull($tokens, null, 'getPHID'); $author_phids = mpull($tokens_given, 'getAuthorPHID'); $handles = id(new PhabricatorHandleQuery()) ->setViewer($user) ->withPHIDs($author_phids) ->execute(); Javelin::initBehavior('phabricator-tooltips'); $list = array(); foreach ($tokens_given as $token_given) { if (!idx($tokens, $token_given->getTokenPHID())) { continue; } $token = $tokens[$token_given->getTokenPHID()]; $aural = javelin_tag( 'span', array( 'aural' => true, ), pht( '"%s" token, awarded by %s.', $token->getName(), $handles[$token_given->getAuthorPHID()]->getName())); $list[] = javelin_tag( 'span', array( 'sigil' => 'has-tooltip', 'class' => 'token-icon', 'meta' => array( 'tip' => $handles[$token_given->getAuthorPHID()]->getName(), ), ), array( $aural, $token->renderIcon(), )); } $view = $event->getValue('view'); $view->addProperty(pht('Tokens'), $list); } }