0
0
Fork 0
mirror of https://github.com/healthchecks/healthchecks.git synced 2025-04-17 18:22:33 +00:00

Update the senddeletionscheduled command to notify team members too

This commit is contained in:
Pēteris Caune 2023-07-14 09:51:36 +03:00
parent c4851f3b49
commit 05742f42f9
No known key found for this signature in database
GPG key ID: E28D7679E9A9EDE2
4 changed files with 73 additions and 32 deletions

View file

@ -3,6 +3,7 @@ from __future__ import annotations
import time import time
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from django.utils.timezone import now from django.utils.timezone import now
@ -16,23 +17,35 @@ class Command(BaseCommand):
def pause(self): def pause(self):
time.sleep(1) time.sleep(1)
def members(self, user):
q = User.objects.filter(memberships__project__owner=user)
q = q.exclude(last_login=None)
return q.order_by("email")
def handle(self, *args, **options): def handle(self, *args, **options):
q = Profile.objects.order_by("id") q = Profile.objects.order_by("id")
q = q.filter(deletion_scheduled_date__gt=now()) q = q.filter(deletion_scheduled_date__gt=now())
sent = 0 sent = 0
for profile in q: for profile in q:
self.stdout.write(f"Sending notice to {profile.user.email}") recipients = [profile.user.email]
# Include team members in the recipient list too:
for u in self.members(profile.user):
recipients.append(u.email)
ctx = { for recipient in recipients:
"email": profile.user.email, role = "owner" if recipient == profile.user.email else "member"
"support_email": settings.SUPPORT_EMAIL, self.stdout.write(f"Sending notice to {recipient} ({role})")
"deletion_scheduled_date": profile.deletion_scheduled_date, ctx = {
} "owner_email": profile.user.email,
emails.deletion_scheduled(profile.user.email, ctx) "num_checks": profile.num_checks_used(),
sent += 1 "support_email": settings.SUPPORT_EMAIL,
"deletion_scheduled_date": profile.deletion_scheduled_date,
}
emails.deletion_scheduled(recipient, ctx)
sent += 1
# Throttle so we don't send too many emails at once: # Throttle so we don't send too many emails at once:
self.pause() self.pause()
return f"Done!\nNotices sent: {sent}\n" return f"Done!\nNotices sent: {sent}\n"

View file

@ -8,6 +8,7 @@ from django.core import mail
from django.utils.timezone import now from django.utils.timezone import now
from hc.accounts.management.commands.senddeletionscheduled import Command from hc.accounts.management.commands.senddeletionscheduled import Command
from hc.api.models import Check
from hc.test import BaseTestCase from hc.test import BaseTestCase
@ -16,19 +17,14 @@ def counts(result):
return [int(s) for s in re.findall(r"\d+", result)] return [int(s) for s in re.findall(r"\d+", result)]
class SendDeletionNoticesTestCase(BaseTestCase): class SendDeletionScheduledTestCase(BaseTestCase):
def test_it_skips_profiles_with_deletion_scheduled_date_not_set(self):
cmd = Command(stdout=Mock())
cmd.pause = Mock() # don't pause for 1s
result = cmd.handle()
self.assertEqual(counts(result), [0])
self.assertEqual(len(mail.outbox), 0)
def test_it_sends_notice(self): def test_it_sends_notice(self):
self.profile.deletion_scheduled_date = now() + td(days=31) self.profile.deletion_scheduled_date = now() + td(days=31)
self.profile.save() self.profile.save()
Check.objects.create(project=self.project)
Check.objects.create(project=self.project)
cmd = Command(stdout=Mock()) cmd = Command(stdout=Mock())
cmd.pause = Mock() # don't pause for 1s cmd.pause = Mock() # don't pause for 1s
@ -37,6 +33,33 @@ class SendDeletionNoticesTestCase(BaseTestCase):
email = mail.outbox[0] email = mail.outbox[0]
self.assertEqual(email.subject, "Account Deletion Warning") self.assertEqual(email.subject, "Account Deletion Warning")
self.assertEqual(email.to[0], "alice@example.org")
self.assertIn("Owner: alice@example.org", email.body)
self.assertIn("Number of checks in the account: 2", email.body)
def test_it_sends_notice_to_team_members(self):
self.profile.deletion_scheduled_date = now() + td(days=31)
self.profile.save()
self.bob.last_login = now()
self.bob.save()
cmd = Command(stdout=Mock())
cmd.pause = Mock() # don't pause for 1s
result = cmd.handle()
self.assertEqual(counts(result), [2])
self.assertEqual(mail.outbox[0].to[0], "alice@example.org")
self.assertEqual(mail.outbox[1].to[0], "bob@example.org")
def test_it_skips_profiles_with_deletion_scheduled_date_not_set(self):
cmd = Command(stdout=Mock())
cmd.pause = Mock() # don't pause for 1s
result = cmd.handle()
self.assertEqual(counts(result), [0])
self.assertEqual(len(mail.outbox), 0)
def test_it_skips_profiles_with_deletion_scheduled_date_in_past(self): def test_it_skips_profiles_with_deletion_scheduled_date_in_past(self):
self.profile.deletion_scheduled_date = now() - td(minutes=1) self.profile.deletion_scheduled_date = now() - td(minutes=1)

View file

@ -2,16 +2,17 @@
{% load hc_extras %} {% load hc_extras %}
{% block content %} {% block content %}
Hello,<br /><br /> Hello,<br />
<br />
Your {% site_name %} account is The {% site_name %} account registered to <strong>{{ owner_email }}</strong>
<strong>scheduled for deletion on {{ deletion_scheduled_date.date }}</strong>. is scheduled for deletion on <strong>{{ deletion_scheduled_date.date }}</strong>.<br />
<br />
<br /><br /> Account details:<br />
If you wish to keep your account, please contact us at {{ support_email}} as Owner: <strong>{{ owner_email }}</strong><br />
soon as possible. Number of checks in the account: <strong>{{ num_checks }}</strong><br />
<br />
<br /><br /> To prevent deletion, please contact us at {{ support_email}} as soon as possible.<br />
<br />
Sincerely,<br /> Sincerely,<br />
The {% site_name %} Team The {% site_name %} Team
{% endblock %} {% endblock %}

View file

@ -1,10 +1,14 @@
{% load hc_extras %} {% load hc_extras %}
Hello, Hello,
Your {% site_name %} account is scheduled for deletion on {{ deletion_scheduled_date.date }}. The {% site_name %} account registered to {{ owner_email }} is scheduled for deletion
on {{ deletion_scheduled_date.date }}.
If you wish to keep your account, please contact us at {{ support_email}} as Account details:
soon as possible. Owner: {{ owner_email }}
Number of checks in the account: {{ num_checks }}
To prevent deletion, please contact us at {{ support_email}} as soon as possible.
-- --
Sincerely, Sincerely,