From 744d650ef28b9b2db77fb4c4141fa02c726d1c71 Mon Sep 17 00:00:00 2001 From: Bianca Severino Date: Tue, 18 May 2021 16:03:50 -0400 Subject: [PATCH] feat: add integrity signature check to courseware api --- .../djangoapps/courseware_api/serializers.py | 1 + .../courseware_api/tests/test_views.py | 32 +++++++++++++++++++ .../core/djangoapps/courseware_api/views.py | 23 +++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/openedx/core/djangoapps/courseware_api/serializers.py b/openedx/core/djangoapps/courseware_api/serializers.py index dad21fd24f..65326d2177 100644 --- a/openedx/core/djangoapps/courseware_api/serializers.py +++ b/openedx/core/djangoapps/courseware_api/serializers.py @@ -117,6 +117,7 @@ class CourseInfoSerializer(serializers.Serializer): # pylint: disable=abstract- verification_status = serializers.CharField() linkedin_add_to_profile_url = serializers.URLField() is_mfe_special_exams_enabled = serializers.BooleanField() + user_needs_integrity_signature = serializers.BooleanField() def __init__(self, *args, **kwargs): """ diff --git a/openedx/core/djangoapps/courseware_api/tests/test_views.py b/openedx/core/djangoapps/courseware_api/tests/test_views.py index fed0f41555..3e7a33491b 100644 --- a/openedx/core/djangoapps/courseware_api/tests/test_views.py +++ b/openedx/core/djangoapps/courseware_api/tests/test_views.py @@ -37,6 +37,8 @@ from common.djangoapps.student.models import ( ) from common.djangoapps.student.roles import CourseInstructorRole from common.djangoapps.student.tests.factories import CourseEnrollmentCelebrationFactory, UserFactory +from openedx.core.djangoapps.agreements.api import create_integrity_signature +from openedx.core.djangoapps.agreements.toggles import ENABLE_INTEGRITY_SIGNATURE from xmodule.modulestore.django import modulestore from xmodule.modulestore.tests.django_utils import TEST_DATA_SPLIT_MODULESTORE, SharedModuleStoreTestCase from xmodule.modulestore.tests.factories import ItemFactory, ToyCourseFactory @@ -321,6 +323,36 @@ class CourseApiTestViews(BaseCoursewareTests, MasqueradeMixin): assert 'is_mfe_special_exams_enabled' in courseware_data assert courseware_data['is_mfe_special_exams_enabled'] == (is_globaly_enabled and is_waffle_enabled) + @ddt.data( + (None, False, False, False), + ('verified', False, False, True), + ('masters', False, False, True), + ('audit', False, False, False), + ('verified', False, True, False), + ('masters', False, True, False), + ('verified', True, False, False), + ) + @ddt.unpack + @override_waffle_flag(ENABLE_INTEGRITY_SIGNATURE, True) + def test_user_needs_integrity_signature( + self, enrollment_mode, is_staff, has_integrity_signature, needs_integrity_signature, + ): + """ + Test that the correct value is returned if the user needs to sign the integrity agreement for the course. + """ + if is_staff: + self.user.is_staff = True + self.user.save() + if enrollment_mode: + CourseEnrollment.enroll(self.user, self.course.id, enrollment_mode) + if has_integrity_signature: + create_integrity_signature(self.user.username, str(self.course.id)) + response = self.client.get(self.url) + assert response.status_code == 200 + courseware_data = response.json() + assert 'user_needs_integrity_signature' in courseware_data + assert courseware_data['user_needs_integrity_signature'] == needs_integrity_signature + class SequenceApiTestViews(BaseCoursewareTests): """ diff --git a/openedx/core/djangoapps/courseware_api/views.py b/openedx/core/djangoapps/courseware_api/views.py index 01052b9ede..d58884e76d 100644 --- a/openedx/core/djangoapps/courseware_api/views.py +++ b/openedx/core/djangoapps/courseware_api/views.py @@ -43,11 +43,13 @@ from lms.djangoapps.courseware.toggles import ( from lms.djangoapps.courseware.views.views import get_cert_data from lms.djangoapps.grades.api import CourseGradeFactory from lms.djangoapps.verify_student.services import IDVerificationService +from openedx.core.djangoapps.agreements.api import get_integrity_signature +from openedx.core.djangoapps.agreements.toggles import is_integrity_signature_enabled +from openedx.core.djangoapps.courseware_api.utils import get_celebrations_dict +from openedx.core.djangoapps.programs.utils import ProgramProgressMeter from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser from openedx.core.lib.api.view_utils import DeveloperErrorViewMixin from openedx.core.lib.courses import get_course_by_id -from openedx.core.djangoapps.courseware_api.utils import get_celebrations_dict -from openedx.core.djangoapps.programs.utils import ProgramProgressMeter from openedx.features.course_experience import DISPLAY_COURSE_SOCK_FLAG from openedx.features.content_type_gating.models import ContentTypeGatingConfig from openedx.features.course_duration_limits.access import get_access_expiration_data @@ -292,6 +294,22 @@ class CoursewareMeta: self.overview.display_name, user_certificate.mode, cert_url, certificate=user_certificate, ) + @property + def user_needs_integrity_signature(self): + """ + Boolean describing whether the user needs to sign the integrity agreement for a course. + """ + if ( + not self.is_staff + and self.enrollment_object + and self.enrollment_object.mode in CourseMode.CERTIFICATE_RELEVANT_MODES + and is_integrity_signature_enabled() + ): + signature = get_integrity_signature(self.effective_user.username, str(self.course_key)) + if not signature: + return True + return False + @property def related_programs(self): """ @@ -405,6 +423,7 @@ class CoursewareInformation(RetrieveAPIView): * verify_identity_url: URL for a learner to verify their identity. Only returned for learners enrolled in a verified mode. Will update to reverify URL if necessary. * linkedin_add_to_profile_url: URL to add the effective user's certificate to a LinkedIn Profile. + * user_needs_integrity_signature: Whether the user needs to sign the integrity agreement for the course **Parameters:**