diff --git a/src/applications/passphrase/controller/PassphraseCredentialCreateController.php b/src/applications/passphrase/controller/PassphraseCredentialCreateController.php index cfddcbcc4a..87afe22cc6 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialCreateController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialCreateController.php @@ -1,68 +1,74 @@ getViewer(); $types = PassphraseCredentialType::getAllCreateableTypes(); $types = mpull($types, null, 'getCredentialType'); $types = msort($types, 'getCredentialTypeName'); $errors = array(); $e_type = null; if ($request->isFormPost()) { $type = $request->getStr('type'); if (empty($types[$type])) { $errors[] = pht('You must choose a credential type.'); $e_type = pht('Required'); } if (!$errors) { $uri = $this->getApplicationURI('edit/?type='.$type); return id(new AphrontRedirectResponse())->setURI($uri); } } $types_control = id(new AphrontFormRadioButtonControl()) ->setName('type') ->setLabel(pht('Credential Type')) ->setError($e_type); foreach ($types as $type) { $types_control->addButton( $type->getCredentialType(), $type->getCredentialTypeName(), $type->getCredentialTypeDescription()); } $form = id(new AphrontFormView()) ->setUser($viewer) ->appendChild($types_control) ->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Continue')) ->addCancelButton($this->getApplicationURI())); $title = pht('New Credential'); $crumbs = $this->buildApplicationCrumbs(); $crumbs->addTextCrumb(pht('Create')); + $crumbs->setBorder(true); $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Create New Credential')) + ->setHeaderText(pht('Credential')) ->setFormErrors($errors) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); - return $this->buildApplicationPage( - array( - $crumbs, - $box, - ), - array( - 'title' => $title, - )); + $header = id(new PHUIHeaderView()) + ->setHeader($title) + ->setHeaderIcon('fa-plus-square'); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setFooter($box); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($view); } } diff --git a/src/applications/passphrase/controller/PassphraseCredentialEditController.php b/src/applications/passphrase/controller/PassphraseCredentialEditController.php index 72c21a9e39..4aa687ddc1 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialEditController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialEditController.php @@ -1,379 +1,384 @@ getViewer(); $id = $request->getURIData('id'); if ($id) { $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, PhabricatorPolicyCapability::CAN_EDIT, )) ->executeOne(); if (!$credential) { return new Aphront404Response(); } $type = $this->getCredentialType($credential->getCredentialType()); $is_new = false; } else { $type_const = $request->getStr('type'); $type = $this->getCredentialType($type_const); if (!$type->isCreateable()) { throw new Exception( pht( 'Credential has noncreateable type "%s"!', $type_const)); } $credential = PassphraseCredential::initializeNewCredential($viewer) ->setCredentialType($type->getCredentialType()) ->setProvidesType($type->getProvidesType()) ->attachImplementation($type); $is_new = true; // Prefill username if provided. $credential->setUsername((string)$request->getStr('username')); if (!$request->getStr('isInitialized')) { $type->didInitializeNewCredential($viewer, $credential); } } $errors = array(); $v_name = $credential->getName(); $e_name = true; $v_desc = $credential->getDescription(); $v_space = $credential->getSpacePHID(); $v_username = $credential->getUsername(); $e_username = true; $v_is_locked = false; $bullet = "\xE2\x80\xA2"; $v_secret = $credential->getSecretID() ? str_repeat($bullet, 32) : null; if ($is_new && ($v_secret === null)) { // If we're creating a new credential, the credential type may have // populated the secret for us (for example, generated an SSH key). In // this case, try { $v_secret = $credential->getSecret()->openEnvelope(); } catch (Exception $ex) { // Ignore this. } } $validation_exception = null; $errors = array(); $e_password = null; if ($request->isFormPost()) { $v_name = $request->getStr('name'); $v_desc = $request->getStr('description'); $v_username = $request->getStr('username'); $v_view_policy = $request->getStr('viewPolicy'); $v_edit_policy = $request->getStr('editPolicy'); $v_is_locked = $request->getStr('lock'); $v_secret = $request->getStr('secret'); $v_space = $request->getStr('spacePHID'); $v_password = $request->getStr('password'); $v_decrypt = $v_secret; $env_secret = new PhutilOpaqueEnvelope($v_secret); $env_password = new PhutilOpaqueEnvelope($v_password); if ($type->requiresPassword($env_secret)) { if (strlen($v_password)) { $v_decrypt = $type->decryptSecret($env_secret, $env_password); if ($v_decrypt === null) { $e_password = pht('Incorrect'); $errors[] = pht( 'This key requires a password, but the password you provided '. 'is incorrect.'); } else { $v_decrypt = $v_decrypt->openEnvelope(); } } else { $e_password = pht('Required'); $errors[] = pht( 'This key requires a password. You must provide the password '. 'for the key.'); } } if (!$errors) { $type_name = PassphraseCredentialTransaction::TYPE_NAME; $type_desc = PassphraseCredentialTransaction::TYPE_DESCRIPTION; $type_username = PassphraseCredentialTransaction::TYPE_USERNAME; $type_destroy = PassphraseCredentialTransaction::TYPE_DESTROY; $type_secret_id = PassphraseCredentialTransaction::TYPE_SECRET_ID; $type_is_locked = PassphraseCredentialTransaction::TYPE_LOCK; $type_view_policy = PhabricatorTransactions::TYPE_VIEW_POLICY; $type_edit_policy = PhabricatorTransactions::TYPE_EDIT_POLICY; $type_space = PhabricatorTransactions::TYPE_SPACE; $xactions = array(); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_name) ->setNewValue($v_name); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_desc) ->setNewValue($v_desc); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_view_policy) ->setNewValue($v_view_policy); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_edit_policy) ->setNewValue($v_edit_policy); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_space) ->setNewValue($v_space); // Open a transaction in case we're writing a new secret; this limits // the amount of code which handles secret plaintexts. $credential->openTransaction(); if (!$credential->getIsLocked()) { if ($type->shouldRequireUsername()) { $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_username) ->setNewValue($v_username); } // If some value other than a sequence of bullets was provided for // the credential, update it. In particular, note that we are // explicitly allowing empty secrets: one use case is HTTP auth where // the username is a secret token which covers both identity and // authentication. if (!preg_match('/^('.$bullet.')+$/', trim($v_decrypt))) { // If the credential was previously destroyed, restore it when it is // edited if a secret is provided. $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_destroy) ->setNewValue(0); $new_secret = id(new PassphraseSecret()) ->setSecretData($v_decrypt) ->save(); $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_secret_id) ->setNewValue($new_secret->getID()); } $xactions[] = id(new PassphraseCredentialTransaction()) ->setTransactionType($type_is_locked) ->setNewValue($v_is_locked); } try { $editor = id(new PassphraseCredentialTransactionEditor()) ->setActor($viewer) ->setContinueOnNoEffect(true) ->setContentSourceFromRequest($request) ->applyTransactions($credential, $xactions); $credential->saveTransaction(); if ($request->isAjax()) { return id(new AphrontAjaxResponse())->setContent( array( 'phid' => $credential->getPHID(), 'name' => 'K'.$credential->getID().' '.$credential->getName(), )); } else { return id(new AphrontRedirectResponse()) ->setURI('/K'.$credential->getID()); } } catch (PhabricatorApplicationTransactionValidationException $ex) { $credential->killTransaction(); $validation_exception = $ex; $e_name = $ex->getShortMessage($type_name); $e_username = $ex->getShortMessage($type_username); $credential->setViewPolicy($v_view_policy); $credential->setEditPolicy($v_edit_policy); } } } $policies = id(new PhabricatorPolicyQuery()) ->setViewer($viewer) ->setObject($credential) ->execute(); $secret_control = $type->newSecretControl(); $credential_is_locked = $credential->getIsLocked(); $form = id(new AphrontFormView()) ->setUser($viewer) ->addHiddenInput('isInitialized', true) ->appendChild( id(new AphrontFormTextControl()) ->setName('name') ->setLabel(pht('Name')) ->setValue($v_name) ->setError($e_name)) ->appendChild( id(new AphrontFormTextAreaControl()) ->setHeight(AphrontFormTextAreaControl::HEIGHT_VERY_SHORT) ->setName('description') ->setLabel(pht('Description')) ->setValue($v_desc)) ->appendChild( id(new AphrontFormMarkupControl()) ->setLabel(pht('Credential Type')) ->setValue($type->getCredentialTypeName())) ->appendChild( id(new AphrontFormDividerControl())) ->appendControl( id(new AphrontFormPolicyControl()) ->setName('viewPolicy') ->setPolicyObject($credential) ->setSpacePHID($v_space) ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) ->setPolicies($policies)) ->appendControl( id(new AphrontFormPolicyControl()) ->setName('editPolicy') ->setPolicyObject($credential) ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) ->setPolicies($policies)) ->appendChild( id(new AphrontFormDividerControl())); if ($credential_is_locked) { $form->appendRemarkupInstructions( pht('This credential is permanently locked and can not be edited.')); } if ($type->shouldRequireUsername()) { $form ->appendChild( id(new AphrontFormTextControl()) ->setName('username') ->setLabel(pht('Login/Username')) ->setValue($v_username) ->setDisabled($credential_is_locked) ->setError($e_username)); } $form ->appendChild( $secret_control ->setName('secret') ->setLabel($type->getSecretLabel()) ->setDisabled($credential_is_locked) ->setValue($v_secret)); if ($type->shouldShowPasswordField()) { $form->appendChild( id(new AphrontFormPasswordControl()) ->setDisableAutocomplete(true) ->setName('password') ->setLabel($type->getPasswordLabel()) ->setDisabled($credential_is_locked) ->setError($e_password)); } if ($is_new) { $form->appendChild( id(new AphrontFormCheckboxControl()) ->addCheckbox( 'lock', 1, array( phutil_tag('strong', array(), pht('Lock Permanently:')), ' ', pht('Prevent the secret from being revealed or changed.'), ), $v_is_locked) ->setDisabled($credential_is_locked)); } $crumbs = $this->buildApplicationCrumbs(); + $crumbs->setBorder(true); if ($is_new) { - $title = pht('Create Credential'); - $header = pht('Create New Credential'); + $title = pht('Create New Credential'); $crumbs->addTextCrumb(pht('Create')); $cancel_uri = $this->getApplicationURI(); + $header_icon = 'fa-plus-square'; } else { - $title = pht('Edit Credential'); - $header = pht('Edit Credential %s', 'K'.$credential->getID()); + $title = pht('Edit Credential: %s', $credential->getName()); $crumbs->addTextCrumb( 'K'.$credential->getID(), '/K'.$credential->getID()); $crumbs->addTextCrumb(pht('Edit')); $cancel_uri = '/K'.$credential->getID(); + $header_icon = 'fa-pencil'; } if ($request->isAjax()) { if ($errors) { $errors = id(new PHUIInfoView())->setErrors($errors); } - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) + return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FORM) ->setTitle($title) ->appendChild($errors) ->appendChild($form->buildLayoutView()) ->addSubmitButton(pht('Create Credential')) ->addCancelButton($cancel_uri); - - return id(new AphrontDialogResponse())->setDialog($dialog); } $form->appendChild( id(new AphrontFormSubmitControl()) ->setValue(pht('Save')) ->addCancelButton($cancel_uri)); $box = id(new PHUIObjectBoxView()) - ->setHeaderText($header) + ->setHeaderText(pht('Credential')) ->setFormErrors($errors) ->setValidationException($validation_exception) + ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) ->setForm($form); - return $this->buildApplicationPage( - array( - $crumbs, + $header = id(new PHUIHeaderView()) + ->setHeader($title) + ->setHeaderIcon($header_icon); + + $view = id(new PHUITwoColumnView()) + ->setHeader($header) + ->setFooter(array( $box, - ), - array( - 'title' => $title, )); + + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($view); } private function getCredentialType($type_const) { $type = PassphraseCredentialType::getTypeByConstant($type_const); if (!$type) { throw new Exception( pht('Credential has invalid type "%s"!', $type_const)); } return $type; } } diff --git a/src/applications/passphrase/controller/PassphraseCredentialPublicController.php b/src/applications/passphrase/controller/PassphraseCredentialPublicController.php index 56fc6ac4ae..481d111fd9 100644 --- a/src/applications/passphrase/controller/PassphraseCredentialPublicController.php +++ b/src/applications/passphrase/controller/PassphraseCredentialPublicController.php @@ -1,53 +1,51 @@ getViewer(); $id = $request->getURIData('id'); $credential = id(new PassphraseCredentialQuery()) ->setViewer($viewer) ->withIDs(array($id)) ->requireCapabilities( array( PhabricatorPolicyCapability::CAN_VIEW, )) ->executeOne(); if (!$credential) { return new Aphront404Response(); } $type = PassphraseCredentialType::getTypeByConstant( $credential->getCredentialType()); if (!$type) { throw new Exception(pht('Credential has invalid type "%s"!', $type)); } if (!$type->hasPublicKey()) { throw new Exception(pht('Credential has no public key!')); } $view_uri = '/'.$credential->getMonogram(); $public_key = $type->getPublicKey($viewer, $credential); $body = id(new PHUIFormLayoutView()) ->appendChild( id(new AphrontFormTextAreaControl()) ->setLabel(pht('Public Key')) ->setReadOnly(true) ->setValue($public_key)); - $dialog = id(new AphrontDialogView()) - ->setUser($viewer) + return $this->newDialog() ->setWidth(AphrontDialogView::WIDTH_FORM) ->setTitle(pht('Public Key (%s)', $credential->getMonogram())) ->appendChild($body) ->addCancelButton($view_uri, pht('Done')); - return id(new AphrontDialogResponse())->setDialog($dialog); } }