mirror of
https://github.com/healthchecks/healthchecks.git
synced 2025-04-11 15:51:19 +00:00
Add Channel.email property
It replaces: * Channel.email_value * Channel.email_notify_up * Channel.email_notify_down
This commit is contained in:
parent
ccc8faa953
commit
dcf9f327f6
9 changed files with 45 additions and 49 deletions
hc
accounts/management/commands
api
front
templates/front
|
@ -39,7 +39,7 @@ class Command(BaseCommand):
|
|||
f"please contact {settings.SUPPORT_EMAIL} ASAP."
|
||||
)
|
||||
for channel in Channel.objects.filter(project__owner_id=profile.user_id):
|
||||
if channel.kind == "email" and channel.email_value in skip_emails:
|
||||
if channel.kind == "email" and channel.email.value in skip_emails:
|
||||
continue
|
||||
|
||||
dummy = Check(name=name, desc=desc, status="down", project=channel.project)
|
||||
|
|
|
@ -219,7 +219,7 @@ class ChannelsAdmin(admin.ModelAdmin):
|
|||
def project_(self, obj):
|
||||
url = self.view_on_site(obj)
|
||||
name = escape(obj.project_name or "Default")
|
||||
email = escape(obj.email)
|
||||
email = escape(obj.owner_email)
|
||||
return f"{email} › <a href='{url}'>{name}</a>"
|
||||
|
||||
def time(self, obj):
|
||||
|
@ -230,7 +230,7 @@ class ChannelsAdmin(admin.ModelAdmin):
|
|||
qs = super().get_queryset(request)
|
||||
qs = qs.annotate(project_code=F("project__code"))
|
||||
qs = qs.annotate(project_name=F("project__name"))
|
||||
qs = qs.annotate(email=F("project__owner__email"))
|
||||
qs = qs.annotate(owner_email=F("project__owner__email"))
|
||||
return qs
|
||||
|
||||
def view_on_site(self, obj):
|
||||
|
|
|
@ -727,6 +727,20 @@ class PhoneConf(BaseModel):
|
|||
notify_down: bool | None = Field(None, alias="down")
|
||||
|
||||
|
||||
class EmailConf(BaseModel):
|
||||
value: str
|
||||
notify_up: bool = Field(alias="up")
|
||||
notify_down: bool = Field(alias="down")
|
||||
|
||||
@classmethod
|
||||
def load(cls, data: Any) -> EmailConf:
|
||||
# Is it a plain email address?
|
||||
if not data.startswith("{"):
|
||||
return cls.model_validate({"value": data, "up": True, "down": True})
|
||||
|
||||
return super().model_validate_json(data)
|
||||
|
||||
|
||||
class Channel(models.Model):
|
||||
name = models.CharField(max_length=100, blank=True)
|
||||
code = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
|
||||
|
@ -745,7 +759,7 @@ class Channel(models.Model):
|
|||
if self.name:
|
||||
return self.name
|
||||
if self.kind == "email":
|
||||
return "Email to %s" % self.email_value
|
||||
return "Email to %s" % self.email.value
|
||||
elif self.kind == "sms":
|
||||
return "SMS to %s" % self.phone.value
|
||||
elif self.kind == "slack":
|
||||
|
@ -779,7 +793,7 @@ class Channel(models.Model):
|
|||
args = [self.code, self.make_token()]
|
||||
verify_link = reverse("hc-verify-email", args=args)
|
||||
verify_link = settings.SITE_ROOT + verify_link
|
||||
emails.verify_email(self.email_value, {"verify_link": verify_link})
|
||||
emails.verify_email(self.email.value, {"verify_link": verify_link})
|
||||
|
||||
def get_unsub_link(self) -> str:
|
||||
signer = TimestampSigner(salt="alerts")
|
||||
|
@ -977,28 +991,8 @@ class Channel(models.Model):
|
|||
return doc["board_name"], doc["list_name"]
|
||||
|
||||
@property
|
||||
def email_value(self) -> str:
|
||||
assert self.kind == "email"
|
||||
if not self.value.startswith("{"):
|
||||
return self.value
|
||||
|
||||
return self.json["value"]
|
||||
|
||||
@property
|
||||
def email_notify_up(self) -> bool:
|
||||
assert self.kind == "email"
|
||||
if not self.value.startswith("{"):
|
||||
return True
|
||||
|
||||
return self.json.get("up")
|
||||
|
||||
@property
|
||||
def email_notify_down(self) -> bool:
|
||||
assert self.kind == "email"
|
||||
if not self.value.startswith("{"):
|
||||
return True
|
||||
|
||||
return self.json.get("down")
|
||||
def email(self) -> EmailConf:
|
||||
return EmailConf.load(self.value)
|
||||
|
||||
@property
|
||||
def opsgenie_key(self) -> str:
|
||||
|
|
|
@ -25,7 +25,9 @@ class FlipModelTestCase(BaseTestCase):
|
|||
self.assertEqual(channels, [self.channel])
|
||||
|
||||
def test_select_channels_handles_noop(self) -> None:
|
||||
self.channel.value = json.dumps({"down": False})
|
||||
self.channel.value = json.dumps(
|
||||
{"value": "alice@example.org", "up": False, "down": False}
|
||||
)
|
||||
self.channel.save()
|
||||
|
||||
channels = self.flip.select_channels()
|
||||
|
|
|
@ -155,7 +155,7 @@ class Email(Transport):
|
|||
# If this email address has an associated account, include
|
||||
# a summary of projects the account has access to
|
||||
try:
|
||||
profile = Profile.objects.get(user__email=self.channel.email_value)
|
||||
profile = Profile.objects.get(user__email=self.channel.email.value)
|
||||
projects = list(profile.projects())
|
||||
except Profile.DoesNotExist:
|
||||
projects = None
|
||||
|
@ -170,13 +170,13 @@ class Email(Transport):
|
|||
"unsub_link": unsub_link,
|
||||
}
|
||||
|
||||
emails.alert(self.channel.email_value, ctx, headers)
|
||||
emails.alert(self.channel.email.value, ctx, headers)
|
||||
|
||||
def is_noop(self, check: Check) -> bool:
|
||||
if check.status == "down":
|
||||
return not self.channel.email_notify_down
|
||||
return not self.channel.email.notify_down
|
||||
else:
|
||||
return not self.channel.email_notify_up
|
||||
return not self.channel.email.notify_up
|
||||
|
||||
|
||||
class Shell(Transport):
|
||||
|
|
|
@ -39,9 +39,9 @@ class EditEmailTestCase(BaseTestCase):
|
|||
self.assertRedirects(r, self.channels_url)
|
||||
|
||||
self.channel.refresh_from_db()
|
||||
self.assertEqual(self.channel.email_value, "new@example.org")
|
||||
self.assertTrue(self.channel.email_notify_down)
|
||||
self.assertFalse(self.channel.email_notify_up)
|
||||
self.assertEqual(self.channel.email.value, "new@example.org")
|
||||
self.assertTrue(self.channel.email.notify_down)
|
||||
self.assertFalse(self.channel.email.notify_up)
|
||||
|
||||
# It should send a verification link
|
||||
email = mail.outbox[0]
|
||||
|
@ -58,9 +58,9 @@ class EditEmailTestCase(BaseTestCase):
|
|||
self.client.post(self.url, form)
|
||||
|
||||
self.channel.refresh_from_db()
|
||||
self.assertEqual(self.channel.email_value, "alerts@example.org")
|
||||
self.assertFalse(self.channel.email_notify_down)
|
||||
self.assertTrue(self.channel.email_notify_up)
|
||||
self.assertEqual(self.channel.email.value, "alerts@example.org")
|
||||
self.assertFalse(self.channel.email.notify_down)
|
||||
self.assertTrue(self.channel.email.notify_up)
|
||||
self.assertTrue(self.channel.email_verified)
|
||||
|
||||
# The email address did not change, so we should skip verification
|
||||
|
@ -73,7 +73,7 @@ class EditEmailTestCase(BaseTestCase):
|
|||
self.client.post(self.url, form)
|
||||
|
||||
self.channel.refresh_from_db()
|
||||
self.assertEqual(self.channel.email_value, "new@example.org")
|
||||
self.assertEqual(self.channel.email.value, "new@example.org")
|
||||
|
||||
@override_settings(EMAIL_USE_VERIFICATION=False)
|
||||
def test_it_hides_confirmation_needed_notice(self) -> None:
|
||||
|
@ -90,7 +90,7 @@ class EditEmailTestCase(BaseTestCase):
|
|||
self.assertRedirects(r, self.channels_url)
|
||||
|
||||
self.channel.refresh_from_db()
|
||||
self.assertEqual(self.channel.email_value, "dan@example.org")
|
||||
self.assertEqual(self.channel.email.value, "dan@example.org")
|
||||
|
||||
# Email should *not* have been sent
|
||||
self.assertEqual(len(mail.outbox), 0)
|
||||
|
@ -103,7 +103,7 @@ class EditEmailTestCase(BaseTestCase):
|
|||
self.assertRedirects(r, self.channels_url)
|
||||
|
||||
self.channel.refresh_from_db()
|
||||
self.assertEqual(self.channel.email_value, "alice@example.org")
|
||||
self.assertEqual(self.channel.email.value, "alice@example.org")
|
||||
|
||||
# Email should *not* have been sent
|
||||
self.assertEqual(len(mail.outbox), 0)
|
||||
|
|
|
@ -1255,7 +1255,7 @@ def email_form(request: HttpRequest, channel: Channel) -> HttpResponse:
|
|||
if request.method == "POST":
|
||||
form = forms.EmailForm(request.POST)
|
||||
if form.is_valid():
|
||||
if channel.disabled or form.cleaned_data["value"] != channel.email_value:
|
||||
if channel.disabled or form.cleaned_data["value"] != channel.email.value:
|
||||
channel.disabled = False
|
||||
|
||||
if not settings.EMAIL_USE_VERIFICATION:
|
||||
|
@ -1284,9 +1284,9 @@ def email_form(request: HttpRequest, channel: Channel) -> HttpResponse:
|
|||
else:
|
||||
form = forms.EmailForm(
|
||||
{
|
||||
"value": channel.email_value,
|
||||
"up": channel.email_notify_up,
|
||||
"down": channel.email_notify_down,
|
||||
"value": channel.email.value,
|
||||
"up": channel.email.notify_up,
|
||||
"down": channel.email.notify_down,
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -39,11 +39,11 @@
|
|||
{% endif %}
|
||||
<div class="channel-details-mini">
|
||||
{% if ch.kind == "email" %}
|
||||
Email to <span>{{ ch.email_value }}</span>
|
||||
{% if ch.email_notify_down and not ch.email_notify_up %}
|
||||
Email to <span>{{ ch.email.value }}</span>
|
||||
{% if ch.email.notify_down and not ch.email.notify_up %}
|
||||
(down only)
|
||||
{% endif %}
|
||||
{% if ch.email_notify_up and not ch.email_notify_down %}
|
||||
{% if ch.email.notify_up and not ch.email.notify_down %}
|
||||
(up only)
|
||||
{% endif %}
|
||||
{% elif ch.kind == "pd" %}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{% if event.channel.kind == "email" %}
|
||||
Sent email to {{ event.channel.email_value }}
|
||||
Sent email to {{ event.channel.email.value }}
|
||||
{% elif event.channel.kind == "slack" %}
|
||||
Sent Slack alert
|
||||
{% if event.channel.slack_channel %}
|
||||
|
|
Loading…
Add table
Reference in a new issue