From c6da84c7f8889079ff92c20023b7fdc5d0142023 Mon Sep 17 00:00:00 2001 From: OhMaley Date: Thu, 26 Dec 2024 11:47:39 -0500 Subject: [PATCH 1/3] Set is_active to False when deleting a user --- src/apps/profiles/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/apps/profiles/models.py b/src/apps/profiles/models.py index 66918e173..991b4451f 100644 --- a/src/apps/profiles/models.py +++ b/src/apps/profiles/models.py @@ -207,6 +207,7 @@ def delete(self, *args, **kwargs): # Mark the user as deleted self.is_deleted = True self.deleted_at = now() + self.is_active = False # Anonymize or removed personal data user_email = self.email # keep track of the email for the end of the procedure From f1d29789bdd4cb44f49da3f7e61bd79aa766250b Mon Sep 17 00:00:00 2001 From: OhMaley Date: Thu, 26 Dec 2024 12:05:48 -0500 Subject: [PATCH 2/3] change the email sending method and populate the missing txt files --- src/apps/profiles/views.py | 45 ++++--- .../emails/template_delete_account.txt | 24 ++++ .../template_delete_account_confirmed.txt | 7 ++ .../emails/template_delete_account_notice.txt | 118 ++++++++++++++++++ 4 files changed, 176 insertions(+), 18 deletions(-) create mode 100644 src/templates/profiles/emails/template_delete_account.txt create mode 100644 src/templates/profiles/emails/template_delete_account_confirmed.txt create mode 100644 src/templates/profiles/emails/template_delete_account_notice.txt diff --git a/src/apps/profiles/views.py b/src/apps/profiles/views.py index f5b7f5863..f8c090038 100644 --- a/src/apps/profiles/views.py +++ b/src/apps/profiles/views.py @@ -28,6 +28,7 @@ from datasets.models import Data, DataGroup from tasks.models import Task from forums.models import Post +from utils.email import codalab_send_mail class LoginView(auth_views.LoginView): @@ -110,20 +111,21 @@ def activateEmail(request, user, to_email): def send_delete_account_confirmation_mail(request, user): - mail_subject = 'Confirm Your Account Deletion Request' - message = render_to_string('profiles/emails/template_delete_account.html', { + context = { 'user': user, 'domain': get_current_site(request).domain, 'uid': urlsafe_base64_encode(force_bytes(user.pk)), 'token': default_token_generator.make_token(user), 'protocol': 'https' if request.is_secure() else 'http' - }) - email = EmailMessage(mail_subject, message, to=[user.email]) - if email.send(): - messages.success(request, f'Dear {user.username}, please go to your email inbox and click on \ - the link to complete the deletion process. *Note: Check your spam folder.') - else: - messages.error(request, f'Problem sending confirmation email.') + } + codalab_send_mail( + context_data=context, + subject=f'Confirm Your Account Deletion Request', + html_file="profiles/emails/template_delete_account.html", + text_file="profiles/emails/template_delete_account.txt", + to_email=[user.email] + ) + messages.success(request, f'Dear {user.username}, please go to your email inbox and click on the link to complete the deletion process. *Note: Check your spam folder.') def send_user_deletion_notice_to_admin(user): @@ -140,8 +142,7 @@ def send_user_deletion_notice_to_admin(user): queues = user.queues.all() posts = Post.objects.filter(posted_by=user) - mail_subject = f'Notice: user {user.username} removed his account' - message = render_to_string('profiles/emails/template_delete_account_notice.html', { + context = { 'user': user, 'organizations': organizations, 'competitions_organizer': competitions_organizer, @@ -152,16 +153,24 @@ def send_user_deletion_notice_to_admin(user): 'tasks': tasks, 'queues': queues, 'posts': posts - }) - email = EmailMessage(mail_subject, message, to=admin_emails) - email.send() + } + codalab_send_mail( + context_data=context, + subject=f'Notice: user {user.username} removed his account', + html_file="profiles/emails/template_delete_account_notice.html", + text_file="profiles/emails/template_delete_account_notice.txt", + to_email=admin_emails + ) def send_user_deletion_confirmed(email): - mail_subject = f'Codabench: your account has been successfully removed' - message = render_to_string('profiles/emails/template_delete_account_confirmed.html') - email = EmailMessage(mail_subject, message, to=[email]) - email.send() + codalab_send_mail( + context_data={}, + subject=f'Codabench: your account has been successfully removed', + html_file="profiles/emails/template_delete_account_confirmed.html", + text_file="profiles/emails/template_delete_account_confirmed.txt", + to_email=[email] + ) def delete(request, uidb64, token): diff --git a/src/templates/profiles/emails/template_delete_account.txt b/src/templates/profiles/emails/template_delete_account.txt new file mode 100644 index 000000000..536567411 --- /dev/null +++ b/src/templates/profiles/emails/template_delete_account.txt @@ -0,0 +1,24 @@ +{% extends 'emails/base_email.html' %} + +{% block content %} +

