From 9220c4d8dd38399df60fedf4b040187851f951d1 Mon Sep 17 00:00:00 2001 From: Amir Qayyum Khan Date: Wed, 30 Mar 2016 18:17:34 +0500 Subject: [PATCH] Fixed 500 error in case of user's profile not found when login/logout with CAS --- common/djangoapps/external_auth/views.py | 7 ++-- common/djangoapps/student/models.py | 7 +++- common/djangoapps/student/tests/test_login.py | 42 +++++++++++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/common/djangoapps/external_auth/views.py b/common/djangoapps/external_auth/views.py index 0bba580f74..3a49a9e720 100644 --- a/common/djangoapps/external_auth/views.py +++ b/common/djangoapps/external_auth/views.py @@ -478,9 +478,10 @@ def cas_login(request, next_page=None, required=False): if request.user.is_authenticated(): user = request.user - if not UserProfile.objects.filter(user=user): - user_profile = UserProfile(name=user.username, user=user) - user_profile.save() + UserProfile.objects.get_or_create( + user=user, + defaults={'name': user.username} + ) return ret diff --git a/common/djangoapps/student/models.py b/common/djangoapps/student/models.py index cf5fa7bac0..195af3a0ad 100644 --- a/common/djangoapps/student/models.py +++ b/common/djangoapps/student/models.py @@ -1799,7 +1799,12 @@ def enforce_single_login(sender, request, user, signal, **kwargs): # pylint: else: key = None if user: - user.profile.set_login_session(key) + user_profile, __ = UserProfile.objects.get_or_create( + user=user, + defaults={'name': user.username} + ) + if user_profile: + user.profile.set_login_session(key) class DashboardConfiguration(ConfigurationModel): diff --git a/common/djangoapps/student/tests/test_login.py b/common/djangoapps/student/tests/test_login.py index 926a7999f3..1a80873a78 100644 --- a/common/djangoapps/student/tests/test_login.py +++ b/common/djangoapps/student/tests/test_login.py @@ -272,6 +272,48 @@ class LoginTest(TestCase): # client1 will be logged out self.assertEqual(response.status_code, 302) + @patch.dict("django.conf.settings.FEATURES", {'PREVENT_CONCURRENT_LOGINS': True}) + def test_single_session_with_no_user_profile(self): + """ + Assert that user login with cas (Central Authentication Service) is + redirect to dashboard in case of lms or upload_transcripts in case of + cms + """ + user = UserFactory.build(username='tester', email='tester@edx.org') + user.set_password('test_password') + user.save() + + # Assert that no profile is created. + self.assertFalse(hasattr(user, 'profile')) + + creds = {'email': 'tester@edx.org', 'password': 'test_password'} + client1 = Client() + client2 = Client() + + response = client1.post(self.url, creds) + self._assert_response(response, success=True) + + # Reload the user from the database + user = User.objects.get(pk=user.pk) + + # Assert that profile is created. + self.assertTrue(hasattr(user, 'profile')) + + # second login should log out the first + response = client2.post(self.url, creds) + self._assert_response(response, success=True) + + try: + # this test can be run with either lms or studio settings + # since studio does not have a dashboard url, we should + # look for another url that is login_required, in that case + url = reverse('dashboard') + except NoReverseMatch: + url = reverse('upload_transcripts') + response = client1.get(url) + # client1 will be logged out + self.assertEqual(response.status_code, 302) + @patch.dict("django.conf.settings.FEATURES", {'PREVENT_CONCURRENT_LOGINS': True}) def test_single_session_with_url_not_having_login_required_decorator(self): # accessing logout url as it does not have login-required decorator it will avoid redirect