Changeset View
Changeset View
Standalone View
Standalone View
src/applications/settings/panel/PhabricatorSettingsPanelSSHKeys.php
<?php | <?php | ||||
final class PhabricatorSettingsPanelSSHKeys | final class PhabricatorSettingsPanelSSHKeys | ||||
extends PhabricatorSettingsPanel { | extends PhabricatorSettingsPanel { | ||||
public function isEditableByAdministrators() { | |||||
return true; | |||||
} | |||||
public function getPanelKey() { | public function getPanelKey() { | ||||
return 'ssh'; | return 'ssh'; | ||||
} | } | ||||
public function getPanelName() { | public function getPanelName() { | ||||
return pht('SSH Public Keys'); | return pht('SSH Public Keys'); | ||||
} | } | ||||
public function getPanelGroup() { | public function getPanelGroup() { | ||||
return pht('Authentication'); | return pht('Authentication'); | ||||
} | } | ||||
public function isEnabled() { | public function isEnabled() { | ||||
return true; | return true; | ||||
} | } | ||||
public function processRequest(AphrontRequest $request) { | public function processRequest(AphrontRequest $request) { | ||||
$viewer = $request->getUser(); | |||||
$user = $request->getUser(); | $user = $this->getUser(); | ||||
$generate = $request->getStr('generate'); | $generate = $request->getStr('generate'); | ||||
if ($generate) { | if ($generate) { | ||||
return $this->processGenerate($request); | return $this->processGenerate($request); | ||||
} | } | ||||
$edit = $request->getStr('edit'); | $edit = $request->getStr('edit'); | ||||
$delete = $request->getStr('delete'); | $delete = $request->getStr('delete'); | ||||
if (!$edit && !$delete) { | if (!$edit && !$delete) { | ||||
return $this->renderKeyListView($request); | return $this->renderKeyListView($request); | ||||
} | } | ||||
$id = nonempty($edit, $delete); | $id = nonempty($edit, $delete); | ||||
if ($id && is_numeric($id)) { | if ($id && is_numeric($id)) { | ||||
// NOTE: Prevent editing/deleting of keys you don't own. | // NOTE: This prevents editing/deleting of keys not owned by the user. | ||||
$key = id(new PhabricatorUserSSHKey())->loadOneWhere( | $key = id(new PhabricatorUserSSHKey())->loadOneWhere( | ||||
'userPHID = %s AND id = %d', | 'userPHID = %s AND id = %d', | ||||
$user->getPHID(), | $user->getPHID(), | ||||
(int)$id); | (int)$id); | ||||
if (!$key) { | if (!$key) { | ||||
return new Aphront404Response(); | return new Aphront404Response(); | ||||
} | } | ||||
} else { | } else { | ||||
▲ Show 20 Lines • Show All 88 Lines • ▼ Show 20 Lines | if ($is_new) { | ||||
$header = pht('Add New SSH Public Key'); | $header = pht('Add New SSH Public Key'); | ||||
$save = pht('Add Key'); | $save = pht('Add Key'); | ||||
} else { | } else { | ||||
$header = pht('Edit SSH Public Key'); | $header = pht('Edit SSH Public Key'); | ||||
$save = pht('Save Changes'); | $save = pht('Save Changes'); | ||||
} | } | ||||
$form = id(new AphrontFormView()) | $form = id(new AphrontFormView()) | ||||
->setUser($user) | ->setUser($viewer) | ||||
->addHiddenInput('edit', $is_new ? 'true' : $key->getID()) | ->addHiddenInput('edit', $is_new ? 'true' : $key->getID()) | ||||
->appendChild( | ->appendChild( | ||||
id(new AphrontFormTextControl()) | id(new AphrontFormTextControl()) | ||||
->setLabel(pht('Name')) | ->setLabel(pht('Name')) | ||||
->setName('name') | ->setName('name') | ||||
->setValue($key->getName()) | ->setValue($key->getName()) | ||||
->setError($e_name)) | ->setError($e_name)) | ||||
->appendChild( | ->appendChild( | ||||
Show All 11 Lines | $form_box = id(new PHUIObjectBoxView()) | ||||
->setHeaderText($header) | ->setHeaderText($header) | ||||
->setFormErrors($errors) | ->setFormErrors($errors) | ||||
->setForm($form); | ->setForm($form); | ||||
return $form_box; | return $form_box; | ||||
} | } | ||||
private function renderKeyListView(AphrontRequest $request) { | private function renderKeyListView(AphrontRequest $request) { | ||||
$user = $this->getUser(); | |||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$keys = id(new PhabricatorUserSSHKey())->loadAllWhere( | $keys = id(new PhabricatorUserSSHKey())->loadAllWhere( | ||||
'userPHID = %s', | 'userPHID = %s', | ||||
$user->getPHID()); | $user->getPHID()); | ||||
$rows = array(); | $rows = array(); | ||||
foreach ($keys as $key) { | foreach ($keys as $key) { | ||||
$rows[] = array( | $rows[] = array( | ||||
phutil_tag( | phutil_tag( | ||||
'a', | 'a', | ||||
array( | array( | ||||
'href' => $this->getPanelURI('?edit='.$key->getID()), | 'href' => $this->getPanelURI('?edit='.$key->getID()), | ||||
), | ), | ||||
$key->getName()), | $key->getName()), | ||||
$key->getKeyComment(), | $key->getKeyComment(), | ||||
$key->getKeyType(), | $key->getKeyType(), | ||||
phabricator_date($key->getDateCreated(), $user), | phabricator_date($key->getDateCreated(), $viewer), | ||||
phabricator_time($key->getDateCreated(), $user), | phabricator_time($key->getDateCreated(), $viewer), | ||||
javelin_tag( | javelin_tag( | ||||
'a', | 'a', | ||||
array( | array( | ||||
'href' => $this->getPanelURI('?delete='.$key->getID()), | 'href' => $this->getPanelURI('?delete='.$key->getID()), | ||||
'class' => 'small grey button', | 'class' => 'small grey button', | ||||
'sigil' => 'workflow', | 'sigil' => 'workflow', | ||||
), | ), | ||||
pht('Delete')), | pht('Delete')), | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | private function renderKeyListView(AphrontRequest $request) { | ||||
return $panel; | return $panel; | ||||
} | } | ||||
private function processDelete( | private function processDelete( | ||||
AphrontRequest $request, | AphrontRequest $request, | ||||
PhabricatorUserSSHKey $key) { | PhabricatorUserSSHKey $key) { | ||||
$user = $request->getUser(); | $viewer = $request->getUser(); | ||||
$user = $this->getUser(); | |||||
$name = phutil_tag('strong', array(), $key->getName()); | $name = phutil_tag('strong', array(), $key->getName()); | ||||
if ($request->isDialogFormPost()) { | if ($request->isDialogFormPost()) { | ||||
$key->delete(); | $key->delete(); | ||||
return id(new AphrontReloadResponse()) | return id(new AphrontReloadResponse()) | ||||
->setURI($this->getPanelURI()); | ->setURI($this->getPanelURI()); | ||||
} | } | ||||
$dialog = id(new AphrontDialogView()) | $dialog = id(new AphrontDialogView()) | ||||
->setUser($user) | ->setUser($viewer) | ||||
->addHiddenInput('delete', $key->getID()) | ->addHiddenInput('delete', $key->getID()) | ||||
->setTitle(pht('Really delete SSH Public Key?')) | ->setTitle(pht('Really delete SSH Public Key?')) | ||||
->appendChild(phutil_tag('p', array(), pht( | ->appendChild(phutil_tag('p', array(), pht( | ||||
'The key "%s" will be permanently deleted, and you will not longer be '. | 'The key "%s" will be permanently deleted, and you will not longer be '. | ||||
'able to use the corresponding private key to authenticate.', | 'able to use the corresponding private key to authenticate.', | ||||
$name))) | $name))) | ||||
->addSubmitButton(pht('Delete Public Key')) | ->addSubmitButton(pht('Delete Public Key')) | ||||
->addCancelButton($this->getPanelURI()); | ->addCancelButton($this->getPanelURI()); | ||||
return id(new AphrontDialogResponse()) | return id(new AphrontDialogResponse()) | ||||
->setDialog($dialog); | ->setDialog($dialog); | ||||
} | } | ||||
private function processGenerate( | private function processGenerate(AphrontRequest $request) { | ||||
AphrontRequest $request) { | $user = $this->getUser(); | ||||
$viewer = $request->getUser(); | $viewer = $request->getUser(); | ||||
$is_self = ($user->getPHID() == $viewer->getPHID()); | |||||
if ($request->isFormPost()) { | if ($request->isFormPost()) { | ||||
$keys = PhabricatorSSHKeyGenerator::generateKeypair(); | $keys = PhabricatorSSHKeyGenerator::generateKeypair(); | ||||
list($public_key, $private_key) = $keys; | list($public_key, $private_key) = $keys; | ||||
$file = PhabricatorFile::buildFromFileDataOrHash( | $file = PhabricatorFile::buildFromFileDataOrHash( | ||||
$private_key, | $private_key, | ||||
array( | array( | ||||
'name' => 'id_rsa_phabricator.key', | 'name' => 'id_rsa_phabricator.key', | ||||
'ttl' => time() + (60 * 10), | 'ttl' => time() + (60 * 10), | ||||
'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, | 'viewPolicy' => PhabricatorPolicies::POLICY_NOONE, | ||||
)); | )); | ||||
$key = id(new PhabricatorUserSSHKey()) | $key = id(new PhabricatorUserSSHKey()) | ||||
->setUserPHID($viewer->getPHID()) | ->setUserPHID($user->getPHID()) | ||||
->setName('id_rsa_phabricator') | ->setName('id_rsa_phabricator') | ||||
->setKeyType('rsa') | ->setKeyType('rsa') | ||||
->setKeyBody($public_key) | ->setKeyBody($public_key) | ||||
->setKeyHash(md5($public_key)) | ->setKeyHash(md5($public_key)) | ||||
->setKeyComment(pht('Generated Key')) | ->setKeyComment(pht('Generated Key')) | ||||
->save(); | ->save(); | ||||
// NOTE: We're disabling workflow on submit so the download works. We're | // NOTE: We're disabling workflow on submit so the download works. We're | ||||
// disabling workflow on cancel so the page reloads, showing the new | // disabling workflow on cancel so the page reloads, showing the new | ||||
// key. | // key. | ||||
if ($is_self) { | |||||
$what_happened = pht( | |||||
'The public key has been associated with your Phabricator '. | |||||
'account. Use the button below to download the private key.'); | |||||
} else { | |||||
$what_happened = pht( | |||||
'The public key has been associated with the %s account. '. | |||||
'Use the button below to download the private key.', | |||||
phutil_tag('strong', array(), $user->getUsername())); | |||||
} | |||||
$dialog = id(new AphrontDialogView()) | $dialog = id(new AphrontDialogView()) | ||||
->setTitle(pht('Download Private Key')) | ->setTitle(pht('Download Private Key')) | ||||
->setUser($viewer) | ->setUser($viewer) | ||||
->setDisableWorkflowOnCancel(true) | ->setDisableWorkflowOnCancel(true) | ||||
->setDisableWorkflowOnSubmit(true) | ->setDisableWorkflowOnSubmit(true) | ||||
->setSubmitURI($file->getDownloadURI()) | ->setSubmitURI($file->getDownloadURI()) | ||||
->appendParagraph( | ->appendParagraph( | ||||
pht( | pht( | ||||
'Successfully generated a new keypair.')) | 'Successfully generated a new keypair.')) | ||||
->appendParagraph( | ->appendParagraph($what_happened) | ||||
pht( | |||||
'The public key has been associated with your Phabricator '. | |||||
'account. Use the button below to download the private key.')) | |||||
->appendParagraph( | ->appendParagraph( | ||||
pht( | pht( | ||||
'After you download the private key, it will be destroyed. '. | 'After you download the private key, it will be destroyed. '. | ||||
'You will not be able to retrieve it if you lose your copy.')) | 'You will not be able to retrieve it if you lose your copy.')) | ||||
->addSubmitButton(pht('Download Private Key')) | ->addSubmitButton(pht('Download Private Key')) | ||||
->addCancelButton($this->getPanelURI(), pht('Done')); | ->addCancelButton($this->getPanelURI(), pht('Done')); | ||||
return id(new AphrontDialogResponse()) | return id(new AphrontDialogResponse()) | ||||
->setDialog($dialog); | ->setDialog($dialog); | ||||
} | } | ||||
$dialog = id(new AphrontDialogView()) | $dialog = id(new AphrontDialogView()) | ||||
->setUser($viewer) | ->setUser($viewer) | ||||
->addCancelButton($this->getPanelURI()); | ->addCancelButton($this->getPanelURI()); | ||||
try { | try { | ||||
PhabricatorSSHKeyGenerator::assertCanGenerateKeypair(); | PhabricatorSSHKeyGenerator::assertCanGenerateKeypair(); | ||||
if ($is_self) { | |||||
$explain = pht( | |||||
'This will generate an SSH keypair, associate the public key '. | |||||
'with your account, and let you download the private key.'); | |||||
} else { | |||||
$explain = pht( | |||||
'This will generate an SSH keypair, associate the public key with '. | |||||
'the %s account, and let you download the private key.', | |||||
phutil_tag('strong', array(), $user->getUsername())); | |||||
} | |||||
$dialog | $dialog | ||||
->addHiddenInput('generate', true) | ->addHiddenInput('generate', true) | ||||
->setTitle(pht('Generate New Keypair')) | ->setTitle(pht('Generate New Keypair')) | ||||
->appendParagraph( | ->appendParagraph($explain) | ||||
pht( | |||||
"This will generate an SSH keypair, associate the public key ". | |||||
"with your account, and let you download the private key.")) | |||||
->appendParagraph( | ->appendParagraph( | ||||
pht( | pht( | ||||
"Phabricator will not retain a copy of the private key.")) | "Phabricator will not retain a copy of the private key.")) | ||||
->addSubmitButton(pht('Generate Keypair')); | ->addSubmitButton(pht('Generate Keypair')); | ||||
} catch (Exception $ex) { | } catch (Exception $ex) { | ||||
$dialog | $dialog | ||||
->setTitle(pht('Unable to Generate Keys')) | ->setTitle(pht('Unable to Generate Keys')) | ||||
->appendParagraph($ex->getMessage()); | ->appendParagraph($ex->getMessage()); | ||||
} | } | ||||
return id(new AphrontDialogResponse()) | return id(new AphrontDialogResponse()) | ||||
->setDialog($dialog); | ->setDialog($dialog); | ||||
} | } | ||||
} | } |