1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-18 09:48:39 +01:00

Prepare for db-driven auth configuration by making proviers operate in dual modes

Summary:
Ref T1536. This sets us for the "Config -> Database" migration. Basically:

  - If stuff is defined in the database, respect the database stuff (no installs have anything defined yet since they can't reach the interfaces/code).
  - Otherwise, respect the config stuff (all installs currently do this).

Test Plan: Saw database stuff respected when database stuff was defined; saw config stuff respected otherwise.

Reviewers: chad, btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T1536

Differential Revision: https://secure.phabricator.com/D6240
This commit is contained in:
epriestley 2013-06-20 11:17:53 -07:00
parent 269ad21867
commit d8394b2ee0
9 changed files with 186 additions and 95 deletions

View file

@ -60,12 +60,8 @@ final class PhabricatorAuthEditController
throw new Exception("This provider is already configured!"); throw new Exception("This provider is already configured!");
} }
$config = id(new PhabricatorAuthProviderConfig()) $config = $provider->getDefaultProviderConfig();
->setProviderClass(get_class($provider)) $provider->attachProviderConfig($config);
->setShouldAllowLogin(1)
->setShouldAllowRegistration(1)
->setShouldAllowLink(1)
->setShouldAllowUnlink(1);
$is_new = true; $is_new = true;
} }
@ -87,11 +83,6 @@ final class PhabricatorAuthEditController
if (!$errors) { if (!$errors) {
if ($is_new) { if ($is_new) {
$xactions[] = id(new PhabricatorAuthProviderConfigTransaction())
->setTransactionType(
PhabricatorAuthProviderConfigTransaction::TYPE_ENABLE)
->setNewValue(1);
$config->setProviderType($provider->getProviderType()); $config->setProviderType($provider->getProviderType());
$config->setProviderDomain($provider->getProviderDomain()); $config->setProviderDomain($provider->getProviderDomain());
} }
@ -177,7 +168,11 @@ final class PhabricatorAuthEditController
$status_tag = id(new PhabricatorTagView()) $status_tag = id(new PhabricatorTagView())
->setType(PhabricatorTagView::TYPE_STATE); ->setType(PhabricatorTagView::TYPE_STATE);
if ($config->getIsEnabled()) { if ($is_new) {
$status_tag
->setName(pht('New Provider'))
->setBackgroundColor('blue');
} else if ($config->getIsEnabled()) {
$status_tag $status_tag
->setName(pht('Enabled')) ->setName(pht('Enabled'))
->setBackgroundColor('green'); ->setBackgroundColor('green');

View file

@ -9,12 +9,26 @@ abstract class PhabricatorAuthProvider {
return $this; return $this;
} }
public function hasProviderConfig() {
return (bool)$this->providerConfig;
}
public function getProviderConfig() { public function getProviderConfig() {
if ($this->config === null) { if ($this->providerConfig === null) {
throw new Exception( throw new Exception(
"Call attachProviderConfig() before getProviderConfig()!"); "Call attachProviderConfig() before getProviderConfig()!");
} }
return $this->config; return $this->providerConfig;
}
public function getDefaultProviderConfig() {
return id(new PhabricatorAuthProviderConfig())
->setProviderClass(get_class($this))
->setIsEnabled(1)
->setShouldAllowLogin(1)
->setShouldAllowRegistration(1)
->setShouldAllowLink(1)
->setShouldAllowUnlink(1);
} }
public function getNameForCreate() { public function getNameForCreate() {
@ -56,23 +70,52 @@ abstract class PhabricatorAuthProvider {
if ($providers === null) { if ($providers === null) {
$objects = self::getAllBaseProviders(); $objects = self::getAllBaseProviders();
$configs = id(new PhabricatorAuthProviderConfigQuery())
->setViewer(PhabricatorUser::getOmnipotentUser())
->execute();
$providers = array(); $providers = array();
$from_class_map = array(); if ($configs) {
foreach ($objects as $object) { foreach ($configs as $config) {
$from_class = get_class($object); if (!isset($objects[$config->getProviderClass()])) {
$object_providers = $object->createProviders(); // This configuration is for a provider which is not installed.
assert_instances_of($object_providers, 'PhabricatorAuthProvider'); continue;
foreach ($object_providers as $provider) { }
$key = $provider->getProviderKey();
if (isset($providers[$key])) { $object = clone $objects[$config->getProviderClass()];
$first_class = $from_class_map[$key]; $object->attachProviderConfig($config);
throw new Exception(
"PhabricatorAuthProviders '{$first_class}' and '{$from_class}' ". $key = $object->getProviderKey();
"both created authentication providers identified by key ". if (isset($providers[$key])) {
"'{$key}'. Provider keys must be unique."); throw new Exception(
pht(
"Two authentication providers use the same provider key ".
"('%s'). Each provider must be identified by a unique ".
"key.",
$key));
}
$providers[$key] = $object;
}
} else {
// TODO: Remove this once we transition to be completely database
// driven.
$from_class_map = array();
foreach ($objects as $object) {
$from_class = get_class($object);
$object_providers = $object->createProviders();
assert_instances_of($object_providers, 'PhabricatorAuthProvider');
foreach ($object_providers as $provider) {
$key = $provider->getProviderKey();
if (isset($providers[$key])) {
$first_class = $from_class_map[$key];
throw new Exception(
"PhabricatorAuthProviders '{$first_class}' and ".
"'{$from_class}' both created authentication providers ".
"identified by key '{$key}'. Provider keys must be unique.");
}
$providers[$key] = $provider;
$from_class_map[$key] = $from_class;
} }
$providers[$key] = $provider;
$from_class_map[$key] = $from_class;
} }
} }
} }
@ -98,13 +141,39 @@ abstract class PhabricatorAuthProvider {
abstract public function getAdapter(); abstract public function getAdapter();
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return $this->getProviderConfig()->getIsEnabled();
}
return true; return true;
} }
abstract public function shouldAllowLogin(); public function shouldAllowLogin() {
abstract public function shouldAllowRegistration(); if ($this->hasProviderConfig()) {
abstract public function shouldAllowAccountLink(); return $this->getProviderConfig()->getShouldAllowLogin();
abstract public function shouldAllowAccountUnlink(); }
return true;
}
public function shouldAllowRegistration() {
if ($this->hasProviderConfig()) {
return $this->getProviderConfig()->getShouldAllowRegistration();
}
return true;
}
public function shouldAllowAccountLink() {
if ($this->hasProviderConfig()) {
return $this->getProviderConfig()->getShouldAllowLink();
}
return true;
}
public function shouldAllowAccountUnlink() {
if ($this->hasProviderConfig()) {
return $this->getProviderConfig()->getShouldAllowUnlink();
}
return true;
}
public function buildLoginForm( public function buildLoginForm(
PhabricatorAuthStartController $controller) { PhabricatorAuthStartController $controller) {

View file

@ -15,8 +15,17 @@ final class PhabricatorAuthProviderLDAP
'LDAP credentials to log in to Phabricator.'); 'LDAP credentials to log in to Phabricator.');
} }
public function getDefaultProviderConfig() {
return parent::getDefaultProviderConfig()
->setProperty(self::KEY_PORT, 389)
->setProperty(self::KEY_VERSION, 3);
}
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('ldap.auth-enabled'); PhabricatorEnv::getEnvConfig('ldap.auth-enabled');
} }
@ -49,22 +58,6 @@ final class PhabricatorAuthProviderLDAP
return $this->adapter; return $this->adapter;
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() {
return true;
}
public function shouldAllowAccountLink() {
return true;
}
public function shouldAllowAccountUnlink() {
return true;
}
protected function renderLoginForm(AphrontRequest $request, $mode) { protected function renderLoginForm(AphrontRequest $request, $mode) {
$viewer = $request->getUser(); $viewer = $request->getUser();

View file

@ -22,18 +22,31 @@ abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
$this->getOAuthClientID() && $this->getOAuthClientID() &&
$this->getOAuthClientSecret(); $this->getOAuthClientSecret();
} }
protected function configureAdapter(PhutilAuthAdapterOAuth $adapter) { protected function configureAdapter(PhutilAuthAdapterOAuth $adapter) {
if ($this->getOAuthClientID()) {
$adapter->setClientID($this->getOAuthClientID());
}
if ($this->getOAuthClientSecret()) { if ($this->hasProviderConfig()) {
$adapter->setClientSecret($this->getOAuthClientSecret()); $config = $this->getProviderConfig();
$adapter->setClientID($config->getProperty(self::PROPERTY_APP_ID));
$adapter->setClientSecret(
new PhutilOpaqueEnvelope(
$config->getProperty(self::PROPERTY_APP_SECRET)));
} else {
if ($this->getOAuthClientID()) {
$adapter->setClientID($this->getOAuthClientID());
}
if ($this->getOAuthClientSecret()) {
$adapter->setClientSecret($this->getOAuthClientSecret());
}
} }
$adapter->setRedirectURI($this->getLoginURI()); $adapter->setRedirectURI($this->getLoginURI());
@ -174,13 +187,21 @@ abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
const PROPERTY_APP_SECRET = 'oauth:app:secret'; const PROPERTY_APP_SECRET = 'oauth:app:secret';
public function readFormValuesFromProvider() { public function readFormValuesFromProvider() {
$secret = $this->getOAuthClientSecret();
if ($secret) { if ($this->hasProviderConfig()) {
$secret = $secret->openEnvelope(); $config = $this->getProviderConfig();
$id = $config->getProperty(self::PROPERTY_APP_ID);
$secret = $config->getProperty(self::PROPERTY_APP_SECRET);
} else {
$id = $this->getOAuthClientID();
$secret = $this->getOAuthClientSecret();
if ($secret) {
$secret = $secret->openEnvelope();
}
} }
return array( return array(
self::PROPERTY_APP_ID => $this->getOAuthClientID(), self::PROPERTY_APP_ID => $id,
self::PROPERTY_APP_SECRET => $secret, self::PROPERTY_APP_SECRET => $secret,
); );
} }
@ -208,7 +229,7 @@ abstract class PhabricatorAuthProviderOAuth extends PhabricatorAuthProvider {
if (!strlen($values[$key_secret])) { if (!strlen($values[$key_secret])) {
$errors[] = pht('Application secret is required.'); $errors[] = pht('Application secret is required.');
$issues[$key_id] = pht('Required'); $issues[$key_secret] = pht('Required');
} }
// If the user has not changed the secret, don't update it (that is, // If the user has not changed the secret, don't update it (that is,

View file

@ -16,6 +16,10 @@ final class PhabricatorAuthProviderOAuthDisqus
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('disqus.auth-enabled'); PhabricatorEnv::getEnvConfig('disqus.auth-enabled');
} }
@ -32,19 +36,18 @@ final class PhabricatorAuthProviderOAuthDisqus
return null; return null;
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() { public function shouldAllowRegistration() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowRegistration();
}
return PhabricatorEnv::getEnvConfig('disqus.registration-enabled'); return PhabricatorEnv::getEnvConfig('disqus.registration-enabled');
} }
public function shouldAllowAccountLink() {
return true;
}
public function shouldAllowAccountUnlink() { public function shouldAllowAccountUnlink() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowAccountUnlink();
}
return !PhabricatorEnv::getEnvConfig('disqus.auth-permanent'); return !PhabricatorEnv::getEnvConfig('disqus.auth-permanent');
} }

