2011-07-22 19:17:57 +02:00
|
|
|
<?php
|
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
final class PhabricatorSettingsPanelSSHKeys
|
|
|
|
extends PhabricatorSettingsPanel {
|
2011-07-22 19:17:57 +02:00
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
public function getPanelKey() {
|
|
|
|
return 'ssh';
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getPanelName() {
|
|
|
|
return pht('SSH Public Keys');
|
|
|
|
}
|
2011-07-22 19:17:57 +02:00
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
public function getPanelGroup() {
|
|
|
|
return pht('Authentication');
|
|
|
|
}
|
|
|
|
|
|
|
|
public function isEnabled() {
|
2011-07-24 20:02:08 +02:00
|
|
|
return PhabricatorEnv::getEnvConfig('auth.sshkeys.enabled');
|
|
|
|
}
|
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
public function processRequest(AphrontRequest $request) {
|
2011-07-24 20:02:08 +02:00
|
|
|
|
2011-07-22 19:17:57 +02:00
|
|
|
$user = $request->getUser();
|
|
|
|
|
|
|
|
$edit = $request->getStr('edit');
|
|
|
|
$delete = $request->getStr('delete');
|
|
|
|
if (!$edit && !$delete) {
|
2012-08-13 21:37:26 +02:00
|
|
|
return $this->renderKeyListView($request);
|
2011-07-22 19:17:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$id = nonempty($edit, $delete);
|
|
|
|
|
|
|
|
if ($id && is_numeric($id)) {
|
|
|
|
// NOTE: Prevent editing/deleting of keys you don't own.
|
|
|
|
$key = id(new PhabricatorUserSSHKey())->loadOneWhere(
|
|
|
|
'userPHID = %s AND id = %d',
|
|
|
|
$user->getPHID(),
|
2012-08-13 21:37:26 +02:00
|
|
|
(int)$id);
|
2011-07-22 19:17:57 +02:00
|
|
|
if (!$key) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$key = new PhabricatorUserSSHKey();
|
|
|
|
$key->setUserPHID($user->getPHID());
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($delete) {
|
2012-08-13 21:37:26 +02:00
|
|
|
return $this->processDelete($request, $key);
|
2011-07-22 19:17:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$e_name = true;
|
|
|
|
$e_key = true;
|
|
|
|
$errors = array();
|
|
|
|
$entire_key = $key->getEntireKey();
|
|
|
|
if ($request->isFormPost()) {
|
|
|
|
$key->setName($request->getStr('name'));
|
|
|
|
$entire_key = $request->getStr('key');
|
|
|
|
|
|
|
|
if (!strlen($entire_key)) {
|
|
|
|
$errors[] = 'You must provide an SSH Public Key.';
|
|
|
|
$e_key = 'Required';
|
|
|
|
} else {
|
|
|
|
$parts = str_replace("\n", '', trim($entire_key));
|
|
|
|
$parts = preg_split('/\s+/', $parts);
|
|
|
|
if (count($parts) == 2) {
|
|
|
|
$parts[] = ''; // Add an empty comment part.
|
|
|
|
} else if (count($parts) == 3) {
|
|
|
|
// This is the expected case.
|
|
|
|
} else {
|
|
|
|
if (preg_match('/private\s*key/i', $entire_key)) {
|
|
|
|
// Try to give the user a better error message if it looks like
|
|
|
|
// they uploaded a private key.
|
|
|
|
$e_key = 'Invalid';
|
|
|
|
$errors[] = 'Provide your public key, not your private key!';
|
|
|
|
} else {
|
|
|
|
$e_key = 'Invalid';
|
|
|
|
$errors[] = 'Provided public key is not properly formatted.';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors) {
|
|
|
|
list($type, $body, $comment) = $parts;
|
|
|
|
if (!preg_match('/^ssh-dsa|ssh-rsa$/', $type)) {
|
|
|
|
$e_key = 'Invalid';
|
|
|
|
$errors[] = 'Public key should be "ssh-dsa" or "ssh-rsa".';
|
|
|
|
} else {
|
|
|
|
$key->setKeyType($type);
|
|
|
|
$key->setKeyBody($body);
|
2012-03-10 03:06:39 +01:00
|
|
|
$key->setKeyHash(md5($body));
|
2011-07-22 19:17:57 +02:00
|
|
|
$key->setKeyComment($comment);
|
|
|
|
|
|
|
|
$e_key = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strlen($key->getName())) {
|
|
|
|
$errors[] = 'You must name this public key.';
|
|
|
|
$e_name = 'Required';
|
|
|
|
} else {
|
|
|
|
$e_name = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$errors) {
|
|
|
|
try {
|
|
|
|
$key->save();
|
|
|
|
return id(new AphrontRedirectResponse())
|
2012-08-13 21:37:26 +02:00
|
|
|
->setURI($this->getPanelURI());
|
2011-07-22 19:17:57 +02:00
|
|
|
} catch (AphrontQueryDuplicateKeyException $ex) {
|
|
|
|
$e_key = 'Duplicate';
|
|
|
|
$errors[] = 'This public key is already associated with a user '.
|
|
|
|
'account.';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$error_view = null;
|
|
|
|
if ($errors) {
|
|
|
|
$error_view = new AphrontErrorView();
|
|
|
|
$error_view->setTitle('Form Errors');
|
|
|
|
$error_view->setErrors($errors);
|
|
|
|
}
|
|
|
|
|
|
|
|
$is_new = !$key->getID();
|
|
|
|
|
|
|
|
if ($is_new) {
|
|
|
|
$header = 'Add New SSH Public Key';
|
|
|
|
$save = 'Add Key';
|
|
|
|
} else {
|
|
|
|
$header = 'Edit SSH Public Key';
|
|
|
|
$save = 'Save Changes';
|
|
|
|
}
|
|
|
|
|
|
|
|
$form = id(new AphrontFormView())
|
|
|
|
->setUser($user)
|
|
|
|
->addHiddenInput('edit', $is_new ? 'true' : $key->getID())
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextControl())
|
|
|
|
->setLabel('Name')
|
|
|
|
->setName('name')
|
|
|
|
->setValue($key->getName())
|
|
|
|
->setError($e_name))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormTextAreaControl())
|
|
|
|
->setLabel('Public Key')
|
|
|
|
->setName('key')
|
|
|
|
->setValue($entire_key)
|
|
|
|
->setError($e_key))
|
|
|
|
->appendChild(
|
|
|
|
id(new AphrontFormSubmitControl())
|
2012-08-13 21:37:26 +02:00
|
|
|
->addCancelButton($this->getPanelURI())
|
2011-07-22 19:17:57 +02:00
|
|
|
->setValue($save));
|
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->setHeader($header);
|
|
|
|
$panel->appendChild($form);
|
2013-01-16 16:49:05 +01:00
|
|
|
$panel->setNoBackground();
|
2011-07-22 19:17:57 +02:00
|
|
|
|
|
|
|
return id(new AphrontNullView())
|
|
|
|
->appendChild(
|
|
|
|
array(
|
|
|
|
$error_view,
|
|
|
|
$panel,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
private function renderKeyListView(AphrontRequest $request) {
|
|
|
|
|
2011-07-22 19:17:57 +02:00
|
|
|
$user = $request->getUser();
|
|
|
|
|
|
|
|
$keys = id(new PhabricatorUserSSHKey())->loadAllWhere(
|
|
|
|
'userPHID = %s',
|
|
|
|
$user->getPHID());
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($keys as $key) {
|
|
|
|
$rows[] = array(
|
2013-01-18 03:43:35 +01:00
|
|
|
phutil_tag(
|
2011-07-22 19:17:57 +02:00
|
|
|
'a',
|
|
|
|
array(
|
2012-08-13 21:37:26 +02:00
|
|
|
'href' => $this->getPanelURI('?edit='.$key->getID()),
|
2011-07-22 19:17:57 +02:00
|
|
|
),
|
2013-01-18 03:43:35 +01:00
|
|
|
$key->getName()),
|
2011-07-22 19:17:57 +02:00
|
|
|
phutil_escape_html($key->getKeyComment()),
|
|
|
|
phutil_escape_html($key->getKeyType()),
|
|
|
|
phabricator_date($key->getDateCreated(), $user),
|
|
|
|
phabricator_time($key->getDateCreated(), $user),
|
2013-01-25 21:57:17 +01:00
|
|
|
javelin_tag(
|
2011-07-22 19:17:57 +02:00
|
|
|
'a',
|
|
|
|
array(
|
2012-08-13 21:37:26 +02:00
|
|
|
'href' => $this->getPanelURI('?delete='.$key->getID()),
|
2011-07-22 19:17:57 +02:00
|
|
|
'class' => 'small grey button',
|
|
|
|
'sigil' => 'workflow',
|
|
|
|
),
|
|
|
|
'Delete'),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$table = new AphrontTableView($rows);
|
|
|
|
$table->setNoDataString("You haven't added any SSH Public Keys.");
|
|
|
|
$table->setHeaders(
|
|
|
|
array(
|
|
|
|
'Name',
|
|
|
|
'Comment',
|
|
|
|
'Type',
|
|
|
|
'Created',
|
|
|
|
'Time',
|
|
|
|
'',
|
|
|
|
));
|
|
|
|
$table->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'wide pri',
|
|
|
|
'',
|
|
|
|
'',
|
|
|
|
'',
|
|
|
|
'right',
|
|
|
|
'action',
|
|
|
|
));
|
|
|
|
|
|
|
|
$panel = new AphrontPanelView();
|
|
|
|
$panel->addButton(
|
2013-01-18 03:57:09 +01:00
|
|
|
phutil_tag(
|
2011-07-22 19:17:57 +02:00
|
|
|
'a',
|
|
|
|
array(
|
2012-08-13 21:37:26 +02:00
|
|
|
'href' => $this->getPanelURI('?edit=true'),
|
2011-07-22 19:17:57 +02:00
|
|
|
'class' => 'green button',
|
|
|
|
),
|
|
|
|
'Add New Public Key'));
|
|
|
|
$panel->setHeader('SSH Public Keys');
|
|
|
|
$panel->appendChild($table);
|
2013-01-16 16:49:05 +01:00
|
|
|
$panel->setNoBackground();
|
2011-07-22 19:17:57 +02:00
|
|
|
|
|
|
|
return $panel;
|
|
|
|
}
|
|
|
|
|
2012-08-13 21:37:26 +02:00
|
|
|
private function processDelete(
|
|
|
|
AphrontRequest $request,
|
|
|
|
PhabricatorUserSSHKey $key) {
|
|
|
|
|
2011-07-22 19:17:57 +02:00
|
|
|
$user = $request->getUser();
|
|
|
|
|
|
|
|
$name = phutil_escape_html($key->getName());
|
|
|
|
|
|
|
|
if ($request->isDialogFormPost()) {
|
|
|
|
$key->delete();
|
|
|
|
return id(new AphrontReloadResponse())
|
2012-08-13 21:37:26 +02:00
|
|
|
->setURI($this->getPanelURI());
|
2011-07-22 19:17:57 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
$dialog = id(new AphrontDialogView())
|
|
|
|
->setUser($user)
|
|
|
|
->addHiddenInput('delete', $key->getID())
|
|
|
|
->setTitle('Really delete SSH Public Key?')
|
|
|
|
->appendChild(
|
|
|
|
'<p>The key "<strong>'.$name.'</strong>" will be permanently deleted, '.
|
|
|
|
'and you will not longer be able to use the corresponding private key '.
|
|
|
|
'to authenticate.</p>')
|
|
|
|
->addSubmitButton('Delete Public Key')
|
2012-08-13 21:37:26 +02:00
|
|
|
->addCancelButton($this->getPanelURI());
|
2011-07-22 19:17:57 +02:00
|
|
|
|
|
|
|
return id(new AphrontDialogResponse())
|
|
|
|
->setDialog($dialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|