Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F14081147
D18894.id45308.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
22 KB
Referenced Files
None
Subscribers
None
D18894.id45308.diff
View Options
diff --git a/resources/sql/autopatches/20180120.auth.01.password.sql b/resources/sql/autopatches/20180120.auth.01.password.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180120.auth.01.password.sql
@@ -0,0 +1,10 @@
+CREATE TABLE {$NAMESPACE}_auth.auth_password (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ objectPHID VARBINARY(64) NOT NULL,
+ passwordType VARCHAR(64) NOT NULL COLLATE {$COLLATE_TEXT},
+ passwordHash VARCHAR(128) NOT NULL COLLATE {$COLLATE_TEXT},
+ isRevoked BOOL NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
diff --git a/resources/sql/autopatches/20180120.auth.02.passwordxaction.sql b/resources/sql/autopatches/20180120.auth.02.passwordxaction.sql
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20180120.auth.02.passwordxaction.sql
@@ -0,0 +1,19 @@
+CREATE TABLE {$NAMESPACE}_auth.auth_passwordtransaction (
+ 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
@@ -2088,7 +2088,16 @@
'PhabricatorAuthOldOAuthRedirectController' => 'applications/auth/controller/PhabricatorAuthOldOAuthRedirectController.php',
'PhabricatorAuthOneTimeLoginController' => 'applications/auth/controller/PhabricatorAuthOneTimeLoginController.php',
'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthOneTimeLoginTemporaryTokenType.php',
+ 'PhabricatorAuthPassword' => 'applications/auth/storage/PhabricatorAuthPassword.php',
+ 'PhabricatorAuthPasswordEditor' => 'applications/auth/editor/PhabricatorAuthPasswordEditor.php',
+ 'PhabricatorAuthPasswordPHIDType' => 'applications/auth/phid/PhabricatorAuthPasswordPHIDType.php',
+ 'PhabricatorAuthPasswordQuery' => 'applications/auth/query/PhabricatorAuthPasswordQuery.php',
'PhabricatorAuthPasswordResetTemporaryTokenType' => 'applications/auth/tokentype/PhabricatorAuthPasswordResetTemporaryTokenType.php',
+ 'PhabricatorAuthPasswordRevokeTransaction' => 'applications/auth/xaction/PhabricatorAuthPasswordRevokeTransaction.php',
+ 'PhabricatorAuthPasswordRevoker' => 'applications/auth/revoker/PhabricatorAuthPasswordRevoker.php',
+ 'PhabricatorAuthPasswordTestCase' => 'applications/auth/__tests__/PhabricatorAuthPasswordTestCase.php',
+ 'PhabricatorAuthPasswordTransaction' => 'applications/auth/storage/PhabricatorAuthPasswordTransaction.php',
+ 'PhabricatorAuthPasswordTransactionType' => 'applications/auth/xaction/PhabricatorAuthPasswordTransactionType.php',
'PhabricatorAuthProvider' => 'applications/auth/provider/PhabricatorAuthProvider.php',
'PhabricatorAuthProviderConfig' => 'applications/auth/storage/PhabricatorAuthProviderConfig.php',
'PhabricatorAuthProviderConfigController' => 'applications/auth/controller/config/PhabricatorAuthProviderConfigController.php',
@@ -3479,6 +3488,7 @@
'PhabricatorPagerUIExample' => 'applications/uiexample/examples/PhabricatorPagerUIExample.php',
'PhabricatorPassphraseApplication' => 'applications/passphrase/application/PhabricatorPassphraseApplication.php',
'PhabricatorPasswordAuthProvider' => 'applications/auth/provider/PhabricatorPasswordAuthProvider.php',
+ 'PhabricatorPasswordDestructionEngineExtension' => 'applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.php',
'PhabricatorPasswordHasher' => 'infrastructure/util/password/PhabricatorPasswordHasher.php',
'PhabricatorPasswordHasherTestCase' => 'infrastructure/util/password/__tests__/PhabricatorPasswordHasherTestCase.php',
'PhabricatorPasswordHasherUnavailableException' => 'infrastructure/util/password/PhabricatorPasswordHasherUnavailableException.php',
@@ -7363,7 +7373,21 @@
'PhabricatorAuthOldOAuthRedirectController' => 'PhabricatorAuthController',
'PhabricatorAuthOneTimeLoginController' => 'PhabricatorAuthController',
'PhabricatorAuthOneTimeLoginTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType',
+ 'PhabricatorAuthPassword' => array(
+ 'PhabricatorAuthDAO',
+ 'PhabricatorPolicyInterface',
+ 'PhabricatorDestructibleInterface',
+ 'PhabricatorApplicationTransactionInterface',
+ ),
+ 'PhabricatorAuthPasswordEditor' => 'PhabricatorApplicationTransactionEditor',
+ 'PhabricatorAuthPasswordPHIDType' => 'PhabricatorPHIDType',
+ 'PhabricatorAuthPasswordQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'PhabricatorAuthPasswordResetTemporaryTokenType' => 'PhabricatorAuthTemporaryTokenType',
+ 'PhabricatorAuthPasswordRevokeTransaction' => 'PhabricatorAuthPasswordTransactionType',
+ 'PhabricatorAuthPasswordRevoker' => 'PhabricatorAuthRevoker',
+ 'PhabricatorAuthPasswordTestCase' => 'PhabricatorTestCase',
+ 'PhabricatorAuthPasswordTransaction' => 'PhabricatorApplicationTransaction',
+ 'PhabricatorAuthPasswordTransactionType' => 'PhabricatorModularTransactionType',
'PhabricatorAuthProvider' => 'Phobject',
'PhabricatorAuthProviderConfig' => array(
'PhabricatorAuthDAO',
@@ -8980,6 +9004,7 @@
'PhabricatorPagerUIExample' => 'PhabricatorUIExample',
'PhabricatorPassphraseApplication' => 'PhabricatorApplication',
'PhabricatorPasswordAuthProvider' => 'PhabricatorAuthProvider',
+ 'PhabricatorPasswordDestructionEngineExtension' => 'PhabricatorDestructionEngineExtension',
'PhabricatorPasswordHasher' => 'Phobject',
'PhabricatorPasswordHasherTestCase' => 'PhabricatorTestCase',
'PhabricatorPasswordHasherUnavailableException' => 'Exception',
diff --git a/src/applications/auth/__tests__/PhabricatorAuthPasswordTestCase.php b/src/applications/auth/__tests__/PhabricatorAuthPasswordTestCase.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/__tests__/PhabricatorAuthPasswordTestCase.php
@@ -0,0 +1,31 @@
+<?php
+
+final class PhabricatorAuthPasswordTestCase extends PhabricatorTestCase {
+
+ protected function getPhabricatorTestCaseConfiguration() {
+ return array(
+ self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
+ );
+ }
+
+ public function testCompare() {
+ $password1 = new PhutilOpaqueEnvelope('hunter2');
+ $password2 = new PhutilOpaqueEnvelope('hunter3');
+
+ $user = $this->generateNewTestUser();
+ $type = PhabricatorAuthPassword::PASSWORD_TYPE_TEST;
+
+ $pass = PhabricatorAuthPassword::initializeNewPassword($user, $type)
+ ->setPassword($password1, $user)
+ ->save();
+
+ $this->assertTrue(
+ $pass->comparePassword($password1, $user),
+ pht('Good password should match.'));
+
+ $this->assertFalse(
+ $pass->comparePassword($password2, $user),
+ pht('Bad password should not match.'));
+ }
+
+}
diff --git a/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php b/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/editor/PhabricatorAuthPasswordEditor.php
@@ -0,0 +1,22 @@
+<?php
+
+final class PhabricatorAuthPasswordEditor
+ extends PhabricatorApplicationTransactionEditor {
+
+ public function getEditorApplicationClass() {
+ return 'PhabricatorAuthApplication';
+ }
+
+ public function getEditorObjectsDescription() {
+ return pht('Passwords');
+ }
+
+ public function getCreateObjectTitle($author, $object) {
+ return pht('%s created this password.', $author);
+ }
+
+ public function getCreateObjectTitleForFeed($author, $object) {
+ return pht('%s created %s.', $author, $object);
+ }
+
+}
diff --git a/src/applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.php b/src/applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/extension/PhabricatorPasswordDestructionEngineExtension.php
@@ -0,0 +1,29 @@
+<?php
+
+final class PhabricatorPasswordDestructionEngineExtension
+ extends PhabricatorDestructionEngineExtension {
+
+ const EXTENSIONKEY = 'passwords';
+
+ public function getExtensionName() {
+ return pht('Passwords');
+ }
+
+ public function destroyObject(
+ PhabricatorDestructionEngine $engine,
+ $object) {
+
+ $viewer = $engine->getViewer();
+ $object_phid = $object->getPHID();
+
+ $passwords = id(new PhabricatorAuthPasswordQuery())
+ ->setViewer($viewer)
+ ->withObjectPHIDs(array($object_phid))
+ ->execute();
+
+ foreach ($passwords as $password) {
+ $engine->destroyObject($password);
+ }
+ }
+
+}
diff --git a/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php b/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/phid/PhabricatorAuthPasswordPHIDType.php
@@ -0,0 +1,36 @@
+<?php
+
+final class PhabricatorAuthPasswordPHIDType extends PhabricatorPHIDType {
+
+ const TYPECONST = 'APAS';
+
+ public function getTypeName() {
+ return pht('Auth Password');
+ }
+
+ public function newObject() {
+ return new PhabricatorAuthPassword();
+ }
+
+ public function getPHIDTypeApplicationClass() {
+ return 'PhabricatorAuthApplication';
+ }
+
+ protected function buildQueryForObjects(
+ PhabricatorObjectQuery $query,
+ array $phids) {
+ return id(new PhabricatorAuthPasswordQuery())
+ ->withPHIDs($phids);
+ }
+
+ public function loadHandles(
+ PhabricatorHandleQuery $query,
+ array $handles,
+ array $objects) {
+
+ foreach ($handles as $phid => $handle) {
+ $password = $objects[$phid];
+ }
+ }
+
+}
diff --git a/src/applications/auth/query/PhabricatorAuthPasswordQuery.php b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/query/PhabricatorAuthPasswordQuery.php
@@ -0,0 +1,114 @@
+<?php
+
+final class PhabricatorAuthPasswordQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $objectPHIDs;
+ private $passwordTypes;
+ private $isRevoked;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withObjectPHIDs(array $object_phids) {
+ $this->objectPHIDs = $object_phids;
+ return $this;
+ }
+
+ public function withPasswordTypes(array $types) {
+ $this->passwordTypes = $types;
+ return $this;
+ }
+
+ public function withIsRevoked($is_revoked) {
+ $this->isRevoked = $is_revoked;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new PhabricatorAuthPassword();
+ }
+
+ protected function loadPage() {
+ return $this->loadStandardPage($this->newResultObject());
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->objectPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'objectPHID IN (%Ls)',
+ $this->objectPHIDs);
+ }
+
+ if ($this->passwordTypes !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'passwordType IN (%Ls)',
+ $this->passwordTypes);
+ }
+
+ if ($this->isRevoked !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'isRevoked = %d',
+ (int)$this->isRevoked);
+ }
+
+ return $where;
+ }
+
+ protected function willFilterPage(array $passwords) {
+ $object_phids = mpull($passwords, 'getObjectPHID');
+
+ $objects = id(new PhabricatorObjectQuery())
+ ->setViewer($this->getViewer())
+ ->setParentQuery($this)
+ ->withPHIDs($object_phids)
+ ->execute();
+ $objects = mpull($objects, null, 'getPHID');
+
+ foreach ($passwords as $key => $password) {
+ $object = idx($objects, $password->getObjectPHID());
+ if (!$object) {
+ unset($passwords[$key]);
+ $this->didRejectResult($password);
+ continue;
+ }
+
+ $password->attachObject($object);
+ }
+
+ return $passwords;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'PhabricatorAuthApplication';
+ }
+
+}
diff --git a/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php b/src/applications/auth/revoker/PhabricatorAuthPasswordRevoker.php
copy from src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php
copy to src/applications/auth/revoker/PhabricatorAuthPasswordRevoker.php
--- a/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php
+++ b/src/applications/auth/revoker/PhabricatorAuthPasswordRevoker.php
@@ -1,52 +1,52 @@
<?php
-final class PhabricatorAuthSSHRevoker
+final class PhabricatorAuthPasswordRevoker
extends PhabricatorAuthRevoker {
- const REVOKERKEY = 'ssh';
+ const REVOKERKEY = 'password';
public function revokeAllCredentials() {
- $query = new PhabricatorAuthSSHKeyQuery();
+ $query = new PhabricatorAuthPasswordQuery();
return $this->revokeWithQuery($query);
}
public function revokeCredentialsFrom($object) {
- $query = id(new PhabricatorAuthSSHKeyQuery())
+ $query = id(new PhabricatorAuthPasswordQuery())
->withObjectPHIDs(array($object->getPHID()));
-
return $this->revokeWithQuery($query);
}
private function revokeWithQuery(PhabricatorAuthSSHKeyQuery $query) {
$viewer = $this->getViewer();
- // We're only going to revoke keys which have not already been revoked.
-
- $ssh_keys = $query
+ $passwords = $query
->setViewer($viewer)
- ->withIsActive(true)
+ ->withIsRevoked(false)
->execute();
$content_source = PhabricatorContentSource::newForSource(
PhabricatorDaemonContentSource::SOURCECONST);
+ $revoke_type = PhabricatorAuthPasswordRevokeTransaction::TRANSACTIONTYPE;
+
$auth_phid = id(new PhabricatorAuthApplication())->getPHID();
- foreach ($ssh_keys as $ssh_key) {
+ foreach ($passwords as $password) {
$xactions = array();
- $xactions[] = $ssh_key->getApplicationTransactionTemplate()
- ->setTransactionType(PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE)
- ->setNewValue(1);
- $editor = id(new PhabricatorAuthSSHKeyEditor())
+ $xactions[] = $password->getApplicationTransactionTemplate()
+ ->setTransactionType($revoke_type)
+ ->setNewValue(true);
+
+ $editor = $password->getApplicationTransactionEditor()
->setActor($viewer)
->setActingAsPHID($auth_phid)
->setContinueOnNoEffect(true)
->setContinueOnMissingFields(true)
->setContentSource($content_source)
- ->applyTransactions($ssh_key, $xactions);
+ ->applyTransactions($password, $xactions);
}
- return count($ssh_keys);
+ return count($passwords);
}
}
diff --git a/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php b/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php
--- a/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php
+++ b/src/applications/auth/revoker/PhabricatorAuthSSHRevoker.php
@@ -37,7 +37,7 @@
->setTransactionType(PhabricatorAuthSSHKeyTransaction::TYPE_DEACTIVATE)
->setNewValue(1);
- $editor = id(new PhabricatorAuthSSHKeyEditor())
+ $editor = $ssh_key->getApplicationTransactionEditor()
->setActor($viewer)
->setActingAsPHID($auth_phid)
->setContinueOnNoEffect(true)
diff --git a/src/applications/auth/storage/PhabricatorAuthPassword.php b/src/applications/auth/storage/PhabricatorAuthPassword.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/storage/PhabricatorAuthPassword.php
@@ -0,0 +1,167 @@
+<?php
+
+final class PhabricatorAuthPassword
+ extends PhabricatorAuthDAO
+ implements
+ PhabricatorPolicyInterface,
+ PhabricatorDestructibleInterface,
+ PhabricatorApplicationTransactionInterface {
+
+ protected $objectPHID;
+ protected $passwordType;
+ protected $passwordHash;
+ protected $isRevoked;
+
+ private $object = self::ATTACHABLE;
+
+ const PASSWORD_TYPE_ACCOUNT = 'account';
+ const PASSWORD_TYPE_VCS = 'vcs';
+ const PASSWORD_TYPE_TEST = 'test';
+
+ public static function initializeNewPassword(
+ PhabricatorUser $object,
+ $type) {
+
+ return id(new self())
+ ->setObjectPHID($object->getPHID())
+ ->attachObject($object)
+ ->setPasswordType($type)
+ ->setIsRevoked(0);
+ }
+
+ protected function getConfiguration() {
+ return array(
+ self::CONFIG_AUX_PHID => true,
+ self::CONFIG_COLUMN_SCHEMA => array(
+ 'passwordType' => 'text64',
+ 'passwordHash' => 'text128',
+ 'isRevoked' => 'bool',
+ ),
+ self::CONFIG_KEY_SCHEMA => array(
+ 'key_role' => array(
+ 'columns' => array('objectPHID', 'passwordType'),
+ ),
+ ),
+ ) + parent::getConfiguration();
+ }
+
+ public function getPHIDType() {
+ return PhabricatorAuthPasswordPHIDType::TYPECONST;
+ }
+
+ public function getObject() {
+ return $this->assertAttached($this->object);
+ }
+
+ public function attachObject($object) {
+ $this->object = $object;
+ return $this;
+ }
+
+ public function setPassword(
+ PhutilOpaqueEnvelope $password,
+ PhabricatorUser $object) {
+
+ $hasher = PhabricatorPasswordHasher::getBestHasher();
+
+ $digest = $this->digestPassword($password, $object);
+ $hash = $hasher->getPasswordHashForStorage($digest);
+ $raw_hash = $hash->openEnvelope();
+
+ return $this->setPasswordHash($raw_hash);
+ }
+
+ public function comparePassword(
+ PhutilOpaqueEnvelope $password,
+ PhabricatorUser $object) {
+
+ $digest = $this->digestPassword($password, $object);
+ $raw_hash = $this->getPasswordHash();
+ $hash = new PhutilOpaqueEnvelope($raw_hash);
+
+ return PhabricatorPasswordHasher::comparePassword($digest, $hash);
+ }
+
+ private function digestPassword(
+ PhutilOpaqueEnvelope $password,
+ PhabricatorUser $object) {
+
+ $object_phid = $object->getPHID();
+
+ if ($this->getObjectPHID() !== $object->getPHID()) {
+ throw new Exception(
+ pht(
+ 'This password is associated with a an object PHID ("%s") for '.
+ 'a different object than the provided one ("%s").',
+ $this->getObjectPHID(),
+ $object->getPHID()));
+ }
+
+ $raw_input = PhabricatorHash::digestPassword($password, $object_phid);
+
+ return new PhutilOpaqueEnvelope($raw_input);
+ }
+
+
+
+/* -( PhabricatorPolicyInterface )----------------------------------------- */
+
+
+ public function getCapabilities() {
+ return array(
+ PhabricatorPolicyCapability::CAN_VIEW,
+ );
+ }
+
+ public function getPolicy($capability) {
+ return PhabricatorPolicies::getMostOpenPolicy();
+ }
+
+ public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
+ return false;
+ }
+
+
+/* -( PhabricatorExtendedPolicyInterface )--------------------------------- */
+
+
+ public function getExtendedPolicy($capability, PhabricatorUser $viewer) {
+ return array(
+ array($this->getObject(), PhabricatorPolicyCapability::CAN_VIEW),
+ );
+ }
+
+
+/* -( PhabricatorDestructibleInterface )----------------------------------- */
+
+
+ public function destroyObjectPermanently(
+ PhabricatorDestructionEngine $engine) {
+ $this->delete();
+ }
+
+
+/* -( PhabricatorApplicationTransactionInterface )------------------------- */
+
+
+ public function getApplicationTransactionEditor() {
+ return new PhabricatorAuthPasswordEditor();
+ }
+
+ public function getApplicationTransactionObject() {
+ return $this;
+ }
+
+ public function getApplicationTransactionTemplate() {
+ return new PhabricatorAuthPasswordTransaction();
+ }
+
+ public function willRenderTimeline(
+ PhabricatorApplicationTransactionView $timeline,
+ AphrontRequest $request) {
+
+ return $timeline;
+ }
+
+
+}
diff --git a/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php b/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/storage/PhabricatorAuthPasswordTransaction.php
@@ -0,0 +1,21 @@
+<?php
+
+final class PhabricatorAuthPasswordTransaction
+ extends PhabricatorApplicationTransaction {
+
+ public function getApplicationName() {
+ return 'auth';
+ }
+
+ public function getApplicationTransactionType() {
+ return PhabricatorAuthPasswordPHIDType::TYPECONST;
+ }
+
+ public function getApplicationTransactionCommentObject() {
+ return null;
+ }
+
+ public function getBaseTransactionClass() {
+ return 'PhabricatorAuthPasswordTransactionType';
+ }
+}
diff --git a/src/applications/auth/xaction/PhabricatorAuthPasswordRevokeTransaction.php b/src/applications/auth/xaction/PhabricatorAuthPasswordRevokeTransaction.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/xaction/PhabricatorAuthPasswordRevokeTransaction.php
@@ -0,0 +1,32 @@
+<?php
+
+final class PhabricatorAuthPasswordRevokeTransaction
+ extends PhabricatorAuthPasswordTransactionType {
+
+ const TRANSACTIONTYPE = 'password.revoke';
+
+ public function generateOldValue($object) {
+ return (bool)$object->getIsRevoked();
+ }
+
+ public function generateNewValue($object, $value) {
+ return (bool)$value;
+ }
+
+ public function applyInternalEffects($object, $value) {
+ $object->setIsRevoked((int)$value);
+ }
+
+ public function getTitle() {
+ if ($this->getNewValue()) {
+ return pht(
+ '%s revoked this password.',
+ $this->renderAuthor());
+ } else {
+ return pht(
+ '%s reinstated this password.',
+ $this->renderAuthor());
+ }
+ }
+
+}
diff --git a/src/applications/auth/xaction/PhabricatorAuthPasswordTransactionType.php b/src/applications/auth/xaction/PhabricatorAuthPasswordTransactionType.php
new file mode 100644
--- /dev/null
+++ b/src/applications/auth/xaction/PhabricatorAuthPasswordTransactionType.php
@@ -0,0 +1,4 @@
+<?php
+
+abstract class PhabricatorAuthPasswordTransactionType
+ extends PhabricatorModularTransactionType {}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Nov 23, 6:35 PM (18 h, 30 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6779224
Default Alt Text
D18894.id45308.diff (22 KB)
Attached To
Mode
D18894: Add a more modern object for storing password hashes
Attached
Detach File
Event Timeline
Log In to Comment