View file

@ -9,6 +9,11 @@ final class PhabricatorAuthProviderOAuthFacebook
return pht('Facebook'); return pht('Facebook');
} }
public function getDefaultProviderConfig() {
return parent::getDefaultProviderConfig()
->setProperty(self::KEY_REQUIRE_SECURE, 1);
}
protected function newOAuthAdapter() { protected function newOAuthAdapter() {
$secure_only = PhabricatorEnv::getEnvConfig('facebook.require-https-auth'); $secure_only = PhabricatorEnv::getEnvConfig('facebook.require-https-auth');
return id(new PhutilAuthAdapterOAuthFacebook()) return id(new PhutilAuthAdapterOAuthFacebook())
@ -20,6 +25,10 @@ final class PhabricatorAuthProviderOAuthFacebook
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('facebook.auth-enabled'); PhabricatorEnv::getEnvConfig('facebook.auth-enabled');
} }
@ -36,19 +45,17 @@ final class PhabricatorAuthProviderOAuthFacebook
return null; return null;
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() { public function shouldAllowRegistration() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowRegistration();
}
return PhabricatorEnv::getEnvConfig('facebook.registration-enabled'); return PhabricatorEnv::getEnvConfig('facebook.registration-enabled');
} }
public function shouldAllowAccountLink() {
return true;
}
public function shouldAllowAccountUnlink() { public function shouldAllowAccountUnlink() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowAccountUnlink();
}
return !PhabricatorEnv::getEnvConfig('facebook.auth-permanent'); return !PhabricatorEnv::getEnvConfig('facebook.auth-permanent');
} }

