diff --git a/python/nav/alertengine/dispatchers/slack_dispatcher.py b/python/nav/alertengine/dispatchers/slack_dispatcher.py index 93aabccb7d..4d582c1c71 100644 --- a/python/nav/alertengine/dispatchers/slack_dispatcher.py +++ b/python/nav/alertengine/dispatchers/slack_dispatcher.py @@ -19,6 +19,8 @@ import json import time +from django.core.validators import URLValidator +from django.core.exceptions import ValidationError from urllib.request import Request, urlopen from urllib.error import HTTPError @@ -86,4 +88,9 @@ def _is_still_backing_off_for(self, address): @staticmethod def is_valid_address(address): + validator = URLValidator() + try: + validator(address) + except ValidationError: + return False return True diff --git a/python/nav/web/alertprofiles/forms.py b/python/nav/web/alertprofiles/forms.py index 8a85f50da1..75105ac0a4 100644 --- a/python/nav/web/alertprofiles/forms.py +++ b/python/nav/web/alertprofiles/forms.py @@ -25,6 +25,7 @@ from crispy_forms_foundation.layout import Layout, Row, Column, Field, Submit, HTML from nav.alertengine.dispatchers.email_dispatcher import Email +from nav.alertengine.dispatchers.slack_dispatcher import Slack from nav.alertengine.dispatchers.sms_dispatcher import Sms from nav.models.profiles import MatchField, Filter, Expression, FilterGroup @@ -118,6 +119,9 @@ def clean(self): elif type_.handler == 'email': if not Email.is_valid_address(address): error = 'Not a valid email address.' + elif type_.handler == 'slack': + if not Slack.is_valid_address(address): + error = 'Not a valid absolute url.' if error: self._errors['address'] = self.error_class([error]) diff --git a/tests/integration/web/alertprofiles_test.py b/tests/integration/web/alertprofiles_test.py index 2276f95ef1..3e924cad6f 100644 --- a/tests/integration/web/alertprofiles_test.py +++ b/tests/integration/web/alertprofiles_test.py @@ -8,8 +8,13 @@ from django.test.client import RequestFactory from django.urls import reverse from nav.compatibility import smart_str - -from nav.models.profiles import AlertProfile, Account, AlertPreference +from nav.models.profiles import ( + Account, + AlertAddress, + AlertPreference, + AlertProfile, + AlertSender, +) from nav.web.alertprofiles.views import set_active_profile @@ -171,6 +176,62 @@ def test_set_accountgroup_permissions_should_not_crash(db, client): assert response.status_code == 200 +def test_alertprofiles_add_slack_address_with_valid_url_should_succeed(client): + """Tests that a slack address with a valid absolute url can be added""" + valid_url = "https://example.com" + slack = AlertSender.objects.get(name=AlertSender.SLACK) + url = reverse("alertprofiles-address-save") + data = { + "address": valid_url, + "type": slack.pk, + } + response = client.post(url, data=data, follow=True) + assert response.status_code == 200 + assert AlertAddress.objects.filter( + type=slack, + address=valid_url, + ).exists() + assert f"Saved address {valid_url}" in smart_str(response.content) + + +def test_alertprofiles_add_slack_address_with_a_valid_but_not_absolute_url_should_fail( + client, +): + """Tests that a slack address with a not valid url cannot be added""" + non_absolute_url = "www.example.com" + slack = AlertSender.objects.get(name=AlertSender.SLACK) + url = reverse("alertprofiles-address-save") + data = { + "address": non_absolute_url, + "type": slack.pk, + } + response = client.post(url, data=data, follow=True) + assert response.status_code == 200 + assert not AlertAddress.objects.filter( + type=slack, + address=non_absolute_url, + ).exists() + assert "Not a valid absolute url." in smart_str(response.content) + + +def test_alertprofiles_add_slack_address_with_non_valid_url_should_fail(client): + """Tests that a slack address with a not valid url cannot be added""" + invalid_url = "abc" + slack = AlertSender.objects.get(name=AlertSender.SLACK) + url = reverse("alertprofiles-address-save") + data = { + "address": invalid_url, + "type": slack.pk, + } + response = client.post(url, data=data, follow=True) + assert response.status_code == 200 + assert not AlertAddress.objects.filter( + type=slack, + address=invalid_url, + ).exists() + assert "Not a valid absolute url." in smart_str(response.content) + + # # fixtures and helpers #