Adding 'visible' field for SSO providers
This commit is contained in:
@@ -194,7 +194,7 @@ def auth_pipeline_urls(auth_entry, redirect_url=None):
|
||||
return {
|
||||
provider.provider_id: third_party_auth.pipeline.get_login_url(
|
||||
provider.provider_id, auth_entry, redirect_url=redirect_url
|
||||
) for provider in third_party_auth.provider.Registry.accepting_logins()
|
||||
) for provider in third_party_auth.provider.Registry.displayed_for_login()
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -54,8 +54,8 @@ class LoginFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, SharedModuleStoreTes
|
||||
self.url = reverse("signin_user")
|
||||
self.course_id = unicode(self.course.id)
|
||||
self.courseware_url = reverse("courseware", args=[self.course_id])
|
||||
self.configure_google_provider(enabled=True)
|
||||
self.configure_facebook_provider(enabled=True)
|
||||
self.configure_google_provider(enabled=True, visible=True)
|
||||
self.configure_facebook_provider(enabled=True, visible=True)
|
||||
|
||||
@patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
|
||||
@ddt.data(THIRD_PARTY_AUTH_PROVIDERS)
|
||||
@@ -170,8 +170,8 @@ class RegisterFormTest(ThirdPartyAuthTestMixin, UrlResetMixin, SharedModuleStore
|
||||
|
||||
self.url = reverse("register_user")
|
||||
self.course_id = unicode(self.course.id)
|
||||
self.configure_google_provider(enabled=True)
|
||||
self.configure_facebook_provider(enabled=True)
|
||||
self.configure_google_provider(enabled=True, visible=True)
|
||||
self.configure_facebook_provider(enabled=True, visible=True)
|
||||
|
||||
@patch.dict(settings.FEATURES, {"ENABLE_THIRD_PARTY_AUTH": False})
|
||||
@ddt.data(*THIRD_PARTY_AUTH_PROVIDERS)
|
||||
|
||||
@@ -51,7 +51,11 @@ class TpaAPITestCase(ThirdPartyAuthTestMixin, APITestCase):
|
||||
self.configure_facebook_provider(enabled=True)
|
||||
self.configure_linkedin_provider(enabled=False)
|
||||
self.enable_saml()
|
||||
testshib = self.configure_saml_provider(name='TestShib', enabled=True, idp_slug=IDP_SLUG_TESTSHIB)
|
||||
testshib = self.configure_saml_provider(
|
||||
name='TestShib',
|
||||
enabled=True,
|
||||
idp_slug=IDP_SLUG_TESTSHIB
|
||||
)
|
||||
|
||||
# Create several users and link each user to Google and TestShib
|
||||
for username in LINKED_USERS:
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('third_party_auth', '0001_initial'),
|
||||
('third_party_auth', '0002_schema__provider_icon_image'),
|
||||
('third_party_auth', '0003_samlproviderconfig_debug_mode'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='LTIProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=True
|
||||
),
|
||||
preserve_default=False
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='LTIProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=False
|
||||
)
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='OAuth2ProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=True
|
||||
),
|
||||
preserve_default=False
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='OAuth2ProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=False
|
||||
)
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='SAMLProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=True
|
||||
),
|
||||
preserve_default=False
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='SAMLProviderConfig',
|
||||
name='visible',
|
||||
field=models.BooleanField(
|
||||
help_text=b'If this option is not selected, users will not be presented with the provider as an option to authenticate with on the login screen, but manual authentication using the correct link is still possible.',
|
||||
default=False
|
||||
)
|
||||
),
|
||||
]
|
||||
@@ -121,6 +121,14 @@ class ProviderConfig(ConfigurationModel):
|
||||
"email, and their account will be activated immediately upon registration."
|
||||
),
|
||||
)
|
||||
visible = models.BooleanField(
|
||||
default=False,
|
||||
help_text=_(
|
||||
"If this option is not selected, users will not be presented with the provider "
|
||||
"as an option to authenticate with on the login screen, but manual "
|
||||
"authentication using the correct link is still possible."
|
||||
),
|
||||
)
|
||||
prefix = None # used for provider_id. Set to a string value in subclass
|
||||
backend_name = None # Set to a field or fixed value in subclass
|
||||
accepts_logins = True # Whether to display a sign-in button when the provider is enabled
|
||||
@@ -212,6 +220,14 @@ class ProviderConfig(ConfigurationModel):
|
||||
"""Gets associated Django settings.AUTHENTICATION_BACKEND string."""
|
||||
return '{}.{}'.format(self.backend_class.__module__, self.backend_class.__name__)
|
||||
|
||||
@property
|
||||
def display_for_login(self):
|
||||
"""
|
||||
Determines whether the provider ought to be shown as an option with
|
||||
which to authenticate on the login screen, registration screen, and elsewhere.
|
||||
"""
|
||||
return bool(self.enabled and self.accepts_logins and self.visible)
|
||||
|
||||
|
||||
class OAuth2ProviderConfig(ProviderConfig):
|
||||
"""
|
||||
|
||||
@@ -37,9 +37,9 @@ class Registry(object):
|
||||
return sorted(cls._enabled_providers(), key=lambda provider: provider.name)
|
||||
|
||||
@classmethod
|
||||
def accepting_logins(cls):
|
||||
"""Returns list of providers that can be used to initiate logins currently"""
|
||||
return [provider for provider in cls.enabled() if provider.accepts_logins]
|
||||
def displayed_for_login(cls):
|
||||
"""Returns list of providers that can be used to initiate logins in the UI"""
|
||||
return [provider for provider in cls.enabled() if provider.display_for_login]
|
||||
|
||||
@classmethod
|
||||
def get(cls, provider_id):
|
||||
|
||||
@@ -11,6 +11,7 @@ class AzureADOauth2IntegrationTest(base.Oauth2IntegrationTest):
|
||||
super(AzureADOauth2IntegrationTest, self).setUp()
|
||||
self.provider = self.configure_azure_ad_provider(
|
||||
enabled=True,
|
||||
visible=True,
|
||||
key='azure_ad_oauth2_key',
|
||||
secret='azure_ad_oauth2_secret',
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ class GenericIntegrationTest(IntegrationTestMixin, testutil.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(GenericIntegrationTest, self).setUp()
|
||||
self.configure_dummy_provider(enabled=True)
|
||||
self.configure_dummy_provider(enabled=True, visible=True)
|
||||
|
||||
def do_provider_login(self, provider_redirect_url):
|
||||
"""
|
||||
|
||||
@@ -19,6 +19,7 @@ class GoogleOauth2IntegrationTest(base.Oauth2IntegrationTest):
|
||||
super(GoogleOauth2IntegrationTest, self).setUp()
|
||||
self.provider = self.configure_google_provider(
|
||||
enabled=True,
|
||||
visible=True,
|
||||
key='google_oauth2_key',
|
||||
secret='google_oauth2_secret',
|
||||
)
|
||||
|
||||
@@ -10,6 +10,7 @@ class LinkedInOauth2IntegrationTest(base.Oauth2IntegrationTest):
|
||||
super(LinkedInOauth2IntegrationTest, self).setUp()
|
||||
self.provider = self.configure_linkedin_provider(
|
||||
enabled=True,
|
||||
visible=True,
|
||||
key='linkedin_oauth2_key',
|
||||
secret='linkedin_oauth2_secret',
|
||||
)
|
||||
|
||||
@@ -134,6 +134,7 @@ class TestShibIntegrationTest(IntegrationTestMixin, testutil.SAMLTestCase):
|
||||
fetch_metadata = kwargs.pop('fetch_metadata', True)
|
||||
kwargs.setdefault('name', self.PROVIDER_NAME)
|
||||
kwargs.setdefault('enabled', True)
|
||||
kwargs.setdefault('visible', True)
|
||||
kwargs.setdefault('idp_slug', self.PROVIDER_IDP_SLUG)
|
||||
kwargs.setdefault('entity_id', TESTSHIB_ENTITY_ID)
|
||||
kwargs.setdefault('metadata_source', TESTSHIB_METADATA_URL)
|
||||
|
||||
@@ -13,6 +13,7 @@ class TwitterIntegrationTest(base.Oauth2IntegrationTest):
|
||||
super(TwitterIntegrationTest, self).setUp()
|
||||
self.provider = self.configure_twitter_provider(
|
||||
enabled=True,
|
||||
visible=True,
|
||||
key='twitter_oauth1_key',
|
||||
secret='twitter_oauth1_secret',
|
||||
)
|
||||
|
||||
@@ -48,7 +48,12 @@ class RegistryTest(testutil.TestCase):
|
||||
""" Test that only backend_names listed in settings.AUTHENTICATION_BACKENDS can be used """
|
||||
self.configure_oauth_provider(enabled=True, name="Disallowed", backend_name="disallowed")
|
||||
self.enable_saml()
|
||||
self.configure_saml_provider(enabled=True, name="Disallowed", idp_slug="test", backend_name="disallowed")
|
||||
self.configure_saml_provider(
|
||||
enabled=True,
|
||||
name="Disallowed",
|
||||
idp_slug="test",
|
||||
backend_name="disallowed"
|
||||
)
|
||||
self.assertEqual(len(provider.Registry.enabled()), 0)
|
||||
|
||||
def test_enabled_returns_list_of_enabled_providers_sorted_by_name(self):
|
||||
@@ -62,6 +67,23 @@ class RegistryTest(testutil.TestCase):
|
||||
with patch('third_party_auth.provider._PSA_OAUTH2_BACKENDS', backend_names):
|
||||
self.assertEqual(sorted(provider_names), [prov.name for prov in provider.Registry.enabled()])
|
||||
|
||||
def test_providers_displayed_for_login(self):
|
||||
"""
|
||||
Tests to ensure that only providers that we can use to log in are presented
|
||||
for rendering in the UI.
|
||||
"""
|
||||
hidden_provider = self.configure_google_provider(visible=False, enabled=True)
|
||||
normal_provider = self.configure_facebook_provider(visible=True, enabled=True)
|
||||
implicitly_hidden_provider = self.configure_linkedin_provider(enabled=True)
|
||||
disabled_provider = self.configure_twitter_provider(visible=True, enabled=False)
|
||||
no_log_in_provider = self.configure_lti_provider()
|
||||
provider_ids = [idp.provider_id for idp in provider.Registry.displayed_for_login()]
|
||||
self.assertNotIn(hidden_provider.provider_id, provider_ids)
|
||||
self.assertNotIn(implicitly_hidden_provider.provider_id, provider_ids)
|
||||
self.assertNotIn(disabled_provider.provider_id, provider_ids)
|
||||
self.assertNotIn(no_log_in_provider.provider_id, provider_ids)
|
||||
self.assertIn(normal_provider.provider_id, provider_ids)
|
||||
|
||||
def test_get_returns_enabled_provider(self):
|
||||
google_provider = self.configure_google_provider(enabled=True)
|
||||
self.assertEqual(google_provider.id, provider.Registry.get(google_provider.provider_id).id)
|
||||
|
||||
@@ -35,9 +35,9 @@ class ThirdPartyOAuthTestMixin(ThirdPartyAuthTestMixin):
|
||||
UserSocialAuth.objects.create(user=self.user, provider=self.BACKEND, uid=self.social_uid)
|
||||
self.oauth_client = self._create_client()
|
||||
if self.BACKEND == 'google-oauth2':
|
||||
self.configure_google_provider(enabled=True)
|
||||
self.configure_google_provider(enabled=True, visible=True)
|
||||
elif self.BACKEND == 'facebook':
|
||||
self.configure_facebook_provider(enabled=True)
|
||||
self.configure_facebook_provider(enabled=True, visible=True)
|
||||
|
||||
def _create_client(self):
|
||||
"""
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
"backend_name": "google-oauth2",
|
||||
"key": "test",
|
||||
"secret": "test",
|
||||
"other_settings": "{}"
|
||||
"other_settings": "{}",
|
||||
"visible": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -28,7 +29,8 @@
|
||||
"backend_name": "facebook",
|
||||
"key": "test",
|
||||
"secret": "test",
|
||||
"other_settings": "{}"
|
||||
"other_settings": "{}",
|
||||
"visible": true
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -44,7 +46,8 @@
|
||||
"backend_name": "dummy",
|
||||
"key": "",
|
||||
"secret": "",
|
||||
"other_settings": "{}"
|
||||
"other_settings": "{}",
|
||||
"visible": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user