From 350f98ebdec44ca54513afc010e50eb6b3ebda37 Mon Sep 17 00:00:00 2001 From: Braden MacDonald <braden@opencraft.com> Date: Wed, 6 May 2015 11:16:36 -0700 Subject: [PATCH] Changes for compatibility with latest python-social-auth (0.2.7) --- common/djangoapps/auth_exchange/forms.py | 5 +++-- common/djangoapps/auth_exchange/tests/test_forms.py | 5 ++++- common/djangoapps/student/views.py | 11 +++++++---- common/djangoapps/third_party_auth/pipeline.py | 9 +++++---- common/djangoapps/third_party_auth/provider.py | 36 ++++++------------------------------ common/djangoapps/third_party_auth/tests/specs/base.py | 93 +++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------- common/djangoapps/third_party_auth/tests/test_change_enrollment.py | 6 +++--- common/djangoapps/third_party_auth/tests/utils.py | 4 ++-- common/test/db_cache/bok_choy_schema.sql | 53 ----------------------------------------------------- common/test/db_cache/lettuce.db | Bin 653312 -> 0 bytes lms/envs/test.py | 4 ++-- requirements/edx/base.txt | 2 +- 12 files changed, 82 insertions(+), 146 deletions(-) diff --git a/common/djangoapps/auth_exchange/forms.py b/common/djangoapps/auth_exchange/forms.py index 2391486..7311948 100644 --- a/common/djangoapps/auth_exchange/forms.py +++ b/common/djangoapps/auth_exchange/forms.py @@ -10,6 +10,7 @@ from provider.oauth2.forms import ScopeChoiceField, ScopeMixin from provider.oauth2.models import Client from requests import HTTPError from social.backends import oauth as social_oauth +from social.exceptions import AuthException from third_party_auth import pipeline @@ -54,7 +55,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm): if self._errors: return {} - backend = self.request.social_strategy.backend + backend = self.request.backend if not isinstance(backend, social_oauth.BaseOAuth2): raise OAuthValidationError( { @@ -89,7 +90,7 @@ class AccessTokenExchangeForm(ScopeMixin, OAuthForm): user = None try: user = backend.do_auth(self.cleaned_data.get("access_token")) - except HTTPError: + except (HTTPError, AuthException): pass if user and isinstance(user, User): self.cleaned_data["user"] = user diff --git a/common/djangoapps/auth_exchange/tests/test_forms.py b/common/djangoapps/auth_exchange/tests/test_forms.py index c89fec9..ffeffb4 100644 --- a/common/djangoapps/auth_exchange/tests/test_forms.py +++ b/common/djangoapps/auth_exchange/tests/test_forms.py @@ -24,8 +24,11 @@ class AccessTokenExchangeFormTest(AccessTokenExchangeTestMixin): def setUp(self): super(AccessTokenExchangeFormTest, self).setUp() self.request = RequestFactory().post("dummy_url") + redirect_uri = 'dummy_redirect_url' SessionMiddleware().process_request(self.request) - self.request.social_strategy = social_utils.load_strategy(self.request, self.BACKEND) + self.request.social_strategy = social_utils.load_strategy(self.request) + # pylint: disable=no-member + self.request.backend = social_utils.load_backend(self.request.social_strategy, self.BACKEND, redirect_uri) def _assert_error(self, data, expected_error, expected_error_description): form = AccessTokenExchangeForm(request=self.request, data=data) diff --git a/common/djangoapps/student/views.py b/common/djangoapps/student/views.py index 2e863bc..14528e5 100644 --- a/common/djangoapps/student/views.py +++ b/common/djangoapps/student/views.py @@ -1129,7 +1129,7 @@ def login_oauth_token(request, backend): """ warnings.warn("Please use AccessTokenExchangeView instead.", DeprecationWarning) - backend = request.social_strategy.backend + backend = request.backend if isinstance(backend, social_oauth.BaseOAuth1) or isinstance(backend, social_oauth.BaseOAuth2): if "access_token" in request.POST: # Tell third party auth pipeline that this is an API call @@ -1137,7 +1137,7 @@ def login_oauth_token(request, backend): user = None try: user = backend.do_auth(request.POST["access_token"]) - except HTTPError: + except (HTTPError, AuthException): pass # do_auth can return a non-User object if it fails if user and isinstance(user, User): @@ -1447,7 +1447,10 @@ def create_account_with_params(request, params): # next, link the account with social auth, if provided if should_link_with_social_auth: - request.social_strategy = social_utils.load_strategy(backend=params['provider'], request=request) + backend_name = params['provider'] + request.social_strategy = social_utils.load_strategy(request) + redirect_uri = reverse('social:complete', args=(backend_name, )) + request.backend = social_utils.load_backend(request.social_strategy, backend_name, redirect_uri) social_access_token = params.get('access_token') if not social_access_token: raise ValidationError({ @@ -1461,7 +1464,7 @@ def create_account_with_params(request, params): pipeline_user = None error_message = "" try: - pipeline_user = request.social_strategy.backend.do_auth(social_access_token, user=user) + pipeline_user = request.backend.do_auth(social_access_token, user=user) except AuthAlreadyAssociated: error_message = _("The provided access_token is already associated with another user.") except (HTTPError, AuthException): diff --git a/common/djangoapps/third_party_auth/pipeline.py b/common/djangoapps/third_party_auth/pipeline.py index 2ff7ea6..d13d52a 100644 --- a/common/djangoapps/third_party_auth/pipeline.py +++ b/common/djangoapps/third_party_auth/pipeline.py @@ -445,7 +445,7 @@ def parse_query_params(strategy, response, *args, **kwargs): """Reads whitelisted query params, transforms them into pipeline args.""" auth_entry = strategy.session.get(AUTH_ENTRY_KEY) if not (auth_entry and auth_entry in _AUTH_ENTRY_CHOICES): - raise AuthEntryError(strategy.backend, 'auth_entry missing or invalid') + raise AuthEntryError(strategy.request.backend, 'auth_entry missing or invalid') return {'auth_entry': auth_entry} @@ -526,7 +526,7 @@ def _create_redirect_url(url, strategy): @partial.partial -def set_logged_in_cookie(backend=None, user=None, request=None, auth_entry=None, *args, **kwargs): +def set_logged_in_cookie(backend=None, user=None, strategy=None, auth_entry=None, *args, **kwargs): """This pipeline step sets the "logged in" cookie for authenticated users. Some installations have a marketing site front-end separate from @@ -552,6 +552,7 @@ def set_logged_in_cookie(backend=None, user=None, request=None, auth_entry=None, """ if not is_api(auth_entry) and user is not None and user.is_authenticated(): + request = strategy.request if strategy else None if request is not None: # Check that the cookie isn't already set. # This ensures that we allow the user to continue to the next @@ -692,7 +693,7 @@ def change_enrollment(strategy, auth_entry=None, user=None, *args, **kwargs): @partial.partial -def associate_by_email_if_login_api(auth_entry, strategy, details, user, *args, **kwargs): +def associate_by_email_if_login_api(auth_entry, backend, details, user, *args, **kwargs): """ This pipeline step associates the current social auth with the user with the same email address in the database. It defers to the social library's associate_by_email @@ -701,7 +702,7 @@ def associate_by_email_if_login_api(auth_entry, strategy, details, user, *args, This association is done ONLY if the user entered the pipeline through a LOGIN API. """ if auth_entry == AUTH_ENTRY_LOGIN_API: - association_response = associate_by_email(strategy, details, user, *args, **kwargs) + association_response = associate_by_email(backend, details, user, *args, **kwargs) if ( association_response and association_response.get('user') and diff --git a/common/djangoapps/third_party_auth/provider.py b/common/djangoapps/third_party_auth/provider.py index 4fc1de6..9f0809d 100644 --- a/common/djangoapps/third_party_auth/provider.py +++ b/common/djangoapps/third_party_auth/provider.py @@ -36,7 +36,7 @@ class BaseProvider(object): return '%s.%s' % (cls.BACKEND_CLASS.__module__, cls.BACKEND_CLASS.__name__) @classmethod - def get_email(cls, unused_provider_details): + def get_email(cls, provider_details): """Gets user's email address. Provider responses can contain arbitrary data. This method can be @@ -44,16 +44,16 @@ class BaseProvider(object): extracted by the social_details pipeline step. Args: - unused_provider_details: dict of string -> string. Data about the + provider_details: dict of string -> string. Data about the user passed back by the provider. Returns: String or None. The user's email address, if any. """ - return None + return provider_details.get('email') @classmethod - def get_name(cls, unused_provider_details): + def get_name(cls, provider_details): """Gets user's name. Provider responses can contain arbitrary data. This method can be @@ -61,13 +61,13 @@ class BaseProvider(object): extracted by the social_details pipeline step. Args: - unused_provider_details: dict of string -> string. Data about the + provider_details: dict of string -> string. Data about the user passed back by the provider. Returns: String or None. The user's full name, if any. """ - return None + return provider_details.get('fullname') @classmethod def get_register_form_data(cls, pipeline_kwargs): @@ -121,14 +121,6 @@ class GoogleOauth2(BaseProvider): 'SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET': None, } - @classmethod - def get_email(cls, provider_details): - return provider_details.get('email') - - @classmethod - def get_name(cls, provider_details): - return provider_details.get('fullname') - class LinkedInOauth2(BaseProvider): """Provider for LinkedIn's Oauth2 auth system.""" @@ -141,14 +133,6 @@ class LinkedInOauth2(BaseProvider): 'SOCIAL_AUTH_LINKEDIN_OAUTH2_SECRET': None, } - @classmethod - def get_email(cls, provider_details): - return provider_details.get('email') - - @classmethod - def get_name(cls, provider_details): - return provider_details.get('fullname') - class FacebookOauth2(BaseProvider): """Provider for LinkedIn's Oauth2 auth system.""" @@ -161,14 +145,6 @@ class FacebookOauth2(BaseProvider): 'SOCIAL_AUTH_FACEBOOK_SECRET': None, } - @classmethod - def get_email(cls, provider_details): - return provider_details.get('email') - - @classmethod - def get_name(cls, provider_details): - return provider_details.get('fullname') - class Registry(object): """Singleton registry of third-party auth providers. diff --git a/common/djangoapps/third_party_auth/tests/specs/base.py b/common/djangoapps/third_party_auth/tests/specs/base.py index 902a1be..b188e8f 100644 --- a/common/djangoapps/third_party_auth/tests/specs/base.py +++ b/common/djangoapps/third_party_auth/tests/specs/base.py @@ -140,7 +140,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): exception_middleware = middleware.ExceptionMiddleware() request, _ = self.get_request_and_strategy(auth_entry=auth_entry) response = exception_middleware.process_exception( - request, exceptions.AuthCanceled(request.social_strategy.backend)) + request, exceptions.AuthCanceled(request.backend)) location = response.get('Location') self.assertEqual(302, response.status_code) @@ -161,7 +161,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): """ _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) self.create_user_models_for_existing_account( strategy, email, password, self.get_username(), skip_social_auth=True) @@ -239,7 +239,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): def assert_redirect_to_dashboard_looks_correct(self, response): """Asserts a response would redirect to /dashboard.""" self.assertEqual(302, response.status_code) - # pylint: disable-msg=protected-access + # pylint: disable=protected-access self.assertEqual(auth_settings._SOCIAL_AUTH_LOGIN_REDIRECT_URL, response.get('Location')) def assert_redirect_to_login_looks_correct(self, response): @@ -287,7 +287,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): See student.views.register and student.views._do_create_account. """ response_data = self.get_response_data() - uid = strategy.backend.get_user_id(response_data, response_data) + uid = strategy.request.backend.get_user_id(response_data, response_data) user = social_utils.Storage.user.create_user(email=email, password=password, username=username) profile = student_models.UserProfile(user=user) profile.save() @@ -310,7 +310,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): args = () kwargs = { 'request': strategy.request, - 'backend': strategy.backend, + 'backend': strategy.request.backend, 'user': None, 'response': self.get_response_data(), } @@ -355,8 +355,9 @@ class IntegrationTest(testutil.TestCase, test.TestCase): if auth_entry: request.session[pipeline.AUTH_ENTRY_KEY] = auth_entry - strategy = social_utils.load_strategy(backend=self.backend_name, redirect_uri=redirect_uri, request=request) + strategy = social_utils.load_strategy(request=request) request.social_strategy = strategy + request.backend = social_utils.load_backend(strategy, self.backend_name, redirect_uri) return request, strategy @@ -404,7 +405,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() request.user = self.create_user_models_for_existing_account( strategy, 'user@example.com', 'password', self.get_username(), skip_social_auth=True) @@ -413,12 +414,12 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # expected state. self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) - actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) - actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access # First we expect that we're in the unlinked state, and that there # really is no association in the backend. @@ -428,7 +429,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( - request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access + request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME )) @@ -437,7 +438,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Fire off the auth pipeline to link. self.assert_redirect_to_dashboard_looks_correct(actions.do_complete( - request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access + request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Now we expect to be in the linked state, with a backend entry. @@ -449,7 +450,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, 'user@example.com', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) @@ -461,12 +462,12 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # expected state. self.client.get( pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) - actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) - actions.do_complete(strategy, social_views._do_login, user=user) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login, user=user) # pylint: disable=protected-access # First we expect that we're in the linked state, with a backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), user, linked=True) @@ -474,7 +475,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Fire off the disconnect pipeline to unlink. self.assert_redirect_to_dashboard_looks_correct(actions.do_disconnect( - request.social_strategy, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME)) + request.backend, request.user, None, redirect_field_name=auth.REDIRECT_FIELD_NAME)) # Now we expect to be in the unlinked state, with no backend entry. self.assert_account_settings_context_looks_correct(account_settings_context(request), user, linked=False) @@ -490,7 +491,8 @@ class IntegrationTest(testutil.TestCase, test.TestCase): username = self.get_username() _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + backend = strategy.request.backend + backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) linked_user = self.create_user_models_for_existing_account(strategy, email, password, username) unlinked_user = social_utils.Storage.user.create_user( email='other_' + email, password=password, username='other_' + username) @@ -499,7 +501,8 @@ class IntegrationTest(testutil.TestCase, test.TestCase): self.assert_social_auth_does_not_exist_for_user(unlinked_user, strategy) with self.assertRaises(exceptions.AuthAlreadyAssociated): - actions.do_complete(strategy, social_views._do_login, user=unlinked_user) # pylint: disable-msg=protected-access + # pylint: disable=protected-access + actions.do_complete(backend, social_views._do_login, user=unlinked_user) def test_already_associated_exception_populates_dashboard_with_error(self): # Instrument the pipeline with an exception. We test that the @@ -511,21 +514,21 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # that the duplicate error has no effect on the state of the controls. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account( strategy, 'user@example.com', 'password', self.get_username()) self.assert_social_auth_exists_for_user(user, strategy) self.client.get('/login') self.client.get(pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN)) - actions.do_complete(strategy, social_views._do_login) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login) # pylint: disable=protected-access mako_middleware_process_request(strategy.request) student_views.signin_user(strategy.request) student_views.login_user(strategy.request) - actions.do_complete(strategy, social_views._do_login, user=user) # pylint: disable-msg=protected-access + actions.do_complete(request.backend, social_views._do_login, user=user) # pylint: disable=protected-access - # Monkey-patch storage for messaging; pylint: disable-msg=protected-access + # Monkey-patch storage for messaging; pylint: disable=protected-access request._messages = fallback.FallbackStorage(request) middleware.ExceptionMiddleware().process_exception( request, @@ -539,7 +542,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # configure the backend, and mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) pipeline.analytics.track = mock.MagicMock() user = self.create_user_models_for_existing_account( strategy, 'user@example.com', 'password', self.get_username()) @@ -558,8 +561,8 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Next, the provider makes a request against /auth/complete/<provider> # to resume the pipeline. - # pylint: disable-msg=protected-access - self.assert_redirect_to_login_looks_correct(actions.do_complete(strategy, social_views._do_login)) + # pylint: disable=protected-access + self.assert_redirect_to_login_looks_correct(actions.do_complete(request.backend, social_views._do_login)) mako_middleware_process_request(strategy.request) # At this point we know the pipeline has resumed correctly. Next we @@ -574,7 +577,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # We should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( - request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access + request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME )) @@ -582,13 +585,13 @@ class IntegrationTest(testutil.TestCase, test.TestCase): self.set_logged_in_cookie(request) self.assert_redirect_to_dashboard_looks_correct( - actions.do_complete(strategy, social_views._do_login, user=user)) + actions.do_complete(request.backend, social_views._do_login, user=user)) self.assert_account_settings_context_looks_correct(account_settings_context(request), user) def test_signin_fails_if_account_not_active(self): _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) user = self.create_user_models_for_existing_account(strategy, 'user@example.com', 'password', self.get_username()) user.is_active = False @@ -600,7 +603,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): def test_signin_fails_if_no_account_associated(self): _, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_LOGIN, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) self.create_user_models_for_existing_account( strategy, 'user@example.com', 'password', self.get_username(), skip_social_auth=True) @@ -625,7 +628,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Mock out wire traffic. request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) # Begin! Grab the registration page and check the login control on it. self.assert_register_response_before_pipeline_looks_correct(self.client.get('/register')) @@ -637,8 +640,8 @@ class IntegrationTest(testutil.TestCase, test.TestCase): pipeline.get_login_url(self.PROVIDER_CLASS.NAME, pipeline.AUTH_ENTRY_LOGIN))) # Next, the provider makes a request against /auth/complete/<provider>. - # pylint: disable-msg=protected-access - self.assert_redirect_to_register_looks_correct(actions.do_complete(strategy, social_views._do_login)) + # pylint: disable=protected-access + self.assert_redirect_to_register_looks_correct(actions.do_complete(request.backend, social_views._do_login)) mako_middleware_process_request(strategy.request) # At this point we know the pipeline has resumed correctly. Next we @@ -675,7 +678,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Since the user's account is not yet active, we should be redirected to /login self.assert_redirect_to_login_looks_correct( actions.do_complete( - request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access + request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME ) ) @@ -687,7 +690,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Try again. This time, we should be redirected back to the complete page, setting # the "logged in" cookie for the marketing site. self.assert_logged_in_cookie_redirect(actions.do_complete( - request.social_strategy, social_views._do_login, request.user, None, # pylint: disable-msg=protected-access + request.backend, social_views._do_login, request.user, None, # pylint: disable=protected-access redirect_field_name=auth.REDIRECT_FIELD_NAME )) @@ -698,7 +701,7 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # and send the user to the dashboard, where the association will be # displayed. self.assert_redirect_to_dashboard_looks_correct( - actions.do_complete(strategy, social_views._do_login, user=created_user)) + actions.do_complete(strategy.request.backend, social_views._do_login, user=created_user)) self.assert_social_auth_exists_for_user(created_user, strategy) self.assert_account_settings_context_looks_correct(account_settings_context(request), created_user, linked=True) @@ -710,18 +713,20 @@ class IntegrationTest(testutil.TestCase, test.TestCase): # Create a colliding username in the backend, then proceed with # assignment via pipeline to make sure a distinct username is created. strategy.storage.user.create_user(username=self.get_username(), email='user@email.com', password='password') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) - # pylint: disable-msg=protected-access - self.assert_redirect_to_register_looks_correct(actions.do_complete(strategy, social_views._do_login)) + backend = strategy.request.backend + backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + # pylint: disable=protected-access + self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) distinct_username = pipeline.get(request)['kwargs']['username'] self.assertNotEqual(original_username, distinct_username) def test_new_account_registration_fails_if_email_exists(self): request, strategy = self.get_request_and_strategy( auth_entry=pipeline.AUTH_ENTRY_REGISTER, redirect_uri='social:complete') - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) - # pylint: disable-msg=protected-access - self.assert_redirect_to_register_looks_correct(actions.do_complete(strategy, social_views._do_login)) + backend = strategy.request.backend + backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + # pylint: disable=protected-access + self.assert_redirect_to_register_looks_correct(actions.do_complete(backend, social_views._do_login)) mako_middleware_process_request(strategy.request) self.assert_register_response_in_pipeline_looks_correct( @@ -733,21 +738,21 @@ class IntegrationTest(testutil.TestCase, test.TestCase): def test_pipeline_raises_auth_entry_error_if_auth_entry_invalid(self): auth_entry = 'invalid' - self.assertNotIn(auth_entry, pipeline._AUTH_ENTRY_CHOICES) # pylint: disable-msg=protected-access + self.assertNotIn(auth_entry, pipeline._AUTH_ENTRY_CHOICES) # pylint: disable=protected-access _, strategy = self.get_request_and_strategy(auth_entry=auth_entry, redirect_uri='social:complete') with self.assertRaises(pipeline.AuthEntryError): - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) def test_pipeline_raises_auth_entry_error_if_auth_entry_missing(self): _, strategy = self.get_request_and_strategy(auth_entry=None, redirect_uri='social:complete') with self.assertRaises(pipeline.AuthEntryError): - strategy.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) + strategy.request.backend.auth_complete = mock.MagicMock(return_value=self.fake_auth_complete(strategy)) -class Oauth2IntegrationTest(IntegrationTest): # pylint: disable-msg=abstract-method +class Oauth2IntegrationTest(IntegrationTest): # pylint: disable=abstract-method """Base test case for integration tests of Oauth2 providers.""" # Dict of string -> object. Information about the token granted to the diff --git a/common/djangoapps/third_party_auth/tests/test_change_enrollment.py b/common/djangoapps/third_party_auth/tests/test_change_enrollment.py index 3fa4655..b793286 100644 --- a/common/djangoapps/third_party_auth/tests/test_change_enrollment.py +++ b/common/djangoapps/third_party_auth/tests/test_change_enrollment.py @@ -182,6 +182,6 @@ class PipelineEnrollmentTest(UrlResetMixin, ModuleStoreTestCase): request.user = self.user request.session = cache.SessionStore() - return social_utils.load_strategy( - backend=self.BACKEND_NAME, request=request - ) + request.social_strategy = social_utils.load_strategy(request) + request.backend = social_utils.load_backend(request.social_strategy, self.BACKEND_NAME, redirect_uri='') + return request.social_strategy diff --git a/common/djangoapps/third_party_auth/tests/utils.py b/common/djangoapps/third_party_auth/tests/utils.py index 6dcc266..208930c 100644 --- a/common/djangoapps/third_party_auth/tests/utils.py +++ b/common/djangoapps/third_party_auth/tests/utils.py @@ -66,7 +66,7 @@ class ThirdPartyOAuthTestMixin(object): class ThirdPartyOAuthTestMixinFacebook(object): """Tests oauth with the Facebook backend""" BACKEND = "facebook" - USER_URL = "https://graph.facebook.com/me" + USER_URL = "https://graph.facebook.com/v2.3/me" # In facebook responses, the "id" field is used as the user's identifier UID_FIELD = "id" @@ -74,6 +74,6 @@ class ThirdPartyOAuthTestMixinFacebook(object): class ThirdPartyOAuthTestMixinGoogle(object): """Tests oauth with the Google backend""" BACKEND = "google-oauth2" - USER_URL = "https://www.googleapis.com/oauth2/v1/userinfo" + USER_URL = "https://www.googleapis.com/plus/v1/people/me" # In google-oauth2 responses, the "email" field is used as the user's identifier UID_FIELD = "email" diff --git a/common/test/db_cache/bok_choy_schema.sql b/common/test/db_cache/bok_choy_schema.sql index 2473bda..2f2373a 100644 --- a/common/test/db_cache/bok_choy_schema.sql +++ b/common/test/db_cache/bok_choy_schema.sql @@ -2236,59 +2236,6 @@ CREATE TABLE `shoppingcart_registrationcoderedemption` ( CONSTRAINT `registration_code_id_refs_id_4d01e47b` FOREIGN KEY (`registration_code_id`) REFERENCES `shoppingcart_courseregistrationcode` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `social_auth_association`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `social_auth_association` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `server_url` varchar(255) NOT NULL, - `handle` varchar(255) NOT NULL, - `secret` varchar(255) NOT NULL, - `issued` int(11) NOT NULL, - `lifetime` int(11) NOT NULL, - `assoc_type` varchar(64) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `social_auth_code`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `social_auth_code` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `email` varchar(75) NOT NULL, - `code` varchar(32) NOT NULL, - `verified` tinyint(1) NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `email` (`email`,`code`), - KEY `social_auth_code_65da3d2c` (`code`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `social_auth_nonce`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `social_auth_nonce` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `server_url` varchar(255) NOT NULL, - `timestamp` int(11) NOT NULL, - `salt` varchar(65) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; -DROP TABLE IF EXISTS `social_auth_usersocialauth`; -/*!40101 SET @saved_cs_client = @@character_set_client */; -/*!40101 SET character_set_client = utf8 */; -CREATE TABLE `social_auth_usersocialauth` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `user_id` int(11) NOT NULL, - `provider` varchar(32) NOT NULL, - `uid` varchar(255) NOT NULL, - `extra_data` longtext NOT NULL, - PRIMARY KEY (`id`), - UNIQUE KEY `provider` (`provider`,`uid`), - KEY `social_auth_usersocialauth_fbfc09f1` (`user_id`), - CONSTRAINT `user_id_refs_id_60fa311b` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -/*!40101 SET character_set_client = @saved_cs_client */; DROP TABLE IF EXISTS `south_migrationhistory`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; diff --git a/common/test/db_cache/lettuce.db b/common/test/db_cache/lettuce.db index 5060b4b..3bd9676 100644 Binary files a/common/test/db_cache/lettuce.db and b/common/test/db_cache/lettuce.db differ diff --git a/lms/envs/test.py b/lms/envs/test.py index 38a30b9..ce6342d 100644 --- a/lms/envs/test.py +++ b/lms/envs/test.py @@ -242,8 +242,8 @@ THIRD_PARTY_AUTH = { "SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET": "test", }, "Facebook": { - "SOCIAL_AUTH_GOOGLE_OAUTH2_KEY": "test", - "SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET": "test", + "SOCIAL_AUTH_FACEBOOK_KEY": "test", + "SOCIAL_AUTH_FACEBOOK_SECRET": "test", }, } diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index 37a5ccd..da14311 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -69,7 +69,7 @@ pyparsing==2.0.1 python-memcached==1.48 python-openid==2.2.5 python-dateutil==2.1 -python-social-auth==0.1.23 +python-social-auth==0.2.7 pytz==2015.2 pysrt==0.4.7 PyYAML==3.10 -- libgit2 0.26.0