-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: create an ID Verification for verified mode enrollments
Add a receiver of `COURSE_ENROLLMENT_CHANGED` Open edX Event, that will create a new Manual ID Verification if the enrollment mode of the enrollment that was changed is `verified`. Added openedx-events as dependency. Update dependencies. Fix lint format code because of the test update dependencies. fccn/nau-technical#200
- Loading branch information
Showing
17 changed files
with
351 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
nau_openedx_extensions/edxapp_wrapper/backends/verify_student_v1.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
""" | ||
Real implementation of user id verifications service. | ||
""" | ||
from django.contrib.auth import get_user_model | ||
from lms.djangoapps.verify_student.models import ManualVerification # pylint: disable=import-error | ||
|
||
|
||
def get_user_id_verifications(user_id, *args, **kwargs): | ||
""" | ||
Read the user's `ManualVerification` from the edx-platform. | ||
Args: | ||
user: The user id to read the Id Verifications. | ||
Returns: | ||
An enumeration of those Id Verifications | ||
""" | ||
user = get_user_model().objects.get(id=user_id) | ||
return ManualVerification.objects.filter(user=user).order_by('-created_at') | ||
|
||
|
||
def create_user_id_verification(user_id, *args, **kwargs): | ||
""" | ||
Create a new `ManualVerification` on the edx-platform. | ||
Args: | ||
user: The user id that this Id verification should be created. | ||
Returns: | ||
The object created | ||
""" | ||
user = get_user_model().objects.get(id=user_id) | ||
ManualVerification(user=user, name=user.profile.name, *args, **kwargs).save() |
28 changes: 28 additions & 0 deletions
28
nau_openedx_extensions/edxapp_wrapper/backends/verify_student_v1_tests.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
""" | ||
Real implementation of user id verifications service. | ||
""" | ||
|
||
|
||
def get_user_id_verifications(user_id, *args, **kwargs): # pylint: disable=unused-argument | ||
""" | ||
Read the user's `ManualVerification` from the edx-platform. | ||
Args: | ||
user_id: The user id to read the Id Verifications. | ||
Returns: | ||
An enumeration of those Id Verifications | ||
""" | ||
return [] | ||
|
||
def create_user_id_verification(user_id, *args, **kwargs): # pylint: disable=unused-argument | ||
""" | ||
Create a new `ManualVerification` on the edx-platform. | ||
Args: | ||
user_id: The user id that this Id verification should be created. | ||
Returns: | ||
The object created | ||
""" | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
""" | ||
Student backend abstraction | ||
""" | ||
from __future__ import absolute_import, unicode_literals | ||
|
||
from importlib import import_module | ||
|
||
from django.conf import settings | ||
|
||
|
||
def get_user_id_verifications(user_id, *args, **kwargs): | ||
""" | ||
Read the user's `ManualVerification` from the edx-platform. | ||
""" | ||
|
||
backend_module = settings.NAU_VERIFY_STUDENT_MODULE | ||
backend = import_module(backend_module) | ||
|
||
return backend.get_user_id_verifications(user_id, *args, **kwargs) | ||
|
||
|
||
def create_user_id_verification(user_id, *args, **kwargs): | ||
""" | ||
Create an user Id Verification `ManualVerification` instance on the edx-platform. | ||
""" | ||
backend_module = settings.NAU_VERIFY_STUDENT_MODULE | ||
backend = import_module(backend_module) | ||
|
||
return backend.create_user_id_verification(user_id, *args, **kwargs) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ msgid "" | |
msgstr "" | ||
"Project-Id-Version: PROJECT VERSION\n" | ||
"Report-Msgid-Bugs-To: [email protected]\n" | ||
"POT-Creation-Date: 2024-09-26 11:25+0100\n" | ||
"POT-Creation-Date: 2024-10-02 13:56+0100\n" | ||
"PO-Revision-Date: 2021-02-15 15:56+0000\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
"Language: en\n" | ||
|
@@ -133,11 +133,11 @@ msgid "" | |
"out in order to obtain a certificate." | ||
msgstr "" | ||
|
||
#: nau_openedx_extensions/settings/common.py:89 | ||
#: nau_openedx_extensions/settings/common.py:35 | ||
msgid "Certificate" | ||
msgstr "" | ||
|
||
#: nau_openedx_extensions/settings/common.py:90 | ||
#: nau_openedx_extensions/settings/common.py:36 | ||
msgid "Certificate of Achievement" | ||
msgstr "" | ||
|
||
|
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ msgid "" | |
msgstr "" | ||
"Project-Id-Version: PROJECT VERSION\n" | ||
"Report-Msgid-Bugs-To: [email protected]\n" | ||
"POT-Creation-Date: 2024-09-26 11:25+0100\n" | ||
"POT-Creation-Date: 2024-10-02 13:56+0100\n" | ||
"PO-Revision-Date: 2021-02-15 15:56+0000\n" | ||
"Last-Translator: Ivo Branco <[email protected]>\n" | ||
"Language: pt_PT\n" | ||
|
@@ -142,11 +142,11 @@ msgstr "" | |
"Este curso encontra-se arquivado e já não permite a realização de " | ||
"atividades para obtenção de certificado." | ||
|
||
#: nau_openedx_extensions/settings/common.py:89 | ||
#: nau_openedx_extensions/settings/common.py:35 | ||
msgid "Certificate" | ||
msgstr "Certificado" | ||
|
||
#: nau_openedx_extensions/settings/common.py:90 | ||
#: nau_openedx_extensions/settings/common.py:36 | ||
msgid "Certificate of Achievement" | ||
msgstr "Certificado de Conclusão" | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
""" | ||
File that contains the definition of all signals and its receivers. | ||
""" | ||
|
||
from nau_openedx_extensions.verify_student.id_verification import ( # pylint: disable=unused-import | ||
event_receiver_no_id_verify_for_enrollment_modes, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
""" | ||
Tests for Id Verification of studentes. | ||
""" | ||
|
||
from datetime import datetime | ||
from unittest.mock import Mock, patch | ||
|
||
from django.test import TestCase, override_settings | ||
from openedx_events.learning.data import CourseEnrollmentData, UserData | ||
from openedx_events.learning.signals import COURSE_ENROLLMENT_CHANGED | ||
|
||
from nau_openedx_extensions.verify_student.id_verification import event_receiver_no_id_verify_for_enrollment_modes | ||
|
||
|
||
class VerifyStudentTest(TestCase): | ||
""" | ||
Tests for Id Verification patch. | ||
""" | ||
|
||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.get_user_id_verifications" | ||
) | ||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.create_user_id_verification" | ||
) | ||
def test_verify_student_create_new_verification( | ||
self, create_user_id_verification_mock, get_user_id_verifications_mock | ||
): | ||
""" | ||
Test an enrollment mode that requires a ID Verification. | ||
""" | ||
user_id = 10 | ||
get_user_id_verifications_mock.return_value = [] | ||
COURSE_ENROLLMENT_CHANGED.connect(event_receiver_no_id_verify_for_enrollment_modes) | ||
COURSE_ENROLLMENT_CHANGED.send_event( | ||
enrollment=CourseEnrollmentData( | ||
user=UserData(id=user_id, is_active=True, pii=None), | ||
mode="verified", | ||
course=None, | ||
is_active=None, | ||
creation_date=None, | ||
) | ||
) | ||
create_user_id_verification_mock.assert_called_once() | ||
self.assertEqual(create_user_id_verification_mock.call_args.args[0], user_id) | ||
create_user_id_verification_mock_kwargs = ( | ||
create_user_id_verification_mock.call_args.kwargs | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock_kwargs, | ||
{ | ||
**create_user_id_verification_mock_kwargs, | ||
**{ | ||
"status": "approved", | ||
}, | ||
}, | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock_kwargs, | ||
{ | ||
**create_user_id_verification_mock_kwargs, | ||
**{ | ||
"reason": "Skip id verification from nau_openedx_extensions", | ||
}, | ||
}, | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock.call_args.kwargs.get( | ||
"expiration_date" | ||
).year, | ||
datetime.today().year + 100, | ||
) | ||
|
||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.get_user_id_verifications" | ||
) | ||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.create_user_id_verification" | ||
) | ||
def test_verify_student_enrollment_mode_not_need_id_verification_patch( | ||
self, create_user_id_verification_mock, get_user_id_verifications_mock | ||
): | ||
""" | ||
Test a case enrollment mode that doesn't requires a ID Verification. | ||
""" | ||
user_id = 10 | ||
get_user_id_verifications_mock.return_value = [] | ||
COURSE_ENROLLMENT_CHANGED.connect(event_receiver_no_id_verify_for_enrollment_modes) | ||
COURSE_ENROLLMENT_CHANGED.send_event( | ||
enrollment=CourseEnrollmentData( | ||
user=UserData(id=user_id, is_active=True, pii=None), | ||
mode="honor", | ||
course=None, | ||
is_active=None, | ||
creation_date=None, | ||
) | ||
) | ||
create_user_id_verification_mock.assert_not_called() | ||
|
||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.get_user_id_verifications" | ||
) | ||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.create_user_id_verification" | ||
) | ||
@override_settings(NAU_NO_ID_VERIFY_FOR_ENROLLMENT_MODES="verified, somemode") | ||
def test_verify_student_change_enrollment_modes_require_id_verification( | ||
self, create_user_id_verification_mock, get_user_id_verifications_mock | ||
): | ||
""" | ||
Test that changing the setting `NAU_NO_ID_VERIFY_FOR_ENROLLMENT_MODES` to include a custom enrollment mode, | ||
and test with that new custom enrollment mode, it still creates an id verification. | ||
""" | ||
user_id = 10 | ||
get_user_id_verifications_mock.return_value = [] | ||
COURSE_ENROLLMENT_CHANGED.connect(event_receiver_no_id_verify_for_enrollment_modes) | ||
COURSE_ENROLLMENT_CHANGED.send_event( | ||
enrollment=CourseEnrollmentData( | ||
user=UserData(id=user_id, is_active=True, pii=None), | ||
mode="somemode", | ||
course=None, | ||
is_active=None, | ||
creation_date=None, | ||
) | ||
) | ||
create_user_id_verification_mock.assert_called_once() | ||
self.assertEqual(create_user_id_verification_mock.call_args.args[0], user_id) | ||
create_user_id_verification_mock_kwargs = ( | ||
create_user_id_verification_mock.call_args.kwargs | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock_kwargs, | ||
{ | ||
**create_user_id_verification_mock_kwargs, | ||
**{ | ||
"status": "approved", | ||
}, | ||
}, | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock_kwargs, | ||
{ | ||
**create_user_id_verification_mock_kwargs, | ||
**{ | ||
"reason": "Skip id verification from nau_openedx_extensions", | ||
}, | ||
}, | ||
) | ||
self.assertEqual( | ||
create_user_id_verification_mock.call_args.kwargs.get( | ||
"expiration_date" | ||
).year, | ||
datetime.today().year + 100, | ||
) | ||
|
||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.get_user_id_verifications" | ||
) | ||
@patch( | ||
"nau_openedx_extensions.verify_student.id_verification.create_user_id_verification" | ||
) | ||
def test_verify_student_with_existing_id_verification( | ||
self, create_user_id_verification_mock, get_user_id_verifications_mock | ||
): | ||
""" | ||
Test that if the user already has an id verification, it won't try to create a new one. | ||
""" | ||
active_at_datetime_mock = Mock() | ||
active_at_datetime_mock.return_value = True | ||
|
||
user_id = 10 | ||
get_user_id_verifications_mock.return_value = active_at_datetime_mock | ||
COURSE_ENROLLMENT_CHANGED.connect(event_receiver_no_id_verify_for_enrollment_modes) | ||
COURSE_ENROLLMENT_CHANGED.send_event( | ||
enrollment=CourseEnrollmentData( | ||
user=UserData(id=user_id, is_active=True, pii=None), | ||
mode="verify", | ||
course=None, | ||
is_active=None, | ||
creation_date=None, | ||
) | ||
) | ||
create_user_id_verification_mock.assert_not_called() |
Oops, something went wrong.