We have received your request to delete your account.

+

To proceed with the deletion of your account, please confirm your request by clicking the link below:

+

{{ protocol }}://{{ domain }}{% url 'accounts:delete' uidb64=uid token=token %}

+ +
+ +

Important Information:

+ + +
+ +

If you did not request this action or have changed your mind, you can safely ignore this email, and your account will remain intact.

+ +
+ +

Thank you for being part of our community.

+{% endblock %} diff --git a/src/templates/profiles/emails/template_delete_account_confirmed.txt b/src/templates/profiles/emails/template_delete_account_confirmed.txt new file mode 100644 index 000000000..690b2dff3 --- /dev/null +++ b/src/templates/profiles/emails/template_delete_account_confirmed.txt @@ -0,0 +1,7 @@ +{% extends 'emails/base_email.html' %} + +{% block content %} +

Your account has been successfully removed. Thank you for being part of our community.

+
+

If you change your mind, you can create a new account at any time. We'd be happy to welcome you back!

+{% endblock %} diff --git a/src/templates/profiles/emails/template_delete_account_notice.txt b/src/templates/profiles/emails/template_delete_account_notice.txt new file mode 100644 index 000000000..374511567 --- /dev/null +++ b/src/templates/profiles/emails/template_delete_account_notice.txt @@ -0,0 +1,118 @@ +{% extends 'emails/base_email.html' %} + +{% block content %} +

User account deletion notice

+ +

You are receiving this notice because your are an administrator of the platform.

+ +
+ +

The following user has removed their account:

+ + +
+ +

Summary

+ + + +

Details

+ +

Organizations the user is part of:

+ + +

Competitions the user is the owner:

+ + +

Competitions the user participated in:

+ + +

Submissions from the user:

+ + +

Data created by the user

+ + +

DataGroups created by the user

+ + +

Tasks created by the user

+ + +

Queues created by the user

+ + +

Posts posted by the user

+ + +{% endblock %} From 84b0f4dec8621fbff83761ba0ccf19511336e464 Mon Sep 17 00:00:00 2001 From: OhMaley Date: Thu, 26 Dec 2024 16:45:34 -0500 Subject: [PATCH 3/3] add a checkbox to show/hide deleted users in the list of participant modal --- src/apps/api/views/competitions.py | 2 +- .../riot/competitions/detail/participant_manager.tag | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/apps/api/views/competitions.py b/src/apps/api/views/competitions.py index cf22b444e..793e4efda 100644 --- a/src/apps/api/views/competitions.py +++ b/src/apps/api/views/competitions.py @@ -795,7 +795,7 @@ class CompetitionParticipantViewSet(ModelViewSet): queryset = CompetitionParticipant.objects.all() serializer_class = CompetitionParticipantSerializer filter_backends = (DjangoFilterBackend, SearchFilter) - filter_fields = ('user__username', 'user__email', 'status', 'competition') + filter_fields = ('user__username', 'user__email', 'status', 'competition', 'user__is_deleted') search_fields = ('user__username', 'user__email',) def get_queryset(self): diff --git a/src/static/riot/competitions/detail/participant_manager.tag b/src/static/riot/competitions/detail/participant_manager.tag index 0043b4a26..55cde959e 100644 --- a/src/static/riot/competitions/detail/participant_manager.tag +++ b/src/static/riot/competitions/detail/participant_manager.tag @@ -12,6 +12,10 @@ +
+ + +
Email all participants
@@ -140,6 +144,11 @@ filters.status = status } + let show_deleted_users = self.refs.participant_show_deleted.checked + if (show_deleted_users !== null && show_deleted_users === false) { + filters.user__is_deleted = show_deleted_users + } + CODALAB.api.get_participants(filters) .done(participants => { self.participants = participants