Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15449830
D15947.id38401.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
18 KB
Referenced Files
None
Subscribers
None
D15947.id38401.diff
View Options
diff --git a/resources/sql/autopatches/20160519.ssh.01.xaction.sql b/resources/sql/autopatches/20160519.ssh.01.xaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20160519.ssh.01.xaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_auth.auth_sshkeytransaction (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ authorPHID VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ viewPolicy VARBINARY(64) NOT NULL,
+ editPolicy VARBINARY(64) NOT NULL,
+ commentPHID VARBINARY(64) DEFAULT NULL,
+ commentVersion INT UNSIGNED NOT NULL,
+ transactionType VARCHAR(32) COLLATE {$COLLATE_TEXT} NOT NULL,
+ oldValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ newValue LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ contentSource LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ metadata LONGTEXT COLLATE {$COLLATE_TEXT} NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+ UNIQUE KEY `key_phid` (`phid`),
+ KEY `key_object` (`objectPHID`)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1878,12 +1878,15 @@
'PhabricatorAuthSSHKeyController' => 'applications/auth/controller/PhabricatorAuthSSHKeyController.php',
'PhabricatorAuthSSHKeyDeactivateController' => 'applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php',
'PhabricatorAuthSSHKeyEditController' => 'applications/auth/controller/PhabricatorAuthSSHKeyEditController.php',
+ 'PhabricatorAuthSSHKeyEditor' => 'applications/auth/editor/PhabricatorAuthSSHKeyEditor.php',
'PhabricatorAuthSSHKeyGenerateController' => 'applications/auth/controller/PhabricatorAuthSSHKeyGenerateController.php',
'PhabricatorAuthSSHKeyListController' => 'applications/auth/controller/PhabricatorAuthSSHKeyListController.php',
'PhabricatorAuthSSHKeyPHIDType' => 'applications/auth/phid/PhabricatorAuthSSHKeyPHIDType.php',
'PhabricatorAuthSSHKeyQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyQuery.php',
'PhabricatorAuthSSHKeySearchEngine' => 'applications/auth/query/PhabricatorAuthSSHKeySearchEngine.php',
'PhabricatorAuthSSHKeyTableView' => 'applications/auth/view/PhabricatorAuthSSHKeyTableView.php',
+ 'PhabricatorAuthSSHKeyTransaction' => 'applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php',
+ 'PhabricatorAuthSSHKeyTransactionQuery' => 'applications/auth/query/PhabricatorAuthSSHKeyTransactionQuery.php',
'PhabricatorAuthSSHKeyViewController' => 'applications/auth/controller/PhabricatorAuthSSHKeyViewController.php',
'PhabricatorAuthSSHPublicKey' => 'applications/auth/sshkey/PhabricatorAuthSSHPublicKey.php',
'PhabricatorAuthSession' => 'applications/auth/storage/PhabricatorAuthSession.php',
@@ -6305,16 +6308,20 @@
'PhabricatorAuthDAO',
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
+ 'PhabricatorApplicationTransactionInterface',
),
'PhabricatorAuthSSHKeyController' => 'PhabricatorAuthController',
'PhabricatorAuthSSHKeyDeactivateController' => 'PhabricatorAuthSSHKeyController',
'PhabricatorAuthSSHKeyEditController' => 'PhabricatorAuthSSHKeyController',
+ 'PhabricatorAuthSSHKeyEditor' => 'PhabricatorApplicationTransactionEditor',
'PhabricatorAuthSSHKeyGenerateController' => 'PhabricatorAuthSSHKeyController',
'PhabricatorAuthSSHKeyListController' => 'PhabricatorAuthSSHKeyController',
'PhabricatorAuthSSHKeyPHIDType' => 'PhabricatorPHIDType',
'PhabricatorAuthSSHKeyQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthSSHKeySearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorAuthSSHKeyTableView' => 'AphrontView',
+ 'PhabricatorAuthSSHKeyTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorAuthSSHKeyTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
'PhabricatorAuthSSHKeyViewController' => 'PhabricatorAuthSSHKeyController',
'PhabricatorAuthSSHPublicKey' => 'Phobject',
'PhabricatorAuthSession' => array(
diff --git a/src/applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php b/src/applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php
--- a/src/applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php
+++ b/src/applications/auth/controller/PhabricatorAuthSSHKeyDeactivateController.php
@@ -27,10 +27,18 @@
$cancel_uri);
if ($request->isFormPost()) {
-
- // TODO: Convert to transactions.
- $key->setIsActive(null);
- $key->save();
+ $xactions = array();
+
+ $xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
+ ->setTransactionType(PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE)
+ ->setNewValue(true);
+
+ id(new PhabricatorAuthSSHKeyEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true)
+ ->setContinueOnMissingFields(true)
+ ->applyTransactions($key, $xactions);
return id(new AphrontRedirectResponse())->setURI($cancel_uri);
}
diff --git a/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php b/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php
--- a/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php
+++ b/src/applications/auth/controller/PhabricatorAuthSSHKeyEditController.php
@@ -59,51 +59,45 @@
$v_key = $key->getEntireKey();
$e_key = strlen($v_key) ? null : true;
- $errors = array();
+ $validation_exception = null;
if ($request->isFormPost()) {
+ $type_create = PhabricatorTransactions::TYPE_CREATE;
+ $type_name = PhabricatorAuthSSHKeyTransaction::TYPE_NAME;
+ $type_key = PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
+
+ $e_name = null;
+ $e_key = null;
+
$v_name = $request->getStr('name');
$v_key = $request->getStr('key');
- if (!strlen($v_name)) {
- $errors[] = pht('You must provide a name for this public key.');
- $e_name = pht('Required');
- } else {
- $key->setName($v_name);
- }
+ $xactions = array();
- if (!strlen($v_key)) {
- $errors[] = pht('You must provide a public key.');
- $e_key = pht('Required');
- } else {
- try {
- $public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($v_key);
-
- $type = $public_key->getType();
- $body = $public_key->getBody();
- $comment = $public_key->getComment();
-
- $key->setKeyType($type);
- $key->setKeyBody($body);
- $key->setKeyComment($comment);
-
- $e_key = null;
- } catch (Exception $ex) {
- $e_key = pht('Invalid');
- $errors[] = $ex->getMessage();
- }
+ if (!$key->getID()) {
+ $xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
+ ->setTransactionType(PhabricatorTransactions::TYPE_CREATE);
}
- if (!$errors) {
- try {
- $key->save();
- return id(new AphrontRedirectResponse())->setURI($key->getURI());
- } catch (Exception $ex) {
- $e_key = pht('Duplicate');
- $errors[] = pht(
- 'This public key is already associated with another user or '.
- 'device. Each key must unambiguously identify a single unique '.
- 'owner.');
- }
+ $xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
+ ->setTransactionType($type_name)
+ ->setNewValue($v_name);
+
+ $xactions[] = id(new PhabricatorAuthSSHKeyTransaction())
+ ->setTransactionType($type_key)
+ ->setNewValue($v_key);
+
+ $editor = id(new PhabricatorAuthSSHKeyEditor())
+ ->setActor($viewer)
+ ->setContentSourceFromRequest($request)
+ ->setContinueOnNoEffect(true);
+
+ try {
+ $editor->applyTransactions($key, $xactions);
+ return id(new AphrontRedirectResponse())->setURI($key->getURI());
+ } catch (PhabricatorApplicationTransactionValidationException $ex) {
+ $validation_exception = $ex;
+ $e_name = $ex->getShortMessage($type_name);
+ $e_key = $ex->getShortMessage($type_key);
}
}
@@ -134,7 +128,7 @@
return $this->newDialog()
->setTitle($title)
->setWidth(AphrontDialogView::WIDTH_FORM)
- ->setErrors($errors)
+ ->setValidationException($validation_exception)
->appendForm($form)
->addSubmitButton($save_button)
->addCancelButton($cancel_uri);
diff --git a/src/applications/auth/controller/PhabricatorAuthSSHKeyViewController.php b/src/applications/auth/controller/PhabricatorAuthSSHKeyViewController.php
--- a/src/applications/auth/controller/PhabricatorAuthSSHKeyViewController.php
+++ b/src/applications/auth/controller/PhabricatorAuthSSHKeyViewController.php
@@ -49,12 +49,10 @@
$crumbs->addTextCrumb($title);
$crumbs->setBorder(true);
- // TODO: This doesn't exist yet, build it.
- // $timeline = $this->buildTransactionTimeline(
- // $ssh_key,
- // new PhabricatorAuthSSHKeyTransactionQuery());
- // $timeline->setShouldTerminate(true);
- $timeline = null;
+ $timeline = $this->buildTransactionTimeline(
+ $ssh_key,
+ new PhabricatorAuthSSHKeyTransactionQuery());
+ $timeline->setShouldTerminate(true);
$view = id(new PHUITwoColumnView())
->setHeader($header)
@@ -113,6 +111,9 @@
->setUser($viewer);
$properties->addProperty(pht('SSH Key Type'), $ssh_key->getKeyType());
+ $properties->addProperty(
+ pht('Created'),
+ phabricator_datetime($ssh_key->getDateCreated(), $viewer));
return id(new PHUIObjectBoxView())
->setHeaderText(pht('Details'))
diff --git a/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php b/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/editor/PhabricatorAuthSSHKeyEditor.php
@@ -0,0 +1,180 @@
+<?php
+
+final class PhabricatorAuthSSHKeyEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorAuthApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('SSH Keys');
+ }
+
+ public function getTransactionTypes() {
+ $types = parent::getTransactionTypes();
+
+ $types[] = PhabricatorAuthSSHKeyTransaction::TYPE_NAME;
+ $types[] = PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
+ $types[] = PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE;
+
+ return $types;
+ }
+
+ protected function getCustomTransactionOldValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
+ return $object->getName();
+ case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
+ return $object->getEntireKey();
+ case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
+ return !$object->getIsActive();
+ }
+
+ }
+
+ protected function getCustomTransactionNewValue(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
+ case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
+ return $xaction->getNewValue();
+ case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
+ return (bool)$xaction->getNewValue();
+ }
+ }
+
+ protected function applyCustomInternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+
+ $value = $xaction->getNewValue();
+ switch ($xaction->getTransactionType()) {
+ case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
+ $object->setName($value);
+ return;
+ case PhabricatorAuthSSHKeyTransaction::TYPE_KEY:
+ $public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($value);
+
+ $type = $public_key->getType();
+ $body = $public_key->getBody();
+ $comment = $public_key->getComment();
+
+ $object->setKeyType($type);
+ $object->setKeyBody($body);
+ $object->setKeyComment($comment);
+ return;
+ case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
+ if ($value) {
+ $new = null;
+ } else {
+ $new = 1;
+ }
+
+ $object->setIsActive($new);
+ return;
+ }
+ }
+
+ protected function applyCustomExternalTransaction(
+ PhabricatorLiskDAO $object,
+ PhabricatorApplicationTransaction $xaction) {
+ return;
+ }
+
+ protected function validateTransaction(
+ PhabricatorLiskDAO $object,
+ $type,
+ array $xactions) {
+
+ $errors = parent::validateTransaction($object, $type, $xactions);
+
+ switch ($type) {
+ case PhabricatorAuthSSHKeyTransaction::TYPE_NAME:
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('SSH key name is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ }
+ break;
+
+ case PhabricatorAuthSSHKeyTransaction::TYPE_KEY;
+ $missing = $this->validateIsEmptyTextField(
+ $object->getName(),
+ $xactions);
+
+ if ($missing) {
+ $error = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Required'),
+ pht('SSH key material is required.'),
+ nonempty(last($xactions), null));
+
+ $error->setIsMissingFieldError(true);
+ $errors[] = $error;
+ } else {
+ foreach ($xactions as $xaction) {
+ $new = $xaction->getNewValue();
+
+ try {
+ $public_key = PhabricatorAuthSSHPublicKey::newFromRawKey($new);
+ } catch (Exception $ex) {
+ $errors[] = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Invalid'),
+ $ex->getMessage(),
+ $xaction);
+ }
+ }
+ }
+ break;
+
+ case PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE:
+ foreach ($xactions as $xaction) {
+ if (!$xaction->getNewValue()) {
+ $errors[] = new PhabricatorApplicationTransactionValidationError(
+ $type,
+ pht('Invalid'),
+ pht('SSH keys can not be reactivated.'),
+ $xaction);
+ }
+ }
+ break;
+ }
+
+ return $errors;
+ }
+
+ protected function didCatchDuplicateKeyException(
+ PhabricatorLiskDAO $object,
+ array $xactions,
+ Exception $ex) {
+
+ $errors = array();
+ $errors[] = new PhabricatorApplicationTransactionValidationError(
+ PhabricatorAuthSSHKeyTransaction::TYPE_KEY,
+ pht('Duplicate'),
+ pht(
+ 'This public key is already associated with another user or device. '.
+ 'Each key must unambiguously identify a single unique owner.'),
+ null);
+
+ throw new PhabricatorApplicationTransactionValidationException($errors);
+ }
+
+
+}
diff --git a/src/applications/auth/query/PhabricatorAuthSSHKeyTransactionQuery.php b/src/applications/auth/query/PhabricatorAuthSSHKeyTransactionQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/query/PhabricatorAuthSSHKeyTransactionQuery.php
@@ -0,0 +1,10 @@
+<?php
+
+final class PhabricatorAuthSSHKeyTransactionQuery
+ extends PhabricatorApplicationTransactionQuery {
+
+ public function getTemplateApplicationTransaction() {
+ return new PhabricatorAuthSSHKeyTransaction();
+ }
+
+}
diff --git a/src/applications/auth/storage/PhabricatorAuthSSHKey.php b/src/applications/auth/storage/PhabricatorAuthSSHKey.php
--- a/src/applications/auth/storage/PhabricatorAuthSSHKey.php
+++ b/src/applications/auth/storage/PhabricatorAuthSSHKey.php
@@ -4,7 +4,8 @@
extends PhabricatorAuthDAO
implements
PhabricatorPolicyInterface,
- PhabricatorDestructibleInterface {
+ PhabricatorDestructibleInterface,
+ PhabricatorApplicationTransactionInterface {
protected $objectPHID;
protected $name;
@@ -150,4 +151,26 @@
$this->saveTransaction();
}
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorAuthSSHKeyEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorAuthProviderConfigTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+ return $timeline;
+ }
+
}
diff --git a/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php b/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/storage/PhabricatorAuthSSHKeyTransaction.php
@@ -0,0 +1,55 @@
+<?php
+
+final class PhabricatorAuthSSHKeyTransaction
+ extends PhabricatorApplicationTransaction {
+
+ const TYPE_NAME = 'sshkey.name';
+ const TYPE_KEY = 'sshkey.key';
+ const TYPE_DEACTIVATE = 'sshkey.deactivate';
+
+ public function getApplicationName() {
+ return 'auth';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorAuthSSHKeyPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ public function getTitle() {
+ $author_phid = $this->getAuthorPHID();
+
+ $old = $this->getOldValue();
+ $new = $this->getNewValue();
+
+ switch ($this->getTransactionType()) {
+ case self::TYPE_NAME:
+ return pht(
+ '%s renamed this key from "%s" to "%s".',
+ $this->renderHandleLink($author_phid),
+ $old,
+ $new);
+ case self::TYPE_KEY:
+ return pht(
+ '%s updated the public key material for this SSH key.',
+ $this->renderHandleLink($author_phid));
+ case self::TYPE_DEACTIVATE:
+ if ($new) {
+ return pht(
+ '%s deactivated this key.',
+ $this->renderHandleLink($author_phid));
+ } else {
+ return pht(
+ '%s activated this key.',
+ $this->renderHandleLink($author_phid));
+ }
+
+ }
+
+ return parent::getTitle();
+ }
+
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 29, 12:23 PM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7711318
Default Alt Text
D15947.id38401.diff (18 KB)
Attached To
Mode
D15947: Use transactions to apply web UI SSH key edits
Attached
Detach File
Event Timeline
Log In to Comment