1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-22 14:52:41 +01:00

Update unusual handling of external accounts in "Password" auth provider

Summary:
Depends on D21013. Ref T13493. When users log in with most providers, the provider returns an "ExternalAccount" identifier (like an Asana account GUID) and the workflow figures out where to go from there, usually a decision to try to send the user to registration (if the external account isn't linked to anything yet) or login (if it is).

In the case of password providers, the password is really a property of an existing account, so sending the user to registration never makes sense. We can bypass the "external identifier" indirection layer and just say "username -> internal account" instead of "external GUID -> internal mapping -> internal account".

Formalize this so that "AuthProvider" can generate either a "map this external account" value or a "use this internal account" value.

This stops populating "accountID" on "password" "ExternalAccount" objects, but this was only an artifact of convenience. (These records don't really need to exist at all, but there's little harm in going down the same workflow as everything else for consistency.)

Test Plan: Logged in with a username/password. Wiped the external account table and repeated the process.

Maniphest Tasks: T13493

Differential Revision: https://secure.phabricator.com/D21014
This commit is contained in:
epriestley 2020-02-21 07:25:42 -08:00
parent e43ecad8af
commit 05eb16d6de
6 changed files with 45 additions and 19 deletions

View file

@ -457,7 +457,6 @@ final class PhabricatorAuthRegisterController
if (!$is_setup) {
$account->setUserPHID($user->getPHID());
$provider->willRegisterAccount($account);
$account->save();
}

View file

@ -186,11 +186,9 @@ abstract class PhabricatorAuthProvider extends Phobject {
return;
}
public function willRegisterAccount(PhabricatorExternalAccount $account) {
return;
}
final protected function newExternalAccountForIdentifiers(
array $identifiers) {
protected function loadOrCreateAccount(array $identifiers) {
assert_instances_of($identifiers, 'PhabricatorExternalAccountIdentifier');
if (!$identifiers) {
@ -234,6 +232,38 @@ abstract class PhabricatorAuthProvider extends Phobject {
implode(', ', $raw_identifiers)));
}
return $this->didUpdateAccount($account);
}
final protected function newExternalAccountForUser(PhabricatorUser $user) {
$config = $this->getProviderConfig();
// When a user logs in with a provider like username/password, they
// always already have a Phabricator account (since there's no way they
// could have a username otherwise).
// These users should never go to registration, so we're building a
// dummy "external account" which just links directly back to their
// internal account.
$account = id(new PhabricatorExternalAccountQuery())
->setViewer($user)
->withProviderConfigPHIDs(array($config->getPHID()))
->withUserPHIDs(array($user->getPHID()))
->executeOne();
if (!$account) {
$account = $this->newExternalAccount()
->setUserPHID($user->getPHID());
// TODO: Remove this when "accountID" is removed; the column is not
// nullable.
$account->setAccountID('');
}
return $this->didUpdateAccount($account);
}
private function didUpdateAccount(PhabricatorExternalAccount $account) {
$adapter = $this->getAdapter();
$account->setUsername($adapter->getAccountName());

View file

@ -180,7 +180,9 @@ final class PhabricatorLDAPAuthProvider extends PhabricatorAuthProvider {
}
}
return array($this->loadOrCreateAccount($identifiers), $response);
$account = $this->newExternalAccountForIdentifiers($identifiers);
return array($account, $response);
}

View file

@ -115,7 +115,9 @@ abstract class PhabricatorOAuth1AuthProvider
return array($account, $response);
}
return array($this->loadOrCreateAccount($identifiers), $response);
$account = $this->newExternalAccountForIdentifiers($identifiers);
return array($account, $response);
}
public function processEditForm(

View file

@ -95,7 +95,9 @@ abstract class PhabricatorOAuth2AuthProvider
return array($account, $response);
}
return array($this->loadOrCreateAccount($identifiers), $response);
$account = $this->newExternalAccountForIdentifiers($identifiers);
return array($account, $response);
}
public function processEditForm(

View file

@ -305,7 +305,7 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
->setObject($user);
if ($engine->isValidPassword($envelope)) {
$account = $this->loadOrCreateAccount($user->getPHID());
$account = $this->newExternalAccountForUser($user);
$log_user = $user;
}
}
@ -339,16 +339,6 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
return true;
}
protected function willSaveAccount(PhabricatorExternalAccount $account) {
parent::willSaveAccount($account);
$account->setUserPHID($account->getAccountID());
}
public function willRegisterAccount(PhabricatorExternalAccount $account) {
parent::willRegisterAccount($account);
$account->setAccountID($account->getUserPHID());
}
public static function getPasswordProvider() {
$providers = self::getAllEnabledProviders();
@ -375,4 +365,5 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
public function shouldAllowEmailTrustConfiguration() {
return false;
}
}