[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |