diff --git a/chcemvediet/apps/anonymization/management/__init__.py b/chcemvediet/apps/anonymization/management/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/chcemvediet/apps/anonymization/management/commands/__init__.py b/chcemvediet/apps/anonymization/management/commands/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py b/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py new file mode 100644 index 000000000..ae2f7c921 --- /dev/null +++ b/chcemvediet/apps/anonymization/management/commands/attachment_anonymization.py @@ -0,0 +1,65 @@ +from optparse import make_option + +import magic +from django.core.files.base import ContentFile +from django.core.management.base import BaseCommand, CommandError + +from poleno.attachments.models import Attachment +from chcemvediet.apps.anonymization.models import AttachmentFinalization +from chcemvediet.apps.inforequests.models import Action + + +class Command(BaseCommand): + help = u'Creates AttachmentFinalization for the specified Attachment.' + + option_list = BaseCommand.option_list + ( + make_option(u'-f', u'--file', + dest=u'filename', + help=u'define file path'), + make_option(u'--content_type', + help=u'define content type of file', + ), + make_option(u'--debug', + default=u'', + help=u'add debug message' + ), + make_option(u'--force', + action=u'store_true', + help=u'overwrite an existing successful AttachmentFinalization' + ), + ) + + def usage(self, subcommand=None): + return u'manage.py attachment_anonymization attachment [options] [file]' + + def handle(self, *args, **options): + try: + filename = options[u'filename'] or args[1] + except IndexError: + self.stdout.write(u'Usage: {}'.format(self.usage())) + self.stdout.write( + u'Try "manage.py attachment_anonymization --help" for more information.') + return 1 + + with open(filename, u'rb') as file: + try: + attachment = (Attachment.objects + .attached_to(Action) + .not_normalized() + .get(pk=int(args[0]))) + attachments_finalization = (AttachmentFinalization.objects + .filter(attachment=attachment) + .successful()) + if options[u'force'] or not attachments_finalization: + attachments_finalization.delete() + content = file.read() + content_type = magic.from_buffer(content, mime=True) + AttachmentFinalization.objects.create( + attachment=attachment, + successful=True, + file=ContentFile(content), + content_type=options[u'content_type'] or content_type, + debug=options[u'debug'], + ) + except Attachment.DoesNotExist: + raise CommandError(u'Attachment {} does not exist'.format(args[0])) diff --git a/chcemvediet/apps/anonymization/models.py b/chcemvediet/apps/anonymization/models.py index a60c22845..5120019a0 100644 --- a/chcemvediet/apps/anonymization/models.py +++ b/chcemvediet/apps/anonymization/models.py @@ -322,6 +322,9 @@ def __unicode__(self): return format(self.pk) class AttachmentFinalizationQuerySet(QuerySet): + def successful(self): + return self.filter(successful=True) + def order_by_pk(self): return self.order_by(u'pk') diff --git a/chcemvediet/apps/anonymization/tests/__init__.py b/chcemvediet/apps/anonymization/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/chcemvediet/apps/anonymization/tests/test_management_commands.py b/chcemvediet/apps/anonymization/tests/test_management_commands.py new file mode 100644 index 000000000..6440b79bf --- /dev/null +++ b/chcemvediet/apps/anonymization/tests/test_management_commands.py @@ -0,0 +1,71 @@ +import os +from testfixtures import TempDirectory + +from django.core.management import call_command +from django.test import TestCase +from django.test.utils import override_settings + +from chcemvediet.apps.anonymization.models import AttachmentFinalization +from chcemvediet.tests import ChcemvedietTestCaseMixin + + +class AttachmentAnonymizationManagementCommandTest(ChcemvedietTestCaseMixin, TestCase): + + def _pre_setup(self): + super(AttachmentAnonymizationManagementCommandTest, self)._pre_setup() + self.tempdir = TempDirectory() + self.settings_override = override_settings( + MEDIA_ROOT=self.tempdir.path, + ) + self.settings_override.enable() + self.attachment = self._create_attachment() + + def _post_teardown(self): + self.settings_override.disable() + self.tempdir.cleanup() + super(AttachmentAnonymizationManagementCommandTest, self)._post_teardown() + + def _create_attachment(self, **kwargs): + return super(AttachmentAnonymizationManagementCommandTest, self)._create_attachment( + generic_object=self.action, + **kwargs + ) + + + def test_attachment_anonymization_command_with_valid_arguments_creates_attachment_finalization(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, file.name) + AttachmentFinalization.objects.get(attachment=self.attachment) + + def test_attachment_anonymization_command_file_option(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, filename=file.name) + AttachmentFinalization.objects.get(attachment=self.attachment) + + def test_attachment_anonymization_command_content_type_option(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, file.name, content_type=u'type') + attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment) + self.assertEqual(attachment_finalization.content_type, u'type') + + def test_attachment_anonymization_command_debug_option(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, file.name, debug=u'debug') + attachment_finalization = AttachmentFinalization.objects.get(attachment=self.attachment) + self.assertEqual(attachment_finalization.debug, u'debug') + + def test_attachment_anonymization_command_with_existing_attachment_finalization(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, file.name) + attachment_finalization1 = AttachmentFinalization.objects.get(attachment=self.attachment) + call_command(u'attachment_anonymization', self.attachment.pk, file.name) + attachment_finalization2 = AttachmentFinalization.objects.get(attachment=self.attachment) + self.assertEqual(attachment_finalization1.pk, attachment_finalization2.pk) + + def test_attachment_anonymization_command_force_option(self): + with open(os.path.join(self.tempdir.path, u'myfile.txt'), u'w') as file: + call_command(u'attachment_anonymization', self.attachment.pk, file.name) + attachment_finalization1 = AttachmentFinalization.objects.get(attachment=self.attachment) + call_command(u'attachment_anonymization', self.attachment.pk, file.name, force=True) + attachment_finalization2 = AttachmentFinalization.objects.get(attachment=self.attachment) + self.assertNotEqual(attachment_finalization1.pk, attachment_finalization2.pk) diff --git a/misc/anonymization.md b/misc/anonymization.md index 2807c28ba..8f110ec4b 100644 --- a/misc/anonymization.md +++ b/misc/anonymization.md @@ -92,3 +92,34 @@ Computed Properties: *\* Features that are marked ~~strikethrough~~ are not implemented yet.* + + +## Anonymization +You can manually anonymize `Attachment` using management command: + +``` +manage.py attachment_anonymization attachment [options] [file] + +Options: + -v VERBOSITY, --verbosity=VERBOSITY + Verbosity level; 0=minimal output, 1=normal output, + 2=verbose output, 3=very verbose output + --settings=SETTINGS The Python path to a settings module, e.g. + "myproject.settings.main". If this isn't provided, the + DJANGO_SETTINGS_MODULE environment variable will be + used. + --pythonpath=PYTHONPATH + A directory to add to the Python path, e.g. + "/home/djangoprojects/myproject". + --traceback Raise on exception + --no-color Don't colorize the command output. + -f FILENAME, --file=FILENAME + define file path + --content_type=CONTENT_TYPE + define content type of file + --debug=DEBUG add debug message + --force overwrite an existing successful + AttachmentFinalization + --version show program's version number and exit + -h, --help show this help message and exit +```