1818from django .contrib .auth .base_user import AbstractBaseUser , BaseUserManager
1919from django .contrib .auth .hashers import check_password
2020from django .contrib .auth .models import PermissionsMixin
21+ from django .core .exceptions import FieldDoesNotExist
2122from django .dispatch import receiver
2223from django .db import models
2324from django .db .models import Count , Exists , OuterRef
@@ -2020,14 +2021,12 @@ def gdpr_delete(self):
20202021 """
20212022 Complies with GDPR guidelines by disabling the account and removing identifying information.
20222023 """
2023-
2024- # Check if user has something intentionally public, like preprints or registrations
2025- self ._validate_no_public_entities ()
2026-
2027- # Check if user has any non-registration AbstractNodes or DraftRegistrations that they might still share with
2028- # other contributors
20292024 self ._validate_and_remove_resource_for_gdpr_delete (
2030- self .nodes .exclude (type = 'osf.registration' ), # Includes DraftNodes and other typed nodes
2025+ self .nodes .all (),
2026+ hard_delete = False
2027+ )
2028+ self ._validate_and_remove_resource_for_gdpr_delete (
2029+ self .preprints .all (),
20312030 hard_delete = False
20322031 )
20332032 self ._validate_and_remove_resource_for_gdpr_delete (
@@ -2038,39 +2037,6 @@ def gdpr_delete(self):
20382037 # Finally delete the user's info.
20392038 self ._clear_identifying_information ()
20402039
2041- def _validate_no_public_entities (self ):
2042- """
2043- Ensure that the user doesn't have any public facing resources like Registrations or Preprints
2044- that would be left with other contributors after this deletion.
2045-
2046- Allow GDPR deletion if the user is the sole contributor on a public Registration or Preprint.
2047- """
2048- from osf .models import Preprint , AbstractNode
2049-
2050- registrations_with_others = AbstractNode .objects .annotate (
2051- contrib_count = Count ('_contributors' , distinct = True ),
2052- ).filter (
2053- _contributors = self ,
2054- deleted__isnull = True ,
2055- type = 'osf.registration' ,
2056- contrib_count__gt = 1
2057- ).exists ()
2058-
2059- if registrations_with_others :
2060- raise UserStateError ('You cannot delete this user because they have one or more registrations.' )
2061-
2062- preprints_with_others = Preprint .objects .annotate (
2063- contrib_count = Count ('_contributors' , distinct = True ),
2064- ).filter (
2065- _contributors = self ,
2066- ever_public = True ,
2067- deleted__isnull = True ,
2068- contrib_count__gt = 1
2069- ).exists ()
2070-
2071- if preprints_with_others :
2072- raise UserStateError ('You cannot delete this user because they have one or more preprints.' )
2073-
20742040 def _validate_and_remove_resource_for_gdpr_delete (self , resources , hard_delete ):
20752041 """
20762042 This method ensures a user's resources are properly deleted of using during GDPR delete request.
@@ -2095,26 +2061,35 @@ def _validate_and_remove_resource_for_gdpr_delete(self, resources, hard_delete):
20952061 )
20962062
20972063 shared_resources = resources .exclude (id__in = personal_resources .values_list ('id' ))
2098- for node in shared_resources :
2099- self ._validate_admin_status_for_gdpr_delete (node )
2100- self ._validate_addons_for_gdpr_delete (node )
2064+ for resource in shared_resources :
2065+ self ._validate_admin_status_for_gdpr_delete (resource )
2066+ self ._validate_addons_for_gdpr_delete (resource )
21012067
21022068 for resource in shared_resources .all ():
21032069 logger .info (f'Removing { self ._id } as a contributor to { resource .__class__ .__name__ } (pk:{ resource .pk } )...' )
21042070 resource .remove_contributor (self , auth = Auth (self ), log = False )
2071+ if getattr (resource , 'is_public' , False ) and hasattr (resource , 'update_search' ):
2072+ resource .update_search ()
21052073
2106- # Delete all personal entities (excluding public registrations)
2074+ # Delete all personal non- public entities
21072075 personal_to_delete = personal_resources
2108- if hasattr (model , 'is_public' ) and hasattr (model , 'type' ):
2109- personal_to_delete = personal_to_delete .exclude (is_public = True , type = 'osf.registration' )
2076+ try :
2077+ if model ._meta .get_field ('is_public' ):
2078+ personal_to_delete = personal_to_delete .exclude (is_public = True )
2079+ except FieldDoesNotExist :
2080+ pass
21102081
21112082 for entity in personal_to_delete .all ():
21122083 if hard_delete :
21132084 logger .info (f'Hard-deleting { entity .__class__ .__name__ } (pk: { entity .pk } )...' )
21142085 entity .delete ()
21152086 else :
21162087 logger .info (f'Soft-deleting { entity .__class__ .__name__ } (pk: { entity .pk } )...' )
2117- entity .remove_node (auth = Auth (self ))
2088+ if hasattr (entity , 'remove_node' ):
2089+ entity .remove_node (auth = Auth (self ))
2090+ else :
2091+ entity .is_deleted = True
2092+ entity .save ()
21182093
21192094 def _clear_identifying_information (self ):
21202095 '''
0 commit comments