Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -1348,46 +1312,13 @@ 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.
"""
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.
Expand Down Expand Up @@ -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()
Expand All @@ -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 == '':
Expand Down Expand Up @@ -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()
Expand Down
35 changes: 0 additions & 35 deletions openedx/core/djangoapps/user_api/accounts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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):
"""
Expand Down
6 changes: 3 additions & 3 deletions requirements/constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/development.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/doc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion requirements/edx/testing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading