Browse Source

Add ability to edit existing email integrations

pull/563/head
Pēteris Caune 3 years ago
parent
commit
2a9a544ddf
No known key found for this signature in database GPG Key ID: E28D7679E9A9EDE2
7 changed files with 167 additions and 30 deletions
  1. +1
    -0
      CHANGELOG.md
  2. +9
    -1
      hc/front/forms.py
  3. +1
    -1
      hc/front/tests/test_add_email.py
  4. +109
    -0
      hc/front/tests/test_edit_email.py
  5. +2
    -1
      hc/front/urls.py
  6. +42
    -26
      hc/front/views.py
  7. +3
    -1
      templates/front/channels.html

+ 1
- 0
CHANGELOG.md View File

@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file.
### Improvements
- Add /api/v1/badges/ endpoint (#552)
- Add ability to edit existing email integrations
### Bug Fixes
- Add handling for non-latin-1 characters in webhook headers


+ 9
- 1
hc/front/forms.py View File

@ -140,7 +140,7 @@ class AddPushoverForm(forms.Form):
return "%s|%s|%s" % (key, prio, prio_up)
class AddEmailForm(forms.Form):
class EmailForm(forms.Form):
error_css_class = "has-error"
value = forms.EmailField(max_length=100)
down = forms.BooleanField(required=False, initial=True)
@ -155,6 +155,14 @@ class AddEmailForm(forms.Form):
if not down and not up:
self.add_error("down", "Please select at least one.")
def to_json(self):
d = {
"value": self.cleaned_data["value"],
"up": self.cleaned_data["up"],
"down": self.cleaned_data["down"],
}
return json.dumps(d)
class AddUrlForm(forms.Form):
error_css_class = "has-error"


+ 1
- 1
hc/front/tests/test_add_email.py View File

@ -106,7 +106,7 @@ class AddEmailTestCase(BaseTestCase):
# Email should *not* have been sent
self.assertEqual(len(mail.outbox), 0)
def test_it_rejects_unchecked_up_and_dwon(self):
def test_it_rejects_unchecked_up_and_down(self):
form = {"value": "[email protected]"}
self.client.login(username="[email protected]", password="password")


+ 109
- 0
hc/front/tests/test_edit_email.py View File

@ -0,0 +1,109 @@
import json
from django.core import mail
from django.test.utils import override_settings
from hc.api.models import Channel
from hc.test import BaseTestCase
class EditEmailTestCase(BaseTestCase):
def setUp(self):
super().setUp()
self.channel = Channel(project=self.project, kind="email")
self.channel.value = json.dumps(
{"value": "[email protected]", "up": True, "down": True}
)
self.channel.email_verified = True
self.channel.save()
self.url = "/integrations/%s/edit/" % self.channel.code
def test_it_shows_form(self):
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertContains(r, "Get an email message when check goes up or down.")
self.assertContains(r, "[email protected]")
def test_it_saves_changes(self):
form = {"value": "[email protected]", "down": "true", "up": "false"}
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, form)
self.assertRedirects(r, self.channels_url)
self.channel.refresh_from_db()
self.assertEqual(self.channel.email_value, "[email protected]")
self.assertTrue(self.channel.email_notify_down)
self.assertFalse(self.channel.email_notify_up)
# It should send a verification link
email = mail.outbox[0]
self.assertTrue(email.subject.startswith("Verify email address on"))
self.assertEqual(email.to[0], "[email protected]")
def test_it_skips_verification_if_email_unchanged(self):
form = {"value": "[email protected]", "down": "false", "up": "true"}
self.client.login(username="[email protected]", password="password")
self.client.post(self.url, form)
self.channel.refresh_from_db()
self.assertEqual(self.channel.email_value, "[email protected]")
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
self.assertEqual(len(mail.outbox), 0)
def test_team_access_works(self):
form = {"value": "[email protected]", "down": "true", "up": "true"}
self.client.login(username="[email protected]", password="password")
self.client.post(self.url, form)
self.channel.refresh_from_db()
self.assertEqual(self.channel.email_value, "[email protected]")
@override_settings(EMAIL_USE_VERIFICATION=False)
def test_it_hides_confirmation_needed_notice(self):
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertNotContains(r, "Requires confirmation")
@override_settings(EMAIL_USE_VERIFICATION=False)
def test_it_auto_verifies_email(self):
form = {"value": "[email protected]", "down": "true", "up": "true"}
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, form)
self.assertRedirects(r, self.channels_url)
self.channel.refresh_from_db()
self.assertEqual(self.channel.email_value, "[email protected]")
# Email should *not* have been sent
self.assertEqual(len(mail.outbox), 0)
def test_it_auto_verifies_own_email(self):
form = {"value": "[email protected]", "down": "true", "up": "true"}
self.client.login(username="[email protected]", password="password")
r = self.client.post(self.url, form)
self.assertRedirects(r, self.channels_url)
self.channel.refresh_from_db()
self.assertEqual(self.channel.email_value, "[email protected]")
# Email should *not* have been sent
self.assertEqual(len(mail.outbox), 0)
def test_it_requires_rw_access(self):
self.bobs_membership.role = "r"
self.bobs_membership.save()
self.client.login(username="[email protected]", password="password")
r = self.client.get(self.url)
self.assertEqual(r.status_code, 403)

+ 2
- 1
hc/front/urls.py View File

@ -38,6 +38,7 @@ channel_urls = [
path("add_trello/settings/", views.trello_settings, name="hc-trello-settings"),
path("<uuid:code>/checks/", views.channel_checks, name="hc-channel-checks"),
path("<uuid:code>/name/", views.update_channel_name, name="hc-channel-name"),
path("<uuid:code>/edit/", views.edit_channel, name="hc-edit-channel"),
path("<uuid:code>/edit_webhook/", views.edit_webhook, name="hc-edit-webhook"),
path("<uuid:code>/test/", views.send_test_notification, name="hc-channel-test"),
path("<uuid:code>/remove/", views.remove_channel, name="hc-remove-channel"),
@ -55,7 +56,7 @@ project_urls = [
path("add_apprise/", views.add_apprise, name="hc-add-apprise"),
path("add_call/", views.add_call, name="hc-add-call"),
path("add_discord/", views.add_discord, name="hc-add-discord"),
path("add_email/", views.add_email, name="hc-add-email"),
path("add_email/", views.email_form, name="hc-add-email"),
path("add_linenotify/", views.add_linenotify, name="hc-add-linenotify"),
path("add_matrix/", views.add_matrix, name="hc-add-matrix"),
path("add_mattermost/", views.add_mattermost, name="hc-add-mattermost"),


+ 42
- 26
hc/front/views.py View File

@ -951,50 +951,66 @@ def remove_channel(request, code):
@login_required
def add_email(request, code):
project = _get_rw_project_for_user(request, code)
def email_form(request, code=None, channel=None):
""" Add email integration or edit an existing email integration. """
is_new = channel is None
if is_new:
project = _get_rw_project_for_user(request, code)
channel = Channel(project=project, kind="email")
if request.method == "POST":
form = forms.AddEmailForm(request.POST)
form = forms.EmailForm(request.POST)
if form.is_valid():
channel = Channel(project=project, kind="email")
channel.value = json.dumps(
{
"value": form.cleaned_data["value"],
"up": form.cleaned_data["up"],
"down": form.cleaned_data["down"],
}
)
if form.cleaned_data["value"] != channel.email_value:
if not settings.EMAIL_USE_VERIFICATION:
# In self-hosted setting, administator can set
# EMAIL_USE_VERIFICATION=False to disable email verification
channel.email_verified = True
elif form.cleaned_data["value"] == request.user.email:
# If the user is adding *their own* address
# we skip the verification step
channel.email_verified = True
else:
channel.email_verified = False
channel.value = form.to_json()
channel.save()
channel.assign_all_checks()
is_own_email = form.cleaned_data["value"] == request.user.email
if is_own_email or not settings.EMAIL_USE_VERIFICATION:
# If user is subscribing *their own* address
# we can skip the verification step.
# Additionally, in self-hosted setting, administator has the
# option to disable the email verification step altogether.
if is_new:
channel.assign_all_checks()
channel.email_verified = True
channel.save()
else:
if not channel.email_verified:
channel.send_verify_link()
return redirect("hc-channels", project.code)
return redirect("hc-channels", channel.project.code)
else:
form = forms.AddEmailForm()
form = forms.EmailForm(
{
"value": channel.email_value,
"up": channel.email_notify_up,
"down": channel.email_notify_down,
}
)
ctx = {
"page": "channels",
"project": project,
"project": channel.project,
"use_verification": settings.EMAIL_USE_VERIFICATION,
"form": form,
}
return render(request, "integrations/add_email.html", ctx)
@login_required
def edit_channel(request, code):
channel = _get_rw_channel_for_user(request, code)
if channel.kind == "email":
return email_form(request, channel=channel)
return HttpResponseBadRequest()
@require_setting("WEBHOOKS_ENABLED")
@login_required
def add_webhook(request, code):


+ 3
- 1
templates/front/channels.html View File

@ -147,6 +147,9 @@
{% if ch.kind == "webhook" and rw %}
<a class="btn btn-sm btn-default" href="{% url 'hc-edit-webhook' ch.code %}">Edit</a>
{% endif %}
{% if ch.kind == "email" and rw %}
<a class="btn btn-sm btn-default" href="{% url 'hc-edit-channel' ch.code %}">Edit</a>
{% endif %}
<form action="{% url 'hc-channel-test' ch.code %}" method="post">
{% csrf_token %}
<button
@ -605,7 +608,6 @@
{% if ch.kind == "webhook" %}
<a class="btn btn-default pull-left" href="{% url 'hc-edit-webhook' ch.code %}">Edit Webhook Parameters&hellip;</a>
{% endif %}
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save</button>
</div>


Loading…
Cancel
Save