django-db-anonymiser 0.1.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_db_anonymiser/db_anonymiser/management/commands/dump_and_anonymise.py +19 -0
- django_db_anonymiser/db_anonymiser/tests/test_command.py +32 -0
- {django_db_anonymiser-0.1.0.dist-info → django_db_anonymiser-0.2.1.dist-info}/METADATA +5 -4
- {django_db_anonymiser-0.1.0.dist-info → django_db_anonymiser-0.2.1.dist-info}/RECORD +5 -5
- {django_db_anonymiser-0.1.0.dist-info → django_db_anonymiser-0.2.1.dist-info}/WHEEL +1 -1
|
@@ -23,10 +23,16 @@ class Command(BaseCommand):
|
|
|
23
23
|
action="store_true",
|
|
24
24
|
help="Skip uploading to S3.",
|
|
25
25
|
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--presign",
|
|
28
|
+
action="store_true",
|
|
29
|
+
help="Generates and logs a presigned URL for the uploaded file.",
|
|
30
|
+
)
|
|
26
31
|
|
|
27
32
|
def configure(self):
|
|
28
33
|
self.keep_local_dumpfile = False
|
|
29
34
|
self.skip_s3_upload = False
|
|
35
|
+
self.presign = False
|
|
30
36
|
self.dump_file_name = settings.DB_ANONYMISER_DUMP_FILE_NAME
|
|
31
37
|
self.temporary_dump_location = getattr(
|
|
32
38
|
settings,
|
|
@@ -63,11 +69,16 @@ class Command(BaseCommand):
|
|
|
63
69
|
|
|
64
70
|
if options["skip_s3_upload"]:
|
|
65
71
|
self.skip_s3_upload = True
|
|
72
|
+
|
|
73
|
+
if options["presign"]:
|
|
74
|
+
self.presign = True
|
|
66
75
|
|
|
67
76
|
try:
|
|
68
77
|
self.dump_anonymised_db()
|
|
69
78
|
self.write_to_s3()
|
|
70
79
|
logger.info("DB dump and anonymiser was successful!")
|
|
80
|
+
if self.presign:
|
|
81
|
+
self.generate_presigned_url()
|
|
71
82
|
finally:
|
|
72
83
|
self.cleanup()
|
|
73
84
|
|
|
@@ -93,6 +104,14 @@ class Command(BaseCommand):
|
|
|
93
104
|
self.temporary_dump_location, self.s3_bucket_name, self.dump_file_name
|
|
94
105
|
)
|
|
95
106
|
logger.info("Writing file to S3 complete")
|
|
107
|
+
|
|
108
|
+
def generate_presigned_url(self):
|
|
109
|
+
presigned = self.s3_client.generate_presigned_url(
|
|
110
|
+
'get_object',
|
|
111
|
+
Params={'Bucket': self.s3_bucket_name, 'Key': self.dump_file_name},
|
|
112
|
+
ExpiresIn=600
|
|
113
|
+
)
|
|
114
|
+
logger.info("Presigned URL: %s", presigned)
|
|
96
115
|
|
|
97
116
|
def cleanup(self):
|
|
98
117
|
if self.keep_local_dumpfile:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import os
|
|
2
|
+
from unittest.mock import ANY
|
|
2
3
|
from unittest.mock import patch
|
|
3
4
|
|
|
4
5
|
from django.conf import settings
|
|
@@ -8,6 +9,7 @@ from django.test import TransactionTestCase
|
|
|
8
9
|
|
|
9
10
|
import boto3
|
|
10
11
|
import pytest
|
|
12
|
+
import requests
|
|
11
13
|
from moto import mock_aws
|
|
12
14
|
|
|
13
15
|
|
|
@@ -88,3 +90,33 @@ class TestDumpAndAnonmyiseCommand(TransactionTestCase):
|
|
|
88
90
|
def test_dump_and_anonymise_keeps_local_file(self, mocked_os_remove):
|
|
89
91
|
call_command("dump_and_anonymise", keep_local_dumpfile=True)
|
|
90
92
|
assert not mocked_os_remove.called
|
|
93
|
+
|
|
94
|
+
@patch("django_db_anonymiser.db_anonymiser.management.commands.dump_and_anonymise.logger")
|
|
95
|
+
@patch("django_db_anonymiser.db_anonymiser.management.commands.dump_and_anonymise.Command.generate_presigned_url")
|
|
96
|
+
@patch(
|
|
97
|
+
"django_db_anonymiser.db_anonymiser.management.commands.dump_and_anonymise.os.remove"
|
|
98
|
+
)
|
|
99
|
+
def test_dump_and_anonymise_no_arguments(self, mocked_os_remove, mocked_presign, mocked_logger):
|
|
100
|
+
call_command("dump_and_anonymise")
|
|
101
|
+
bucket_contents = self.aws.list_objects(
|
|
102
|
+
Bucket=settings.DB_ANONYMISER_AWS_STORAGE_BUCKET_NAME
|
|
103
|
+
).get("Contents", [])
|
|
104
|
+
assert bucket_contents[0]["Key"] == settings.DB_ANONYMISER_DUMP_FILE_NAME
|
|
105
|
+
mocked_os_remove.assert_called_with(
|
|
106
|
+
f"/tmp/{settings.DB_ANONYMISER_DUMP_FILE_NAME}"
|
|
107
|
+
)
|
|
108
|
+
mocked_presign.assert_not_called()
|
|
109
|
+
mocked_logger.info.assert_any_call("DB dump and anonymiser was successful!")
|
|
110
|
+
mocked_logger.info.assert_any_call("Writing anonymised dumpfile to temporary location %s", settings.DB_ANONYMISER_DUMP_FILE_NAME)
|
|
111
|
+
mocked_logger.info.assert_any_call("Writing file to S3 complete")
|
|
112
|
+
|
|
113
|
+
@patch("django_db_anonymiser.db_anonymiser.management.commands.dump_and_anonymise.logger")
|
|
114
|
+
def test_dump_and_anonymise_with_presign(self, mocked_logger):
|
|
115
|
+
call_command("dump_and_anonymise", presign=True)
|
|
116
|
+
bucket_contents = self.aws.list_objects(
|
|
117
|
+
Bucket=settings.DB_ANONYMISER_AWS_STORAGE_BUCKET_NAME
|
|
118
|
+
).get("Contents", [])
|
|
119
|
+
assert bucket_contents[0]["Key"] == settings.DB_ANONYMISER_DUMP_FILE_NAME
|
|
120
|
+
mocked_logger.info.assert_any_call("Presigned URL: %s", ANY)
|
|
121
|
+
presigned_url = mocked_logger.info.call_args_list[6][0][1]
|
|
122
|
+
assert requests.get(presigned_url).status_code == 200
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: django-db-anonymiser
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Django app to create configurable anonymised DB dumps.
|
|
5
5
|
Author: Brendan Smith
|
|
6
6
|
Author-email: brendan.smith@digital.trade.gov.uk
|
|
@@ -16,6 +16,7 @@ Requires-Dist: django-environ (>=0.12.0,<0.13.0)
|
|
|
16
16
|
Requires-Dist: faker (>=4.18.0)
|
|
17
17
|
Requires-Dist: psycopg2-binary (>=2.9.10,<3.0.0)
|
|
18
18
|
Requires-Dist: pymysql (>=1.1.2,<2.0.0)
|
|
19
|
+
Requires-Dist: pyyaml (==6.0.2)
|
|
19
20
|
Description-Content-Type: text/markdown
|
|
20
21
|
|
|
21
22
|
# django-db-anonymiser
|
|
@@ -42,7 +43,7 @@ because it is unmaintained.
|
|
|
42
43
|
## Getting started
|
|
43
44
|
|
|
44
45
|
- Add `faker>=4.18.0`, `boto3>=1.26.17` to python requirements; it is assumed python/psycopg and co are already installed.
|
|
45
|
-
- Either add this github repository as a submodule to your django application named `django_db_anonymiser` or install the python package (django-db-anonymiser)[] from PyPI.
|
|
46
|
+
- Either add this github repository as a submodule to your django application named `django_db_anonymiser` or install the python package (django-db-anonymiser)[https://pypi.org/project/django-db-anonymiser/] from PyPI.
|
|
46
47
|
- Add `django_db_anonymiser.db_anonymiser` to `INSTALLED_APPS`
|
|
47
48
|
- Set the following django settings;
|
|
48
49
|
- `DB_ANONYMISER_CONFIG_LOCATION` - the location of your anonymisation yaml file
|
|
@@ -56,7 +57,7 @@ because it is unmaintained.
|
|
|
56
57
|
|
|
57
58
|
For local unit testing from the root of the repository run:
|
|
58
59
|
|
|
59
|
-
$ poetry run pytest
|
|
60
|
+
$ poetry run pytest django_db_anonymiser
|
|
60
61
|
|
|
61
62
|
**Note:** Currently for full test coverage, it is necessary to run tests in circleci, where we spin up a postgres db and test
|
|
62
63
|
the `db_anonymiser` command directly
|
|
@@ -92,7 +93,7 @@ _Note: Make sure your Pull Request (PR) is approved and contains the version upg
|
|
|
92
93
|
poetry publish
|
|
93
94
|
```
|
|
94
95
|
|
|
95
|
-
Check the [PyPI Release history](https://pypi.org/project/
|
|
96
|
+
Check the [PyPI Release history](https://pypi.org/project/django-db-anonymiser/#history) to make sure the package has been updated.
|
|
96
97
|
|
|
97
98
|
For an optional manual check, install the package locally and test everything works as expected.
|
|
98
99
|
|
|
@@ -32,9 +32,9 @@ django_db_anonymiser/db_anonymiser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQe
|
|
|
32
32
|
django_db_anonymiser/db_anonymiser/faker.py,sha256=5X8tH_MAMtrsg248waXMSXTkoacMosqQlkCSFjy_0pA,1729
|
|
33
33
|
django_db_anonymiser/db_anonymiser/management/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
django_db_anonymiser/db_anonymiser/management/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
django_db_anonymiser/db_anonymiser/management/commands/dump_and_anonymise.py,sha256=
|
|
36
|
-
django_db_anonymiser/db_anonymiser/tests/test_command.py,sha256=
|
|
35
|
+
django_db_anonymiser/db_anonymiser/management/commands/dump_and_anonymise.py,sha256=kvocsusmjuBeBKfKE9xg9k3MdnY6hUBT__jc6Q2HHYc,4339
|
|
36
|
+
django_db_anonymiser/db_anonymiser/tests/test_command.py,sha256=J6_KF59S-DBtOx5yumP1Y1LRYU2jR78R0-oOupEflB0,5481
|
|
37
37
|
django_db_anonymiser/db_anonymiser/tests/test_faker.py,sha256=gvrOpSlWDjr4ajLyN5BEhxtkxO7_zls-CP04EolFFV4,3197
|
|
38
|
-
django_db_anonymiser-0.1.
|
|
39
|
-
django_db_anonymiser-0.1.
|
|
40
|
-
django_db_anonymiser-0.1.
|
|
38
|
+
django_db_anonymiser-0.2.1.dist-info/METADATA,sha256=8fJ2QNHGfe4vSSY56VGky_wKe2Z2rE247APT1V_BMbM,4667
|
|
39
|
+
django_db_anonymiser-0.2.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
40
|
+
django_db_anonymiser-0.2.1.dist-info/RECORD,,
|