View file

@ -16,6 +16,10 @@ final class PhabricatorAuthProviderOAuthGitHub
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('github.auth-enabled'); PhabricatorEnv::getEnvConfig('github.auth-enabled');
} }
@ -32,19 +36,17 @@ final class PhabricatorAuthProviderOAuthGitHub
return null; return null;
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() { public function shouldAllowRegistration() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowRegistration();
}
return PhabricatorEnv::getEnvConfig('github.registration-enabled'); return PhabricatorEnv::getEnvConfig('github.registration-enabled');
} }
public function shouldAllowAccountLink() {
return true;
}
public function shouldAllowAccountUnlink() { public function shouldAllowAccountUnlink() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowAccountUnlink();
}
return !PhabricatorEnv::getEnvConfig('github.auth-permanent'); return !PhabricatorEnv::getEnvConfig('github.auth-permanent');
} }

View file

@ -16,6 +16,9 @@ final class PhabricatorAuthProviderOAuthGoogle
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('google.auth-enabled'); PhabricatorEnv::getEnvConfig('google.auth-enabled');
} }
@ -32,19 +35,17 @@ final class PhabricatorAuthProviderOAuthGoogle
return null; return null;
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() { public function shouldAllowRegistration() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowRegistration();
}
return PhabricatorEnv::getEnvConfig('google.registration-enabled'); return PhabricatorEnv::getEnvConfig('google.registration-enabled');
} }
public function shouldAllowAccountLink() {
return true;
}
public function shouldAllowAccountUnlink() { public function shouldAllowAccountUnlink() {
if ($this->hasProviderConfig()) {
return parent::shouldAllowAccountUnlink();
}
return !PhabricatorEnv::getEnvConfig('google.auth-permanent'); return !PhabricatorEnv::getEnvConfig('google.auth-permanent');
} }

View file

@ -15,6 +15,10 @@ final class PhabricatorAuthProviderPassword
} }
public function isEnabled() { public function isEnabled() {
if ($this->hasProviderConfig()) {
return parent::isEnabled();
}
return parent::isEnabled() && return parent::isEnabled() &&
PhabricatorEnv::getEnvConfig('auth.password-auth-enabled'); PhabricatorEnv::getEnvConfig('auth.password-auth-enabled');
} }
@ -34,10 +38,6 @@ final class PhabricatorAuthProviderPassword
return '100-'.$this->getProviderName(); return '100-'.$this->getProviderName();
} }
public function shouldAllowLogin() {
return true;
}
public function shouldAllowRegistration() { public function shouldAllowRegistration() {
// TODO: Hard code this as "false" for now so we don't inadvertantly open // TODO: Hard code this as "false" for now so we don't inadvertantly open
// up password registration where it did not previously exist. // up password registration where it did not previously exist.