diff --git a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py index 4f942417ae0e..262483152cef 100644 --- a/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py +++ b/openedx/core/djangoapps/user_api/accounts/tests/test_retirement_views.py @@ -8,20 +8,12 @@ import ddt from zoneinfo import ZoneInfo -from consent.models import DataSharingConsent from django.contrib.auth.models import User # lint-amnesty, pylint: disable=imported-auth-user from django.contrib.sites.models import Site from django.core import mail from django.core.cache import cache from django.test import TestCase from django.urls import reverse -from enterprise.models import ( - EnterpriseCourseEnrollment, - EnterpriseCustomer, - EnterpriseCustomerUser, - PendingEnterpriseCustomerUser -) -from integrated_channels.sap_success_factors.models import SapSuccessFactorsLearnerDataTransmissionAudit from opaque_keys.edx.keys import CourseKey from rest_framework import status from social_django.models import UserSocialAuth @@ -65,7 +57,6 @@ ) from openedx.core.djangoapps.external_user_ids.models import ExternalIdType from openedx.core.djangoapps.oauth_dispatch.jwt import create_jwt_for_user -from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory from openedx.core.djangoapps.user_api.accounts.views import AccountRetirementPartnerReportView from openedx.core.djangoapps.user_api.models import ( RetirementState, @@ -1289,33 +1280,6 @@ def setUp(self): self.cache_key = UserProfile.country_cache_key_name(self.test_user.id) cache.set(self.cache_key, 'Timor-leste') - # Enterprise model setup - self.course_id = 'course-v1:edX+DemoX.1+2T2017' - self.enterprise_customer = EnterpriseCustomer.objects.create( - name='test_enterprise_customer', - site=SiteFactory.create() - ) - self.enterprise_user = EnterpriseCustomerUser.objects.create( - enterprise_customer=self.enterprise_customer, - user_id=self.test_user.id, - ) - self.enterprise_enrollment = EnterpriseCourseEnrollment.objects.create( - enterprise_customer_user=self.enterprise_user, - course_id=self.course_id - ) - self.pending_enterprise_user = PendingEnterpriseCustomerUser.objects.create( - enterprise_customer_id=self.enterprise_user.enterprise_customer_id, - user_email=self.test_user.email - ) - self.sapsf_audit = SapSuccessFactorsLearnerDataTransmissionAudit.objects.create( - sapsf_user_id=self.test_user.id, - enterprise_course_enrollment_id=self.enterprise_enrollment.id, - ) - self.consent = DataSharingConsent.objects.create( - username=self.test_user.username, - enterprise_customer=self.enterprise_customer, - ) - # Entitlement model setup self.entitlement = CourseEntitlementFactory.create(user=self.test_user) self.entitlement_support_detail = CourseEntitlementSupportDetail.objects.create( @@ -1348,17 +1312,6 @@ def setUp(self): self.headers['content_type'] = "application/json" self.url = reverse('accounts_retire') - def _data_sharing_consent_assertions(self): - """ - Helper method for asserting that ``DataSharingConsent`` objects are retired. - """ - self.consent.refresh_from_db() - assert self.retired_username == self.consent.username - test_users_data_sharing_consent = DataSharingConsent.objects.filter( - username=self.original_username - ) - assert not test_users_data_sharing_consent.exists() - def _entitlement_support_detail_assertions(self): """ Helper method for asserting that ``CourseEntitleSupportDetail`` objects are retired. @@ -1366,28 +1319,6 @@ def _entitlement_support_detail_assertions(self): self.entitlement_support_detail.refresh_from_db() assert '' == self.entitlement_support_detail.comments - def _pending_enterprise_customer_user_assertions(self): - """ - Helper method for asserting that ``PendingEnterpriseCustomerUser`` objects are retired. - """ - self.pending_enterprise_user.refresh_from_db() - assert self.retired_email == self.pending_enterprise_user.user_email - pending_enterprise_users = PendingEnterpriseCustomerUser.objects.filter( - user_email=self.original_email - ) - assert not pending_enterprise_users.exists() - - def _sapsf_audit_assertions(self): - """ - Helper method for asserting that ``SapSuccessFactorsLearnerDataTransmissionAudit`` objects are retired. - """ - self.sapsf_audit.refresh_from_db() - assert '' == self.sapsf_audit.sapsf_user_id - audits_for_original_user_id = SapSuccessFactorsLearnerDataTransmissionAudit.objects.filter( - sapsf_user_id=self.test_user.id, - ) - assert not audits_for_original_user_id.exists() - def post_and_assert_status(self, data, expected_status=status.HTTP_204_NO_CONTENT): """ Helper function for making a request to the retire subscriptions endpoint, and asserting the status. @@ -1463,9 +1394,6 @@ def test_retire_user(self, mock_remove_profile_images, mock_get_profile_image_na assert cache.get(self.cache_key) is None - self._data_sharing_consent_assertions() - self._sapsf_audit_assertions() - self._pending_enterprise_customer_user_assertions() self._entitlement_support_detail_assertions() assert not PendingEmailChange.objects.filter(user=self.test_user).exists() @@ -1480,6 +1408,21 @@ def test_retire_user_twice_idempotent(self): fake_completed_retirement(self.test_user) self.post_and_assert_status(data) + @mock.patch('openedx.core.djangoapps.user_api.accounts.views.USER_RETIRE_LMS_CRITICAL') + def test_retirement_sends_critical_signal_with_retirement_data(self, mock_signal): + """ + USER_RETIRE_LMS_CRITICAL is sent with retired_username and retired_email kwargs. + """ + data = {'username': self.original_username} + self.post_and_assert_status(data) + + mock_signal.send.assert_called_once_with( + sender=mock_signal.send.call_args[1]['sender'], + user=mock_signal.send.call_args[1]['user'], + retired_username=self.retired_username, + retired_email=self.retired_email, + ) + def test_deletes_pii_from_user_profile(self): for model_field, value_to_assign in USER_PROFILE_PII.items(): if value_to_assign == '': @@ -1520,18 +1463,6 @@ def test_can_delete_user_profiles_country_cache(self): AccountRetirementView.delete_users_country_cache(self.test_user) assert cache.get(self.cache_key) is None - def test_can_retire_users_datasharingconsent(self): - AccountRetirementView.retire_users_data_sharing_consent(self.test_user.username, self.retired_username) - self._data_sharing_consent_assertions() - - def test_can_retire_users_sap_success_factors_audits(self): - AccountRetirementView.retire_sapsf_data_transmission(self.test_user) - self._sapsf_audit_assertions() - - def test_can_retire_user_from_pendingenterprisecustomeruser(self): - AccountRetirementView.retire_user_from_pending_enterprise_customer_user(self.test_user, self.retired_email) - self._pending_enterprise_customer_user_assertions() - def test_course_entitlement_support_detail_comments_are_retired(self): AccountRetirementView.retire_entitlement_support_detail(self.test_user) self._entitlement_support_detail_assertions() diff --git a/openedx/core/djangoapps/user_api/accounts/views.py b/openedx/core/djangoapps/user_api/accounts/views.py index c2bc8f4427e0..bd2f655cadb6 100644 --- a/openedx/core/djangoapps/user_api/accounts/views.py +++ b/openedx/core/djangoapps/user_api/accounts/views.py @@ -10,7 +10,6 @@ from functools import wraps from zoneinfo import ZoneInfo -from consent.models import DataSharingConsent from django.apps import apps from django.conf import settings from django.contrib.auth import authenticate, get_user_model, logout @@ -25,9 +24,6 @@ from edx_ace.recipient import Recipient from edx_rest_framework_extensions.auth.jwt.authentication import JwtAuthentication from edx_rest_framework_extensions.auth.session.authentication import SessionAuthenticationAllowInactiveUser -from enterprise.models import EnterpriseCourseEnrollment, EnterpriseCustomerUser, PendingEnterpriseCustomerUser -from integrated_channels.degreed.models import DegreedLearnerDataTransmissionAudit -from integrated_channels.sap_success_factors.models import SapSuccessFactorsLearnerDataTransmissionAudit from rest_framework import permissions, status from rest_framework.authentication import SessionAuthentication from rest_framework.exceptions import UnsupportedMediaType @@ -1154,11 +1150,6 @@ def post(self, request): # Retire user information from any certificate records associated with the learner self.clear_pii_from_certificate_records(user) - # Retire data from Enterprise models - self.retire_users_data_sharing_consent(username, retired_username) - self.retire_sapsf_data_transmission(user) - self.retire_degreed_data_transmission(user) - self.retire_user_from_pending_enterprise_customer_user(user, retired_email) self.retire_entitlement_support_detail(user) # Retire misc. models that may contain PII of this user @@ -1214,32 +1205,6 @@ def delete_users_country_cache(user): cache_key = UserProfile.country_cache_key_name(user.id) cache.delete(cache_key) - @staticmethod - def retire_users_data_sharing_consent(username, retired_username): - DataSharingConsent.objects.filter(username=username).update(username=retired_username) - - @staticmethod - def retire_sapsf_data_transmission(user): # lint-amnesty, pylint: disable=missing-function-docstring - for ent_user in EnterpriseCustomerUser.objects.filter(user_id=user.id): - for enrollment in EnterpriseCourseEnrollment.objects.filter(enterprise_customer_user=ent_user): - audits = SapSuccessFactorsLearnerDataTransmissionAudit.objects.filter( - enterprise_course_enrollment_id=enrollment.id - ) - audits.update(sapsf_user_id="") - - @staticmethod - def retire_degreed_data_transmission(user): # lint-amnesty, pylint: disable=missing-function-docstring - for ent_user in EnterpriseCustomerUser.objects.filter(user_id=user.id): - for enrollment in EnterpriseCourseEnrollment.objects.filter(enterprise_customer_user=ent_user): - audits = DegreedLearnerDataTransmissionAudit.objects.filter( - enterprise_course_enrollment_id=enrollment.id - ) - audits.update(degreed_user_email="") - - @staticmethod - def retire_user_from_pending_enterprise_customer_user(user, retired_email): - PendingEnterpriseCustomerUser.objects.filter(user_email=user.email).update(user_email=retired_email) - @staticmethod def retire_entitlement_support_detail(user): """ diff --git a/requirements/constraints.txt b/requirements/constraints.txt index 4b9169867760..8cb1831dac5a 100644 --- a/requirements/constraints.txt +++ b/requirements/constraints.txt @@ -44,7 +44,7 @@ django-stubs<6 # The team that owns this package will manually bump this package rather than having it pulled in automatically. # This is to allow them to better control its deployment and to do it in a process that works better # for them. -edx-enterprise==6.6.7 +edx-enterprise==6.6.8 # Date: 2023-07-26 # Our legacy Sass code is incompatible with anything except this ancient libsass version. @@ -54,14 +54,14 @@ edx-enterprise==6.6.7 libsass==0.10.0 # Date: 2024-07-16 -# We need to upgrade the version of elasticsearch to atleast 7.15 before we can upgrade to Numpy 2.0.0 +# We need to upgrade the version of elasticsearch to at least 7.15 before we can upgrade to Numpy 2.0.0 # Otherwise we see a failure while running the following command: # export DJANGO_SETTINGS_MODULE=cms.envs.test; python manage.py cms check_reserved_keywords --override_file db_keyword_overrides.yml --report_path reports/reserved_keywords --report_file cms_reserved_keyword_report.csv # Issue for unpinning: https://github.com/openedx/edx-platform/issues/35126 numpy<2.0.0 # Date: 2023-09-18 -# Library is still in active development. Minor verisons (0.x, 0.x+1) may have +# Library is still in active development. Minor versions (0.x, 0.x+1) may have # breaking changes which openedx-core devs want to roll out manually. New patch versions # are OK to accept automatically. # Issue for unpinning: https://github.com/openedx/edx-platform/issues/35269 diff --git a/requirements/edx/base.txt b/requirements/edx/base.txt index b4380b245783..beb3d1e57f86 100644 --- a/requirements/edx/base.txt +++ b/requirements/edx/base.txt @@ -480,7 +480,7 @@ edx-drf-extensions==10.6.0 # enterprise-integrated-channels # openedx-authz # openedx-core -edx-enterprise==6.6.7 +edx-enterprise==6.6.8 # via # -c requirements/constraints.txt # -r requirements/edx/kernel.in diff --git a/requirements/edx/development.txt b/requirements/edx/development.txt index 2d813780a770..93944b021a3a 100644 --- a/requirements/edx/development.txt +++ b/requirements/edx/development.txt @@ -761,7 +761,7 @@ edx-drf-extensions==10.6.0 # enterprise-integrated-channels # openedx-authz # openedx-core -edx-enterprise==6.6.7 +edx-enterprise==6.6.8 # via # -c requirements/constraints.txt # -r requirements/edx/doc.txt diff --git a/requirements/edx/doc.txt b/requirements/edx/doc.txt index 23b4a55931f9..1c1786b8da89 100644 --- a/requirements/edx/doc.txt +++ b/requirements/edx/doc.txt @@ -573,7 +573,7 @@ edx-drf-extensions==10.6.0 # enterprise-integrated-channels # openedx-authz # openedx-core -edx-enterprise==6.6.7 +edx-enterprise==6.6.8 # via # -c requirements/constraints.txt # -r requirements/edx/base.txt diff --git a/requirements/edx/testing.txt b/requirements/edx/testing.txt index 24e97d1853a3..75983a368275 100644 --- a/requirements/edx/testing.txt +++ b/requirements/edx/testing.txt @@ -592,7 +592,7 @@ edx-drf-extensions==10.6.0 # enterprise-integrated-channels # openedx-authz # openedx-core -edx-enterprise==6.6.7 +edx-enterprise==6.6.8 # via # -c requirements/constraints.txt # -r requirements/edx/base.txt