Skip to content

Commit

Permalink
Merge pull request #4163 from open-formulieren/feature/3725-add-broke…
Browse files Browse the repository at this point in the history
…n-brp-configuration-to-email-digest

[#3725] Add detection of BRP broken configuration concerning addressNL component
  • Loading branch information
vaszig authored Apr 19, 2024
2 parents 9df1fc8 + c22d0d9 commit 6ad8167
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/openforms/contrib/brk/checks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def check_config():
{"postcode": "1234AB", "huisnummer": "1"}
)
except NoServiceConfigured as exc:
msg = _("{api_name} endpoint is not configured.").format(api_name="KVK")
msg = _("{api_name} endpoint is not configured").format(api_name="KVK")
raise InvalidPluginConfiguration(msg) from exc
except requests.RequestException as exc:
raise InvalidPluginConfiguration(
Expand Down
16 changes: 16 additions & 0 deletions src/openforms/contrib/brk/service.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from openforms.forms.models.form import Form
from openforms.plugins.exceptions import InvalidPluginConfiguration

from .checks import BRKValidatorCheck


def check_brk_config_for_addressNL() -> str:
live_forms = Form.objects.live()

if any(form.has_component("addressNL") for form in live_forms):
try:
BRKValidatorCheck.check_config()
except InvalidPluginConfiguration as e:
return e.args[0]

return ""
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@

from django.contrib.contenttypes.models import ContentType
from django.urls import reverse
from django.utils.translation import gettext_lazy as _

from django_yubin.models import Message
from furl import furl

from openforms.contrib.brk.service import check_brk_config_for_addressNL
from openforms.logging.models import TimelineLogProxy
from openforms.submissions.models.submission import Submission
from openforms.submissions.utils import get_filtered_submission_admin_url
from openforms.typing import StrOrPromise


@dataclass
Expand Down Expand Up @@ -60,6 +63,12 @@ def failed_submissions_counter(self) -> int:
return len(self.submission_ids)


@dataclass
class BrokenConfiguration:
config_name: StrOrPromise
exception_message: str


def collect_failed_emails(since: datetime) -> Iterable[FailedEmail]:
logs = TimelineLogProxy.objects.filter(
timestamp__gt=since,
Expand Down Expand Up @@ -156,3 +165,17 @@ def collect_failed_prefill_plugins(since: datetime) -> list[FailedPrefill]:
)

return failed_prefill_plugins


def collect_broken_configurations() -> list[BrokenConfiguration]:
check_brk_configuration = check_brk_config_for_addressNL()

broken_configurations = []
if check_brk_configuration:
broken_configurations.append(
BrokenConfiguration(
config_name=_("BRK Client"), exception_message=check_brk_configuration
)
)

return broken_configurations
7 changes: 5 additions & 2 deletions src/openforms/emails/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@

from openforms.celery import app
from openforms.config.models import GlobalConfiguration
from openforms.logging.service import (

from .digest import (
collect_broken_configurations,
collect_failed_emails,
collect_failed_prefill_plugins,
collect_failed_registrations,
)

from .utils import send_mail_html


Expand All @@ -25,11 +26,13 @@ def get_context_data(self) -> dict[str, Any]:
failed_emails = collect_failed_emails(self.since)
failed_registrations = collect_failed_registrations(self.since)
failed_prefill_plugins = collect_failed_prefill_plugins(self.since)
broken_configurations = collect_broken_configurations()

return {
"failed_emails": failed_emails,
"failed_registrations": failed_registrations,
"failed_prefill_plugins": failed_prefill_plugins,
"broken_configurations": broken_configurations,
}

def render(self) -> str:
Expand Down
14 changes: 14 additions & 0 deletions src/openforms/emails/templates/emails/admin_digest.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,17 @@ <h5>{% trans "Prefill plugins" %}</h5>
{% endfor %}
</ul>
{% endif %}

{% if broken_configurations %}
<h5>{% trans "Configuration problems" %}</h5>
<ul>
{% for config in broken_configurations %}
<li>
{% blocktranslate with name=config.config_name message=config.exception_message trimmed %}
The configuration for '{{ name }}' is invalid (<i>{{ message }}</i>).<br/>
Components or plugins which make use of this will not work properly.
{% endblocktranslate %}
</li>
{% endfor %}
</ul>
{% endif %}
141 changes: 140 additions & 1 deletion src/openforms/emails/tests/test_tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@

from django.core import mail
from django.test import TestCase, override_settings
from django.utils.translation import gettext as _

import requests_mock
from django_yubin.models import Message
from freezegun import freeze_time

from openforms.config.models import GlobalConfiguration
from openforms.forms.tests.factories import FormFactory
from openforms.contrib.brk.models import BRKConfig
from openforms.contrib.brk.tests.base import BRK_SERVICE
from openforms.forms.tests.factories import (
FormDefinitionFactory,
FormFactory,
FormStepFactory,
)
from openforms.logging import logevent
from openforms.prefill.registry import register
from openforms.registrations.exceptions import RegistrationFailed
Expand Down Expand Up @@ -260,3 +268,134 @@ def test_prefill_plugin_failures_are_sent(self):
self.assertIn(str(submission_1.id), sent_email.body)
self.assertIn(str(submission_2.id), sent_email.body)
self.assertIn(str(submission.id), sent_email.body)

@requests_mock.Mocker()
def test_no_email_sent_when_brk_congiguration_is_valid_for_addressNL(self, m):
form = FormFactory.create()
form_definition = FormDefinitionFactory.create(
configuration={
"display": "form",
"components": [
{
"key": "addressNl",
"type": "addressNL",
"label": "AddressNL",
"defaultValue": {
"postcode": "",
"houseLetter": "",
"houseNumber": "",
"houseNumberAddition": "",
},
}
],
}
)
FormStepFactory.create(form=form, form_definition=form_definition)

with (
freeze_time("2023-01-03T01:00:00+01:00"),
patch(
"openforms.emails.tasks.GlobalConfiguration.get_solo",
return_value=GlobalConfiguration(
recipients_email_digest=["[email protected]"]
),
),
patch(
"openforms.contrib.brk.client.BRKConfig.get_solo",
return_value=BRKConfig(service=BRK_SERVICE),
),
):

m.get(
"https://api.brk.kadaster.nl/esd-eto-apikey/bevragen/v2/kadastraalonroerendezaken?postcode=1234AB&huisnummer=1",
json={"_embedded": {}},
)

send_email_digest()

self.assertEqual(0, len(mail.outbox))

def test_broken_brk_configuration_for_addressNL_is_sent(self):
form = FormFactory.create()
form_definition = FormDefinitionFactory.create(
configuration={
"display": "form",
"components": [
{
"key": "addressNl",
"type": "addressNL",
"label": "AddressNL",
"defaultValue": {
"postcode": "",
"houseLetter": "",
"houseNumber": "",
"houseNumberAddition": "",
},
}
],
}
)
FormStepFactory.create(form=form, form_definition=form_definition)

with (
freeze_time("2023-01-03T01:00:00+01:00"),
patch(
"openforms.emails.tasks.GlobalConfiguration.get_solo",
return_value=GlobalConfiguration(
recipients_email_digest=["[email protected]"]
),
),
patch(
"openforms.contrib.brk.client.BRKConfig.get_solo",
return_value=BRKConfig(service=None),
),
):

send_email_digest()

sent_email = mail.outbox[0]

self.assertEqual(
sent_email.subject, "[Open Forms] Daily summary of detected problems"
)
self.assertEqual(sent_email.recipients(), ["[email protected]"])
self.assertIn(
_(
"The configuration for 'BRK Client' is invalid (KVK endpoint is not configured)."
),
sent_email.body,
)

def test_no_email_sent_when_brk_congiguration_is_invalid_but_unused(self):
form = FormFactory.create()
form_definition = FormDefinitionFactory.create(
configuration={
"display": "form",
"components": [
{
"key": "textField",
"type": "textfield",
"label": "Text Field",
}
],
}
)
FormStepFactory.create(form=form, form_definition=form_definition)

with (
freeze_time("2023-01-03T01:00:00+01:00"),
patch(
"openforms.emails.tasks.GlobalConfiguration.get_solo",
return_value=GlobalConfiguration(
recipients_email_digest=["[email protected]"]
),
),
patch(
"openforms.contrib.brk.client.BRKConfig.get_solo",
return_value=BRKConfig(service=None),
),
):

send_email_digest()

self.assertEqual(0, len(mail.outbox))
5 changes: 5 additions & 0 deletions src/openforms/forms/models/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,11 @@ def deactivate(self):
logger.debug("Deactivating form %s", self.admin_name)
self.save(update_fields=["active", "deactivate_on"])

def has_component(self, component_type: str) -> bool:
return any(
component["type"] == component_type for component in self.iter_components()
)


class FormsExportQuerySet(DeleteFilesQuerySetMixin, models.QuerySet):
pass
Expand Down

0 comments on commit 6ad8167

Please sign in to comment.