[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/passphrase/controller/ -> PassphraseCredentialEditController.php (source)

   1  <?php
   2  
   3  final class PassphraseCredentialEditController extends PassphraseController {
   4  
   5    private $id;
   6  
   7    public function willProcessRequest(array $data) {
   8      $this->id = idx($data, 'id');
   9    }
  10  
  11    public function processRequest() {
  12      $request = $this->getRequest();
  13      $viewer = $request->getUser();
  14  
  15      if ($this->id) {
  16        $credential = id(new PassphraseCredentialQuery())
  17          ->setViewer($viewer)
  18          ->withIDs(array($this->id))
  19          ->requireCapabilities(
  20            array(
  21              PhabricatorPolicyCapability::CAN_VIEW,
  22              PhabricatorPolicyCapability::CAN_EDIT,
  23            ))
  24          ->executeOne();
  25        if (!$credential) {
  26          return new Aphront404Response();
  27        }
  28  
  29        $type = $this->getCredentialType($credential->getCredentialType());
  30  
  31        $is_new = false;
  32      } else {
  33        $type_const = $request->getStr('type');
  34        $type = $this->getCredentialType($type_const);
  35  
  36        if (!$type->isCreateable()) {
  37          throw new Exception(
  38            pht(
  39              'Credential has noncreateable type "%s"!',
  40              $credential->getCredentialType()));
  41        }
  42  
  43        $credential = PassphraseCredential::initializeNewCredential($viewer)
  44          ->setCredentialType($type->getCredentialType())
  45          ->setProvidesType($type->getProvidesType());
  46  
  47        $is_new = true;
  48  
  49        // Prefill username if provided.
  50        $credential->setUsername($request->getStr('username'));
  51  
  52        if (!$request->getStr('isInitialized')) {
  53          $type->didInitializeNewCredential($viewer, $credential);
  54        }
  55      }
  56  
  57      $errors = array();
  58  
  59      $v_name = $credential->getName();
  60      $e_name = true;
  61  
  62      $v_desc = $credential->getDescription();
  63  
  64      $v_username = $credential->getUsername();
  65      $e_username = true;
  66  
  67      $v_is_locked = false;
  68  
  69      $bullet = "\xE2\x80\xA2";
  70  
  71      $v_secret = $credential->getSecretID() ? str_repeat($bullet, 32) : null;
  72      if ($is_new && ($v_secret === null)) {
  73        // If we're creating a new credential, the credential type may have
  74        // populated the secret for us (for example, generated an SSH key). In
  75        // this case,
  76        try {
  77          $v_secret = $credential->getSecret()->openEnvelope();
  78        } catch (Exception $ex) {
  79          // Ignore this.
  80        }
  81      }
  82  
  83      $validation_exception = null;
  84      $errors = array();
  85      $e_password = null;
  86      if ($request->isFormPost()) {
  87  
  88        $v_name = $request->getStr('name');
  89        $v_desc = $request->getStr('description');
  90        $v_username = $request->getStr('username');
  91        $v_view_policy = $request->getStr('viewPolicy');
  92        $v_edit_policy = $request->getStr('editPolicy');
  93        $v_is_locked = $request->getStr('lock');
  94  
  95        $v_secret = $request->getStr('secret');
  96        $v_password = $request->getStr('password');
  97        $v_decrypt = $v_secret;
  98  
  99        $env_secret = new PhutilOpaqueEnvelope($v_secret);
 100        $env_password = new PhutilOpaqueEnvelope($v_password);
 101  
 102        if ($type->requiresPassword($env_secret)) {
 103          if (strlen($v_password)) {
 104            $v_decrypt = $type->decryptSecret($env_secret, $env_password);
 105            if ($v_decrypt === null) {
 106              $e_password = pht('Incorrect');
 107              $errors[] = pht(
 108                'This key requires a password, but the password you provided '.
 109                'is incorrect.');
 110            } else {
 111              $v_decrypt = $v_decrypt->openEnvelope();
 112            }
 113          } else {
 114            $e_password = pht('Required');
 115            $errors[] = pht(
 116              'This key requires a password. You must provide the password '.
 117              'for the key.');
 118          }
 119        }
 120  
 121        if (!$errors) {
 122          $type_name = PassphraseCredentialTransaction::TYPE_NAME;
 123          $type_desc = PassphraseCredentialTransaction::TYPE_DESCRIPTION;
 124          $type_username = PassphraseCredentialTransaction::TYPE_USERNAME;
 125          $type_destroy = PassphraseCredentialTransaction::TYPE_DESTROY;
 126          $type_secret_id = PassphraseCredentialTransaction::TYPE_SECRET_ID;
 127          $type_is_locked = PassphraseCredentialTransaction::TYPE_LOCK;
 128          $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY;
 129          $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY;
 130  
 131          $xactions = array();
 132  
 133          $xactions[] = id(new PassphraseCredentialTransaction())
 134            ->setTransactionType($type_name)
 135            ->setNewValue($v_name);
 136  
 137          $xactions[] = id(new PassphraseCredentialTransaction())
 138            ->setTransactionType($type_desc)
 139            ->setNewValue($v_desc);
 140  
 141          $xactions[] = id(new PassphraseCredentialTransaction())
 142            ->setTransactionType($type_view_policy)
 143            ->setNewValue($v_view_policy);
 144  
 145          $xactions[] = id(new PassphraseCredentialTransaction())
 146            ->setTransactionType($type_edit_policy)
 147            ->setNewValue($v_edit_policy);
 148  
 149          // Open a transaction in case we're writing a new secret; this limits
 150          // the amount of code which handles secret plaintexts.
 151          $credential->openTransaction();
 152  
 153          if (!$credential->getIsLocked()) {
 154            $xactions[] = id(new PassphraseCredentialTransaction())
 155              ->setTransactionType($type_username)
 156              ->setNewValue($v_username);
 157  
 158            // If some value other than a sequence of bullets was provided for
 159            // the credential, update it. In particular, note that we are
 160            // explicitly allowing empty secrets: one use case is HTTP auth where
 161            // the username is a secret token which covers both identity and
 162            // authentication.
 163  
 164            if (!preg_match('/^('.$bullet.')+$/', trim($v_decrypt))) {
 165              // If the credential was previously destroyed, restore it when it is
 166              // edited if a secret is provided.
 167              $xactions[] = id(new PassphraseCredentialTransaction())
 168                ->setTransactionType($type_destroy)
 169                ->setNewValue(0);
 170  
 171              $new_secret = id(new PassphraseSecret())
 172                ->setSecretData($v_decrypt)
 173                ->save();
 174              $xactions[] = id(new PassphraseCredentialTransaction())
 175                ->setTransactionType($type_secret_id)
 176                ->setNewValue($new_secret->getID());
 177            }
 178  
 179            $xactions[] = id(new PassphraseCredentialTransaction())
 180              ->setTransactionType($type_is_locked)
 181              ->setNewValue($v_is_locked);
 182          }
 183  
 184          try {
 185            $editor = id(new PassphraseCredentialTransactionEditor())
 186              ->setActor($viewer)
 187              ->setContinueOnNoEffect(true)
 188              ->setContentSourceFromRequest($request)
 189              ->applyTransactions($credential, $xactions);
 190  
 191            $credential->saveTransaction();
 192  
 193            if ($request->isAjax()) {
 194              return id(new AphrontAjaxResponse())->setContent(
 195                array(
 196                  'phid' => $credential->getPHID(),
 197                  'name' => 'K'.$credential->getID().' '.$credential->getName(),
 198                ));
 199            } else {
 200              return id(new AphrontRedirectResponse())
 201                ->setURI('/K'.$credential->getID());
 202            }
 203          } catch (PhabricatorApplicationTransactionValidationException $ex) {
 204            $credential->killTransaction();
 205  
 206            $validation_exception = $ex;
 207  
 208            $e_name = $ex->getShortMessage($type_name);
 209            $e_username = $ex->getShortMessage($type_username);
 210  
 211            $credential->setViewPolicy($v_view_policy);
 212            $credential->setEditPolicy($v_edit_policy);
 213          }
 214        }
 215      }
 216  
 217      $policies = id(new PhabricatorPolicyQuery())
 218        ->setViewer($viewer)
 219        ->setObject($credential)
 220        ->execute();
 221  
 222      $secret_control = $type->newSecretControl();
 223      $credential_is_locked = $credential->getIsLocked();
 224  
 225      $form = id(new AphrontFormView())
 226        ->setUser($viewer)
 227        ->addHiddenInput('isInitialized', true)
 228        ->appendChild(
 229          id(new AphrontFormTextControl())
 230            ->setName('name')
 231            ->setLabel(pht('Name'))
 232            ->setValue($v_name)
 233            ->setError($e_name))
 234        ->appendChild(
 235          id(new AphrontFormTextAreaControl())
 236            ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT)
 237            ->setName('description')
 238            ->setLabel(pht('Description'))
 239            ->setValue($v_desc))
 240        ->appendChild(
 241          id(new AphrontFormMarkupControl())
 242            ->setLabel(pht('Credential Type'))
 243            ->setValue($type->getCredentialTypeName()))
 244        ->appendChild(
 245          id(new AphrontFormDividerControl()))
 246        ->appendChild(
 247          id(new AphrontFormPolicyControl())
 248            ->setName('viewPolicy')
 249            ->setPolicyObject($credential)
 250            ->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
 251            ->setPolicies($policies))
 252        ->appendChild(
 253          id(new AphrontFormPolicyControl())
 254            ->setName('editPolicy')
 255            ->setPolicyObject($credential)
 256            ->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
 257            ->setPolicies($policies))
 258        ->appendChild(
 259          id(new AphrontFormDividerControl()));
 260  
 261      if ($credential_is_locked) {
 262        $form->appendRemarkupInstructions(
 263          pht('This credential is permanently locked and can not be edited.'));
 264      }
 265  
 266      $form
 267        ->appendChild(
 268          id(new AphrontFormTextControl())
 269            ->setName('username')
 270            ->setLabel(pht('Login/Username'))
 271            ->setValue($v_username)
 272            ->setDisabled($credential_is_locked)
 273            ->setError($e_username))
 274        ->appendChild(
 275          $secret_control
 276            ->setName('secret')
 277            ->setLabel($type->getSecretLabel())
 278            ->setDisabled($credential_is_locked)
 279            ->setValue($v_secret));
 280  
 281      if ($type->shouldShowPasswordField()) {
 282        $form->appendChild(
 283          id(new AphrontFormPasswordControl())
 284            ->setDisableAutocomplete(true)
 285            ->setName('password')
 286            ->setLabel($type->getPasswordLabel())
 287            ->setDisabled($credential_is_locked)
 288            ->setError($e_password));
 289      }
 290  
 291      if ($is_new) {
 292        $form->appendChild(
 293          id(new AphrontFormCheckboxControl())
 294            ->addCheckbox(
 295              'lock',
 296              1,
 297              array(
 298                phutil_tag('strong', array(), pht('Lock Permanently:')),
 299                ' ',
 300                pht('Prevent the secret from being revealed or changed.'),
 301              ),
 302              $v_is_locked)
 303            ->setDisabled($credential_is_locked));
 304      }
 305  
 306      $crumbs = $this->buildApplicationCrumbs();
 307  
 308      if ($is_new) {
 309        $title = pht('Create Credential');
 310        $header = pht('Create New Credential');
 311        $crumbs->addTextCrumb(pht('Create'));
 312        $cancel_uri = $this->getApplicationURI();
 313      } else {
 314        $title = pht('Edit Credential');
 315        $header = pht('Edit Credential %s', 'K'.$credential->getID());
 316        $crumbs->addTextCrumb(
 317          'K'.$credential->getID(),
 318          '/K'.$credential->getID());
 319        $crumbs->addTextCrumb(pht('Edit'));
 320        $cancel_uri = '/K'.$credential->getID();
 321      }
 322  
 323      if ($request->isAjax()) {
 324        if ($errors) {
 325          $errors = id(new AphrontErrorView())->setErrors($errors);
 326        }
 327  
 328        $dialog = id(new AphrontDialogView())
 329          ->setUser($viewer)
 330          ->setWidth(AphrontDialogView::WIDTH_FORM)
 331          ->setTitle($title)
 332          ->appendChild($errors)
 333          ->appendChild($form->buildLayoutView())
 334          ->addSubmitButton(pht('Create Credential'))
 335          ->addCancelButton($cancel_uri);
 336  
 337        return id(new AphrontDialogResponse())->setDialog($dialog);
 338      }
 339  
 340      $form->appendChild(
 341        id(new AphrontFormSubmitControl())
 342          ->setValue(pht('Save'))
 343          ->addCancelButton($cancel_uri));
 344  
 345      $box = id(new PHUIObjectBoxView())
 346        ->setHeaderText($header)
 347        ->setFormErrors($errors)
 348        ->setValidationException($validation_exception)
 349        ->setForm($form);
 350  
 351      return $this->buildApplicationPage(
 352        array(
 353          $crumbs,
 354          $box,
 355        ),
 356        array(
 357          'title' => $title,
 358        ));
 359    }
 360  
 361    private function getCredentialType($type_const) {
 362      $type = PassphraseCredentialType::getTypeByConstant($type_const);
 363  
 364      if (!$type) {
 365        throw new Exception(
 366          pht('Credential has invalid type "%s"!', $type_const));
 367      }
 368  
 369      return $type;
 370    }
 371  
 372  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1