tangled
alpha
login
or
join now
hello.j23n.com
/
deletemepleaseeu
Have companies delete your personal data
0
fork
atom
overview
issues
pulls
pipelines
Compare changes
Choose any two refs to compare.
base:
main
feat/improve-deletionrequest-admin-layout
bug/linking-incoming-messages
no tags found
compare:
main
feat/improve-deletionrequest-admin-layout
bug/linking-incoming-messages
no tags found
go
+62
-26
2 changed files
expand all
collapse all
unified
split
app
badactors
admin
deletion_request.py
models.py
+38
-16
app/badactors/admin/deletion_request.py
···
5
5
from django.contrib import admin, messages
6
6
from django.shortcuts import redirect
7
7
from django.urls import reverse, path
8
8
+
from django.utils import formats
8
9
from django.utils.html import format_html
9
10
from django.utils.translation import ngettext
10
11
···
42
43
43
44
class PendingEmailInline(admin.TabularInline):
44
45
model = PendingEmail
45
45
-
fields = ["subject", "status", "created_at", "updated_at"]
46
46
-
readonly_fields = ["subject", "status", "created_at", "updated_at"]
46
46
+
fields = ["link", "created_at", "subject", "status", "updated_at"]
47
47
+
readonly_fields = ["link", "subject", "status", "created_at", "updated_at"]
47
48
extra = 0
48
49
can_delete = False
49
50
51
51
+
def link(self, obj):
52
52
+
if obj.pk:
53
53
+
link = reverse("admin:badactors_pendingemail_change", args=[obj.pk])
54
54
+
return format_html('<a href="{}">PE-{}</a>', link, obj.pk)
55
55
+
return "-"
56
56
+
57
57
+
link.short_description = "PendingEmail"
58
58
+
59
59
+
def get_queryset(self, request):
60
60
+
qs = super().get_queryset(request)
61
61
+
return qs.filter(
62
62
+
status__in=[
63
63
+
PendingEmail.Status.DRAFT,
64
64
+
PendingEmail.Status.READY,
65
65
+
PendingEmail.Status.APPROVED,
66
66
+
]
67
67
+
)
68
68
+
50
69
def has_add_permission(self, request, obj=None):
51
70
return False
52
71
···
55
74
template = "admin/badactors/deletionrequest/conversationitem_inline.html"
56
75
model = ConversationItem
57
76
fields = [
77
77
+
"display_message_link",
58
78
"display_message_date",
79
79
+
"display_message_subject",
59
80
"direction",
60
60
-
"display_message_link",
61
81
"message_type",
62
62
-
"requires_manual_review",
63
63
-
"notes",
64
82
]
65
65
-
readonly_fields = ["display_message_date", "direction", "display_message_link"]
83
83
+
readonly_fields = [
84
84
+
"display_message_date",
85
85
+
"display_message_subject",
86
86
+
"direction",
87
87
+
"display_message_link",
88
88
+
]
66
89
can_delete = False
67
90
extra = 0
68
91
ordering = ["sequence"]
69
92
93
93
+
def display_message_subject(self, obj):
94
94
+
if obj.message and obj.message.subject:
95
95
+
return obj.message.subject
96
96
+
return "-"
97
97
+
98
98
+
display_message_subject.short_description = "Subject"
99
99
+
70
100
def display_message_date(self, obj):
71
101
"""Show message timestamp."""
72
102
if obj.message and obj.message.processed:
73
73
-
return obj.message.processed.strftime("%Y-%m-%d %H:%M")
103
103
+
return formats.date_format(obj.message.processed, "DATETIME_FORMAT")
74
104
return "-"
75
105
76
106
display_message_date.short_description = "Date"
···
84
114
85
115
display_message_link.short_description = "Message"
86
116
87
87
-
def formfield_for_dbfield(self, db_field, request, **kwargs):
88
88
-
"""Customize form fields."""
89
89
-
if db_field.name == "notes":
90
90
-
kwargs["widget"] = admin.widgets.AdminTextareaWidget(
91
91
-
attrs={"rows": 2, "cols": 40}
92
92
-
)
93
93
-
return super().formfield_for_dbfield(db_field, request, **kwargs)
94
94
-
95
117
96
118
class ConversationClassificationInline(admin.StackedInline):
97
119
model = ConversationClassification
···
128
150
search_fields = ["company__name", "status", "uuid", "user_email_address"]
129
151
actions = ["send_confirmation_emails_to_users", "send_gdpr_request"]
130
152
inlines = [
131
131
-
LetterOfAuthorityInline,
132
153
PendingEmailInline,
133
154
ConversationItemInline,
134
155
ConversationClassificationInline,
156
156
+
LetterOfAuthorityInline,
135
157
]
136
158
137
159
def display_company(self, obj):
+24
-10
app/badactors/models.py
···
347
347
def __str__(self):
348
348
return f"ConversationItem #{self.sequence} for {self.deletion_request}"
349
349
350
350
+
350
351
@receiver(message_received)
351
352
def add_incoming_message_to_dr(sender, message: Message, **kwargs):
352
353
to_addresses = message.to_addresses
353
354
try:
354
354
-
uuids = [address.split("@")[0] for address in to_addresses if "@deletemeplease.eu" in address]
355
355
+
uuids = [
356
356
+
address.split("@")[0]
357
357
+
for address in to_addresses
358
358
+
if "@deletemeplease.eu" in address
359
359
+
]
355
360
except (AttributeError, TypeError):
356
356
-
logger.error(f"Couldn't parse local portion of email addresses {to_addresses}. Aborting")
361
361
+
logger.error(
362
362
+
f"Couldn't parse local portion of email addresses {to_addresses}. Aborting"
363
363
+
)
357
364
return
358
365
359
366
try:
360
367
drs = DeletionRequest.objects.filter(uuid__in=uuids)
361
361
-
except ValidationError:
362
362
-
logger.warning(f"Found no matching DeletionRequest for incoming email {message} given UUIDs {uuids}. Aborting")
363
363
-
return
368
368
+
except ValidationError:
369
369
+
logger.warning(
370
370
+
f"Found no matching DeletionRequest for incoming email {message} given UUIDs {uuids}. Aborting"
371
371
+
)
372
372
+
return
364
373
365
374
if not drs.exists():
366
366
-
logger.warning(f"Found no matching DeletionRequest for incoming email {message} given UUIDs {uuids}. Aborting")
375
375
+
logger.warning(
376
376
+
f"Found no matching DeletionRequest for incoming email {message} given UUIDs {uuids}. Aborting"
377
377
+
)
367
378
return
368
379
if drs.count() > 1:
369
369
-
logger.error(f"Found multiple matching DeletionRequests for incoming email {message} given UUIDs {uuids}. Aborting")
380
380
+
logger.error(
381
381
+
f"Found multiple matching DeletionRequests for incoming email {message} given UUIDs {uuids}. Aborting"
382
382
+
)
370
383
return
371
384
372
385
ConversationItem.objects.create(
373
373
-
deletion_request = drs.first(),
374
374
-
message = message,
375
375
-
direction = MessageDirection.INCOMING.value
386
386
+
deletion_request=drs.first(),
387
387
+
message=message,
388
388
+
direction=MessageDirection.INCOMING.value,
376
389
)
377
390
391
391
+
378
392
class DeletionRequest(models.Model):
379
393
"""
380
394
Model to store information about deletion requests.