mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-29 10:12:41 +01:00
Write ExternalAccountIdentifiers when interacting with external authentication providers
Summary: Depends on D21015. When we sync an external account and get a list of account identifiers, write them to the database. Nothing reads them yet and we still write "accountId", this just prepares us for reads. Test Plan: Linked, refreshed, unlinked, and re-linked an external account. Peeked at the database and saw a sensible-looking row. Differential Revision: https://secure.phabricator.com/D21016
This commit is contained in:
parent
0872051bfa
commit
bcaf60015a
5 changed files with 125 additions and 4 deletions
|
@ -67,7 +67,7 @@ final class PhabricatorAuthUnlinkController
|
||||||
->setWorkflowKey($workflow_key)
|
->setWorkflowKey($workflow_key)
|
||||||
->requireHighSecurityToken($viewer, $request, $done_uri);
|
->requireHighSecurityToken($viewer, $request, $done_uri);
|
||||||
|
|
||||||
$account->delete();
|
$account->unlinkAccount();
|
||||||
|
|
||||||
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
id(new PhabricatorAuthSessionEngine())->terminateLoginSessions(
|
||||||
$viewer,
|
$viewer,
|
||||||
|
|
|
@ -216,6 +216,7 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
->setViewer($viewer)
|
->setViewer($viewer)
|
||||||
->withProviderConfigPHIDs(array($config->getPHID()))
|
->withProviderConfigPHIDs(array($config->getPHID()))
|
||||||
->withAccountIDs($raw_identifiers)
|
->withAccountIDs($raw_identifiers)
|
||||||
|
->needAccountIdentifiers(true)
|
||||||
->execute();
|
->execute();
|
||||||
if (!$accounts) {
|
if (!$accounts) {
|
||||||
$account = $this->newExternalAccount()
|
$account = $this->newExternalAccount()
|
||||||
|
@ -232,6 +233,17 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
implode(', ', $raw_identifiers)));
|
implode(', ', $raw_identifiers)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See T13493. Add all the identifiers to the account. In the case where
|
||||||
|
// an account initially has a lower-quality identifier (like an email
|
||||||
|
// address) and later adds a higher-quality identifier (like a GUID), this
|
||||||
|
// allows us to automatically upgrade toward the higher-quality identifier
|
||||||
|
// and survive API changes which remove the lower-quality identifier more
|
||||||
|
// gracefully.
|
||||||
|
|
||||||
|
foreach ($identifiers as $identifier) {
|
||||||
|
$account->appendIdentifier($identifier);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->didUpdateAccount($account);
|
return $this->didUpdateAccount($account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -351,7 +363,8 @@ abstract class PhabricatorAuthProvider extends Phobject {
|
||||||
return id(new PhabricatorExternalAccount())
|
return id(new PhabricatorExternalAccount())
|
||||||
->setAccountType($adapter->getAdapterType())
|
->setAccountType($adapter->getAdapterType())
|
||||||
->setAccountDomain($adapter->getAdapterDomain())
|
->setAccountDomain($adapter->getAdapterDomain())
|
||||||
->setProviderConfigPHID($config->getPHID());
|
->setProviderConfigPHID($config->getPHID())
|
||||||
|
->attachAccountIdentifiers(array());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLoginOrder() {
|
public function getLoginOrder() {
|
||||||
|
|
|
@ -22,6 +22,7 @@ final class PhabricatorExternalAccountQuery
|
||||||
private $needImages;
|
private $needImages;
|
||||||
private $accountSecrets;
|
private $accountSecrets;
|
||||||
private $providerConfigPHIDs;
|
private $providerConfigPHIDs;
|
||||||
|
private $needAccountIdentifiers;
|
||||||
|
|
||||||
public function withUserPHIDs(array $user_phids) {
|
public function withUserPHIDs(array $user_phids) {
|
||||||
$this->userPHIDs = $user_phids;
|
$this->userPHIDs = $user_phids;
|
||||||
|
@ -63,6 +64,11 @@ final class PhabricatorExternalAccountQuery
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function needAccountIdentifiers($need) {
|
||||||
|
$this->needAccountIdentifiers = $need;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
public function withProviderConfigPHIDs(array $phids) {
|
public function withProviderConfigPHIDs(array $phids) {
|
||||||
$this->providerConfigPHIDs = $phids;
|
$this->providerConfigPHIDs = $phids;
|
||||||
return $this;
|
return $this;
|
||||||
|
@ -132,6 +138,23 @@ final class PhabricatorExternalAccountQuery
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($this->needAccountIdentifiers) {
|
||||||
|
$account_phids = mpull($accounts, 'getPHID');
|
||||||
|
|
||||||
|
$identifiers = id(new PhabricatorExternalAccountIdentifierQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setParentQuery($this)
|
||||||
|
->withExternalAccountPHIDs($account_phids)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$identifiers = mgroup($identifiers, 'getExternalAccountPHID');
|
||||||
|
foreach ($accounts as $account) {
|
||||||
|
$account_phid = $account->getPHID();
|
||||||
|
$account_identifiers = idx($identifiers, $account_phid, array());
|
||||||
|
$account->attachAccountIdentifiers($account_identifiers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return $accounts;
|
return $accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ final class PhabricatorExternalAccount
|
||||||
|
|
||||||
private $profileImageFile = self::ATTACHABLE;
|
private $profileImageFile = self::ATTACHABLE;
|
||||||
private $providerConfig = self::ATTACHABLE;
|
private $providerConfig = self::ATTACHABLE;
|
||||||
|
private $accountIdentifiers = self::ATTACHABLE;
|
||||||
|
|
||||||
public function getProfileImageFile() {
|
public function getProfileImageFile() {
|
||||||
return $this->assertAttached($this->profileImageFile);
|
return $this->assertAttached($this->profileImageFile);
|
||||||
|
@ -78,7 +79,48 @@ final class PhabricatorExternalAccount
|
||||||
if (!$this->getAccountSecret()) {
|
if (!$this->getAccountSecret()) {
|
||||||
$this->setAccountSecret(Filesystem::readRandomCharacters(32));
|
$this->setAccountSecret(Filesystem::readRandomCharacters(32));
|
||||||
}
|
}
|
||||||
return parent::save();
|
|
||||||
|
$this->openTransaction();
|
||||||
|
|
||||||
|
$result = parent::save();
|
||||||
|
|
||||||
|
$account_phid = $this->getPHID();
|
||||||
|
$config_phid = $this->getProviderConfigPHID();
|
||||||
|
|
||||||
|
if ($this->accountIdentifiers !== self::ATTACHABLE) {
|
||||||
|
foreach ($this->getAccountIdentifiers() as $identifier) {
|
||||||
|
$identifier
|
||||||
|
->setExternalAccountPHID($account_phid)
|
||||||
|
->setProviderConfigPHID($config_phid)
|
||||||
|
->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->saveTransaction();
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unlinkAccount() {
|
||||||
|
|
||||||
|
// When unlinking an account, we disassociate it from the user and
|
||||||
|
// remove all the identifying information. We retain the PHID, the
|
||||||
|
// object itself, and the "ExternalAccountIdentifier" objects in the
|
||||||
|
// external table.
|
||||||
|
|
||||||
|
// TODO: This unlinks (but does not destroy) any profile image.
|
||||||
|
|
||||||
|
return $this
|
||||||
|
->setUserPHID(null)
|
||||||
|
->setDisplayName(null)
|
||||||
|
->setUsername(null)
|
||||||
|
->setRealName(null)
|
||||||
|
->setEmail(null)
|
||||||
|
->setEmailVerified(0)
|
||||||
|
->setProfileImagePHID(null)
|
||||||
|
->setAccountURI(null)
|
||||||
|
->setProperties(array())
|
||||||
|
->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setProperty($key, $value) {
|
public function setProperty($key, $value) {
|
||||||
|
@ -131,6 +173,44 @@ final class PhabricatorExternalAccount
|
||||||
return $this->assertAttached($this->providerConfig);
|
return $this->assertAttached($this->providerConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getAccountIdentifiers() {
|
||||||
|
$raw = $this->assertAttached($this->accountIdentifiers);
|
||||||
|
return array_values($raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function attachAccountIdentifiers(array $identifiers) {
|
||||||
|
assert_instances_of($identifiers, 'PhabricatorExternalAccountIdentifier');
|
||||||
|
$this->accountIdentifiers = mpull($identifiers, null, 'getIdentifierRaw');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function appendIdentifier(
|
||||||
|
PhabricatorExternalAccountIdentifier $identifier) {
|
||||||
|
|
||||||
|
$this->assertAttached($this->accountIdentifiers);
|
||||||
|
|
||||||
|
$map = $this->accountIdentifiers;
|
||||||
|
$raw = $identifier->getIdentifierRaw();
|
||||||
|
|
||||||
|
$old = idx($map, $raw);
|
||||||
|
$new = $identifier;
|
||||||
|
|
||||||
|
if ($old === null) {
|
||||||
|
$result = $new;
|
||||||
|
} else {
|
||||||
|
// Here, we already know about an identifier and have rediscovered it.
|
||||||
|
|
||||||
|
// We could copy properties from the new version of the identifier here,
|
||||||
|
// or merge them in some other way (for example, update a "last seen
|
||||||
|
// from the provider" timestamp), but no such properties currently exist.
|
||||||
|
$result = $old;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->accountIdentifiers[$raw] = $result;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
||||||
|
|
||||||
|
@ -182,6 +262,8 @@ final class PhabricatorExternalAccount
|
||||||
$engine->destroyObject($identifier);
|
$engine->destroyObject($identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This may leave a profile image behind.
|
||||||
|
|
||||||
$this->delete();
|
$this->delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,10 @@ final class PhabricatorExternalAccountIdentifier
|
||||||
|
|
||||||
public function save() {
|
public function save() {
|
||||||
$identifier_raw = $this->getIdentifierRaw();
|
$identifier_raw = $this->getIdentifierRaw();
|
||||||
$this->identiferHash = PhabricatorHash::digestForIndex($identifier_raw);
|
|
||||||
|
$identifier_hash = PhabricatorHash::digestForIndex($identifier_raw);
|
||||||
|
$this->setIdentifierHash($identifier_hash);
|
||||||
|
|
||||||
return parent::save();
|
return parent::save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue