From 136db5ec28eb255827aae6c8a11ed69f23ea4129 Mon Sep 17 00:00:00 2001 From: Bianca Severino Date: Mon, 27 Jul 2020 10:37:40 -0400 Subject: [PATCH] Add SSO Records endpoint for support tools --- lms/djangoapps/support/serializers.py | 18 +++++++++ lms/djangoapps/support/tests/test_views.py | 44 +++++++++++++++++++++ lms/djangoapps/support/urls.py | 4 +- lms/djangoapps/support/views/sso_records.py | 24 +++++++++++ 4 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 lms/djangoapps/support/views/sso_records.py diff --git a/lms/djangoapps/support/serializers.py b/lms/djangoapps/support/serializers.py index c171f2eb28..6247c9e538 100644 --- a/lms/djangoapps/support/serializers.py +++ b/lms/djangoapps/support/serializers.py @@ -1,6 +1,8 @@ """ Serializers for use in the support app. """ +import json + from django.urls import reverse from rest_framework import serializers @@ -86,3 +88,19 @@ def serialize_user_info(user, user_social_auths=None): 'uid': user_social_auth.uid, }) return user_info + + +def serialize_sso_records(user_social_auths): + """ + Serialize user social auth model object + """ + sso_records = [] + for user_social_auth in user_social_auths: + sso_records.append({ + 'provider': user_social_auth.provider, + 'uid': user_social_auth.uid, + 'created': user_social_auth.created, + 'modified': user_social_auth.modified, + 'extraData': json.dumps(user_social_auth.extra_data), + }) + return sso_records diff --git a/lms/djangoapps/support/tests/test_views.py b/lms/djangoapps/support/tests/test_views.py index 330abacca4..ffc96a946c 100644 --- a/lms/djangoapps/support/tests/test_views.py +++ b/lms/djangoapps/support/tests/test_views.py @@ -959,3 +959,47 @@ class ProgramEnrollmentsInspectorViewTests(SupportViewTestCase): ) render_call_dict = mocked_render.call_args[0][1] assert expected_error == render_call_dict['error'] + + +class SsoRecordsTests(SupportViewTestCase): + + def setUp(self): + """Make the user support staff""" + super(SsoRecordsTests, self).setUp() + SupportStaffRole().add_users(self.user) + self.student = UserFactory.create(username='student', email='test@example.com', password='test') + self.url = reverse("support:sso_records", kwargs={'username_or_email': self.student.username}) + self.org_key_list = ['test_org'] + for org_key in self.org_key_list: + lms_org = OrganizationFactory( + short_name=org_key + ) + SAMLProviderConfigFactory( + organization=lms_org, + slug=org_key, + enabled=True, + ) + + def test_empty_response(self): + response = self.client.get(self.url) + data = json.loads(response.content.decode('utf-8')) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(data), 0) + + def test_user_does_not_exist(self): + response = self.client.get(reverse("support:sso_records", kwargs={'username_or_email': 'wrong_username'})) + data = json.loads(response.content.decode('utf-8')) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(data), 0) + + def test_response(self): + user_social_auth = UserSocialAuth.objects.create( + user=self.student, + uid=self.student.email, + provider='tpa-saml' + ) + response = self.client.get(self.url) + data = json.loads(response.content.decode('utf-8')) + self.assertEqual(response.status_code, 200) + self.assertEqual(len(data), 1) + self.assertContains(response, '"uid": "test@example.com"') diff --git a/lms/djangoapps/support/urls.py b/lms/djangoapps/support/urls.py index 5ebd6a7bcb..5989aef98d 100644 --- a/lms/djangoapps/support/urls.py +++ b/lms/djangoapps/support/urls.py @@ -13,6 +13,7 @@ from support.views.feature_based_enrollments import FeatureBasedEnrollmentsSuppo from support.views.index import index from support.views.manage_user import ManageUserDetailView, ManageUserSupportView from support.views.program_enrollments import LinkProgramEnrollmentSupportView, ProgramEnrollmentsInspectorView +from support.views.sso_records import SsoView COURSE_ENTITLEMENTS_VIEW = EntitlementSupportView.as_view() @@ -44,5 +45,6 @@ urlpatterns = [ r'program_enrollments_inspector/?$', ProgramEnrollmentsInspectorView.as_view(), name='program_enrollments_inspector' - ) + ), + url(r'sso_records/(?P[\w.@+-]+)?$', SsoView.as_view(), name='sso_records'), ] diff --git a/lms/djangoapps/support/views/sso_records.py b/lms/djangoapps/support/views/sso_records.py new file mode 100644 index 0000000000..6c6313af48 --- /dev/null +++ b/lms/djangoapps/support/views/sso_records.py @@ -0,0 +1,24 @@ +from django.contrib.auth.models import User +from django.db.models import Q +from django.utils.decorators import method_decorator +from rest_framework.generics import GenericAPIView +from social_django.models import UserSocialAuth + +from lms.djangoapps.support.decorators import require_support_permission +from lms.djangoapps.support.serializers import serialize_sso_records +from util.json_request import JsonResponse + + +class SsoView(GenericAPIView): + """ + Returns a list of SSO records for a given user. + """ + @method_decorator(require_support_permission) + def get(self, request, username_or_email): + try: + user = User.objects.get(Q(username=username_or_email) | Q(email=username_or_email)) + except User.DoesNotExist: + return JsonResponse([]) + user_social_auths = UserSocialAuth.objects.filter(user=user) + sso_records = serialize_sso_records(user_social_auths) + return JsonResponse(sso_records)