feat: Django app to allow user retirement via API (#25800)
This adds a new django app to allow the GDPR user retirement via Open edX's REST API. Prior to this the only way to trigger the user retirement was either by the user themself clicking "Delete my account" in the account setting page or via creating a User Retirement request by admin. With these changes, the user retirement process can be triggered using REST API.
This commit is contained in:
@@ -197,7 +197,7 @@ class TestDeactivateLogout(RetirementTestCase):
|
||||
def build_post(self, password):
|
||||
return {'password': password}
|
||||
|
||||
@mock.patch('openedx.core.djangoapps.user_api.accounts.views.retire_dot_oauth2_models')
|
||||
@mock.patch('openedx.core.djangoapps.user_api.accounts.utils.retire_dot_oauth2_models')
|
||||
def test_user_can_deactivate_self(self, mock_retire_dot):
|
||||
"""
|
||||
Verify a user calling the deactivation endpoint logs out the user, deletes all their SSO tokens,
|
||||
|
||||
@@ -11,14 +11,19 @@ from completion.waffle import ENABLE_COMPLETION_TRACKING_SWITCH
|
||||
from completion.models import BlockCompletion
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from social_django.models import UserSocialAuth
|
||||
|
||||
from common.djangoapps.third_party_auth.config.waffle import ENABLE_MULTIPLE_SSO_ACCOUNTS_ASSOCIATION_TO_SAML_USER
|
||||
from common.djangoapps.student.models import AccountRecovery, Registration, get_retired_email_by_email
|
||||
from openedx.core.djangolib.oauth2_retirement_utils import retire_dot_oauth2_models
|
||||
from openedx.core.djangoapps.site_configuration.models import SiteConfiguration
|
||||
from openedx.core.djangoapps.theming.helpers import get_config_value_from_site_or_settings, get_current_site
|
||||
from openedx.core.djangoapps.user_api.config.waffle import ENABLE_MULTIPLE_USER_ENTERPRISES_FEATURE
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from xmodule.modulestore.exceptions import ItemNotFoundError
|
||||
|
||||
from ..models import UserRetirementStatus
|
||||
|
||||
ENABLE_SECONDARY_EMAIL_FEATURE_SWITCH = 'enable_secondary_email_feature'
|
||||
|
||||
|
||||
@@ -206,3 +211,28 @@ def is_multiple_sso_accounts_association_to_saml_user_enabled():
|
||||
Boolean value representing switch status
|
||||
"""
|
||||
return ENABLE_MULTIPLE_SSO_ACCOUNTS_ASSOCIATION_TO_SAML_USER.is_enabled()
|
||||
|
||||
|
||||
def create_retirement_request_and_deactivate_account(user):
|
||||
"""
|
||||
Adds user to retirement queue, unlinks social auth accounts, changes user passwords
|
||||
and delete tokens and activation keys
|
||||
"""
|
||||
# Add user to retirement queue.
|
||||
UserRetirementStatus.create_retirement(user)
|
||||
|
||||
# Unlink LMS social auth accounts
|
||||
UserSocialAuth.objects.filter(user_id=user.id).delete()
|
||||
|
||||
# Change LMS password & email
|
||||
user.email = get_retired_email_by_email(user.email)
|
||||
user.set_unusable_password()
|
||||
user.save()
|
||||
|
||||
# TODO: Unlink social accounts & change password on each IDA.
|
||||
# Remove the activation keys sent by email to the user for account activation.
|
||||
Registration.objects.filter(user=user).delete()
|
||||
|
||||
# Delete OAuth tokens associated with the user.
|
||||
retire_dot_oauth2_models(user)
|
||||
AccountRecovery.retire_recovery_email(user.id)
|
||||
|
||||
@@ -34,7 +34,6 @@ from rest_framework.response import Response
|
||||
from rest_framework.serializers import ValidationError
|
||||
from rest_framework.views import APIView
|
||||
from rest_framework.viewsets import ViewSet
|
||||
from social_django.models import UserSocialAuth
|
||||
from wiki.models import ArticleRevision
|
||||
from wiki.models.pluginbase import RevisionPluginRevision
|
||||
|
||||
@@ -48,7 +47,6 @@ from openedx.core.djangoapps.lang_pref import LANGUAGE_KEY
|
||||
from openedx.core.djangoapps.profile_images.images import remove_profile_images
|
||||
from openedx.core.djangoapps.user_api.accounts.image_helpers import get_profile_image_names, set_has_profile_image
|
||||
from openedx.core.djangoapps.user_authn.exceptions import AuthFailedError
|
||||
from openedx.core.djangolib.oauth2_retirement_utils import retire_dot_oauth2_models
|
||||
from openedx.core.lib.api.authentication import BearerAuthenticationAllowInactiveUser
|
||||
from openedx.core.lib.api.parsers import MergePatchParser
|
||||
from common.djangoapps.student.models import ( # lint-amnesty, pylint: disable=unused-import
|
||||
@@ -81,6 +79,7 @@ from .api import get_account_settings, update_account_settings
|
||||
from .permissions import CanDeactivateUser, CanReplaceUsername, CanRetireUser
|
||||
from .serializers import UserRetirementPartnerReportSerializer, UserRetirementStatusSerializer
|
||||
from .signals import USER_RETIRE_LMS_CRITICAL, USER_RETIRE_LMS_MISC, USER_RETIRE_MAILINGS
|
||||
from .utils import create_retirement_request_and_deactivate_account
|
||||
|
||||
try:
|
||||
from coaching.api import has_ever_consented_to_coaching
|
||||
@@ -426,23 +425,8 @@ class DeactivateLogoutView(APIView):
|
||||
if verify_user_password_response.status_code != status.HTTP_204_NO_CONTENT:
|
||||
return verify_user_password_response
|
||||
with transaction.atomic():
|
||||
# Add user to retirement queue.
|
||||
UserRetirementStatus.create_retirement(request.user)
|
||||
# Unlink LMS social auth accounts
|
||||
UserSocialAuth.objects.filter(user_id=request.user.id).delete()
|
||||
# Change LMS password & email
|
||||
user_email = request.user.email
|
||||
request.user.email = get_retired_email_by_email(request.user.email)
|
||||
request.user.save()
|
||||
_set_unusable_password(request.user)
|
||||
|
||||
# TODO: Unlink social accounts & change password on each IDA.
|
||||
# Remove the activation keys sent by email to the user for account activation.
|
||||
Registration.objects.filter(user=request.user).delete()
|
||||
|
||||
# Delete OAuth tokens associated with the user.
|
||||
retire_dot_oauth2_models(request.user)
|
||||
AccountRecovery.retire_recovery_email(request.user.id)
|
||||
create_retirement_request_and_deactivate_account(request.user)
|
||||
|
||||
try:
|
||||
# Send notification email to user
|
||||
|
||||
Reference in New Issue
Block a user