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
18 changes: 1 addition & 17 deletions gdpr/anonymizers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.db.models import Model

from gdpr.encryption import numerize_key
from gdpr.utils import get_number_guess_len, get_reversion_local_field_dict
from gdpr.utils import get_number_guess_len
from gdpr.loading import anonymizer_register

if TYPE_CHECKING:
Expand Down Expand Up @@ -81,16 +81,6 @@ def get_value_from_obj(self, obj, name: str, encryption_key: str, anonymization:
return self._get_anonymized_value_from_value(getattr(obj, name), encryption_key)
return self._get_deanonymized_value_from_value(obj, getattr(obj, name), encryption_key)

def get_value_from_version(self, obj, version, name: str, encryption_key: str, anonymization: bool = True):
if anonymization:
return self._get_anonymized_value_from_value(
get_reversion_local_field_dict(version)[name], encryption_key
)
else:
return self._get_deanonymized_value_from_value(
obj, get_reversion_local_field_dict(version)[name], encryption_key
)

def get_value_from_entry(self, obj: Model, entry: "LogEntry", name: str, encryption_key: str, anonymization: bool = True):
def process_value(value: Any, is_anonymized: bool):
if value == "None":
Expand All @@ -111,12 +101,6 @@ def get_anonymized_value_from_obj(self, obj, name: str, encryption_key: str):
def get_deanonymized_value_from_obj(self, obj, name: str, encryption_key: str):
return self.get_value_from_obj(obj, name, encryption_key, anonymization=False)

def get_anonymized_value_from_version(self, obj, version, name: str, encryption_key: str):
return self.get_value_from_version(obj, version, name, encryption_key, anonymization=True)

def get_deanonymized_value_from_version(self, obj, version, name: str, encryption_key: str):
return self.get_value_from_version(obj, version, name, encryption_key, anonymization=False)

def get_anonymized_value(self, value: Any) -> Any:
"""
Deprecated
Expand Down
70 changes: 3 additions & 67 deletions gdpr/anonymizers/model_anonymizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,7 @@
from gdpr.anonymizers.base import BaseAnonymizer, FieldAnonymizer, RelationAnonymizer
from gdpr.fields import Fields
from gdpr.models import AnonymizedData, LegalReason
from gdpr.utils import (
get_field_or_none, get_reversion_version_model, get_all_obj_and_parent_versions,
get_all_obj_and_parent_versions_queryset_list, get_reversion_local_field_dict,
is_auditlog_installed, get_auditlog_entries
)
from gdpr.utils import get_field_or_none, is_auditlog_installed, get_auditlog_entries

if TYPE_CHECKING:
from gdpr.purposes.default import AbstractPurpose
Expand Down Expand Up @@ -59,8 +55,6 @@ def __new__(cls, name, bases, attrs):

if not getattr(new_obj.Meta, 'abstract', False):
anonymizer_register.register(new_obj.Meta.model, new_obj)
new_obj.Meta.anonymize_reversion = getattr(new_obj.Meta, 'anonymize_reversion', False)
new_obj.Meta.delete_reversion = getattr(new_obj.Meta, 'delete_reversion', False)
new_obj.Meta.anonymize_auditlog = getattr(new_obj.Meta, 'anonymize_auditlog', False)
new_obj.Meta.delete_auditlog = getattr(new_obj.Meta, 'delete_auditlog', False)
new_obj.Meta.reversible_anonymization = getattr(new_obj.Meta, 'reversible_anonymization', True)
Expand Down Expand Up @@ -122,25 +116,6 @@ def _get_encryption_key(self, obj, field_name: str):
def is_reversible(self, obj) -> bool:
return self.Meta.reversible_anonymization # type: ignore

def anonymize_reversion(self, obj, field_names, anonymization: bool):
from reversion.models import Version

versions: List[Version] = get_all_obj_and_parent_versions(obj)
versions_update_data = [
(
version,
{
name: self.get_value_from_version(self[name], obj, version, name,
anonymization=anonymization)
for name in field_names
if name in get_reversion_local_field_dict(version)
}
)
for version in versions
]
for version, version_dict in versions_update_data:
self._perform_version_update(version, version_dict)

def anonymize_auditlog(self, obj: Model, field_names: list[str], anonymization: bool):
for entry in get_auditlog_entries(obj):
for name in field_names:
Expand All @@ -150,11 +125,6 @@ def anonymize_auditlog(self, obj: Model, field_names: list[str], anonymization:
)
entry.save()

def delete_reversion(self, obj, anonymization: bool):
if anonymization:
for qs in get_all_obj_and_parent_versions_queryset_list(obj):
qs.delete()

def delete_auditlog(self, obj: Model, anonymization: bool):
if anonymization:
get_auditlog_entries(obj).delete()
Expand Down Expand Up @@ -193,12 +163,6 @@ def get_related_model(self, field_name: str) -> Type[Model]:
def get_value_from_obj(self, field: FieldAnonymizer, obj: Model, name: str, anonymization: bool = True) -> Any:
return field.get_value_from_obj(obj, name, self._get_encryption_key(obj, name), anonymization=anonymization)

def get_value_from_version(self, field: FieldAnonymizer, obj: Model, version, name: str,
anonymization: bool = True) -> Any:
return field.get_value_from_version(
obj, version, name, self._get_encryption_key(obj, name), anonymization=anonymization
)

def get_value_from_entry(
self, field: FieldAnonymizer, obj: Model, entry: "LogEntry", name: str, anonymization: bool = True
) -> Any:
Expand All @@ -221,7 +185,7 @@ def _perform_update(self, obj: Model, updated_data: dict, legal_reason: Optional
setattr(obj, field_name, value)

if is_auditlog_installed():
# this mirror reversion implementation, where history for anonymized change is not tracked
# this handles cases where history for anonymized change is not tracked
from auditlog.context import disable_auditlog
with disable_auditlog():
obj.save()
Expand All @@ -234,28 +198,6 @@ def perform_update(self, obj: Model, updated_data: dict, legal_reason: Optional[
anonymization: bool = True):
self._perform_update(obj, updated_data, legal_reason, anonymization=anonymization)

@staticmethod
def _perform_version_update(version, update_data):
from reversion import revisions

local_obj = version._object_version.object
for field, value in update_data.items():
setattr(local_obj, field, value)
if hasattr(revisions, '_get_options'):
version_options = revisions._get_options(get_reversion_version_model(version))
version_format = version_options.format
version_fields = version_options.fields
else:
version_adapter = revisions.get_adapter(get_reversion_version_model(version))
version_format = version_adapter.get_serialization_format()
version_fields = list(version_adapter.get_fields_to_serialize())
version.serialized_data = serializers.serialize(
version_format,
(local_obj,),
fields=version_fields
)
version.save()

def anonymize_qs(self, qs: QuerySet) -> None:
raise NotImplementedError()

Expand Down Expand Up @@ -417,10 +359,6 @@ def update_obj(self, obj: Model, legal_reason: Optional[LegalReason] = None,
update_dict = {
name: self.get_value_from_obj(self[name], obj, name, anonymization) for name in raw_local_fields
}
if self.Meta.delete_reversion: # type: ignore
self.delete_reversion(obj, anonymization)
elif self.Meta.anonymize_reversion: # type: ignore
self.anonymize_reversion(obj, raw_local_fields, anonymization)
if self.Meta.delete_auditlog:
self.delete_auditlog(obj, anonymization)
elif self.Meta.anonymize_auditlog:
Expand Down Expand Up @@ -453,7 +391,7 @@ class ModelAnonymizer(ModelAnonymizerBase):

class DeleteModelAnonymizer(ModelAnonymizer):
"""
The simpliest anonymization class that is used for removing whole input queryset.
The simplest anonymization class that is used for removing whole input queryset.

For anonymization add `__SELF__` to the FieldMatrix.
"""
Expand All @@ -474,8 +412,6 @@ def update_obj(self, obj: Model, legal_reason: Optional[LegalReason] = None,

obj.__class__.objects.filter(pk=obj.pk).delete()

if self.Meta.delete_reversion: # type: ignore
self.delete_reversion(obj, anonymization)
if self.Meta.delete_auditlog:
self.delete_auditlog(obj, anonymization)

Expand Down
44 changes: 0 additions & 44 deletions gdpr/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,49 +47,17 @@ def get_field_or_none(model: Type[Model], field_name: str):
return None


"""
Enable support for druids reversion fork
"""


def get_reversion_versions(obj: Any) -> QuerySet:
from reversion.models import Version

return Version.objects.get_for_object(obj)


def get_auditlog_entries(obj: Model) -> QuerySet:
from auditlog.models import LogEntry

return LogEntry.objects.get_for_object(obj)


def get_reversion_version_model(version) -> Type[Model]:
"""Get object model of the version."""
if hasattr(version, '_model'):
return version._model
return version.content_type.model_class()


def get_auditlog_entry_model(entry: "LogEntry") -> Type[Model] | None:
"""Get object model of the entry."""
return entry.content_type.model_class()


def get_reversion_local_field_dict(obj):
if hasattr(obj, '_local_field_dict'):
return obj._local_field_dict
return obj.flat_field_dict


def is_reversion_installed():
try:
import reversion
return True
except ImportError:
return False


def is_auditlog_installed():
try:
import auditlog
Expand All @@ -114,15 +82,3 @@ def get_all_parent_objects(obj: Model) -> List[Model]:
parent_objects.append(parent_obj)

return [i for i in parent_objects if i is not None]


def get_all_obj_and_parent_versions_queryset_list(obj: Model) -> List[QuerySet]:
"""Return list of object and its parent version querysets"""
from gdpr.utils import get_reversion_versions

return [get_reversion_versions(i) for i in get_all_parent_objects(obj)] + [get_reversion_versions(obj)]


def get_all_obj_and_parent_versions(obj: Model) -> List[Model]:
"""Return list of all object and its parent versions"""
return [item for sublist in get_all_obj_and_parent_versions_queryset_list(obj) for item in sublist]
1 change: 0 additions & 1 deletion test_requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ python-dateutil==2.7.5
django-extensions
freezegun==0.3.12
Faker==1.0.1
django-reversion==4.0.2
skip-django-germanium==2.4.0
django-auditlog
1 change: 0 additions & 1 deletion tests/anonymizers.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,3 @@ class ChildEAnonymizer(anonymizers.ModelAnonymizer):

class Meta:
model = ChildE
anonymize_reversion = True
19 changes: 1 addition & 18 deletions tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from django.utils.translation import gettext_lazy as _

from gdpr.mixins import AnonymizationModel
from gdpr.utils import is_reversion_installed, is_auditlog_installed
from gdpr.utils import is_auditlog_installed
from tests.validators import CZBirthNumberValidator, BankAccountValidator


Expand Down Expand Up @@ -124,23 +124,6 @@ class ChildE(ParentC, ExtraParentD):
last_name = models.CharField(max_length=250)


if is_reversion_installed():
from reversion import revisions as reversion

reversion.register(Customer)
reversion.register(Email)
reversion.register(Address)
reversion.register(Account)
reversion.register(Payment)
reversion.register(ContactForm)
reversion.register(Note)
reversion.register(TopParentA)
reversion.register(ParentB, follow=('topparenta_ptr',))
reversion.register(ParentC, follow=('parentb_ptr',))
reversion.register(ExtraParentD)
reversion.register(ChildE, follow=('parentc_ptr', 'extraparentd_ptr'))


if is_auditlog_installed():
from auditlog.registry import auditlog

Expand Down
5 changes: 1 addition & 4 deletions tests/test_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Minimal django settings to run tests."""
from gdpr.utils import is_reversion_installed, is_auditlog_installed
from gdpr.utils import is_auditlog_installed

DEBUG = True
SECRET_KEY = 'fake-key'
Expand All @@ -16,9 +16,6 @@
"django.contrib.sessions",
]

if is_reversion_installed():
INSTALLED_APPS += ["reversion"]


if is_auditlog_installed():
INSTALLED_APPS += ["auditlog"]
Expand Down
Loading