diff --git a/src/openforms/authentication/api/fields.py b/src/openforms/authentication/api/fields.py index c0b1e22cb4..235645502e 100644 --- a/src/openforms/authentication/api/fields.py +++ b/src/openforms/authentication/api/fields.py @@ -3,6 +3,8 @@ from openforms.authentication.api.serializers import LoginOptionSerializer from openforms.authentication.registry import register as auth_register +from openforms.config.models import GlobalConfiguration +from openforms.forms.models import Form class LoginOptionsReadOnlyField(serializers.ListField): @@ -24,7 +26,16 @@ def __init__(self, is_for_cosign: bool = False, *args, **kwargs) -> None: def to_internal_value(self, data): raise NotImplementedError("read only") - def to_representation(self, form): + def to_representation(self, value: Form): # type: ignore reportIncompatibleOverride request: Request = self.context["request"] - temp = auth_register.get_options(request, form, self.is_for_cosign) - return super().to_representation(temp) + + options = auth_register.get_options(request, value, self.is_for_cosign) + + # Returning no auth options for cosign if a link is used in the email template + # results in the cosign block not being shown in the frontend. + if self.is_for_cosign: + config = GlobalConfiguration.get_solo() + if config.cosign_request_template_has_link: + options = [] + + return super().to_representation(options) diff --git a/src/openforms/config/models/config.py b/src/openforms/config/models/config.py index a616f8d15f..d8780bc85b 100644 --- a/src/openforms/config/models/config.py +++ b/src/openforms/config/models/config.py @@ -17,7 +17,11 @@ from openforms.data_removal.constants import RemovalMethods from openforms.emails.validators import URLSanitationValidator from openforms.payments.validators import validate_payment_order_id_template -from openforms.template import openforms_backend, render_from_string +from openforms.template import ( + extract_variables_used, + openforms_backend, + render_from_string, +) from openforms.template.validators import DjangoTemplateValidator from openforms.translations.utils import ensure_default_language from openforms.utils.fields import SVGOrImageField @@ -599,3 +603,10 @@ def get_default_theme(self) -> Theme: if none is configured. """ return self.default_theme or Theme() + + @property + def cosign_request_template_has_link(self) -> bool: + variables_used = extract_variables_used( + self.cosign_request_template, backend=openforms_backend + ) + return "form_url" in variables_used diff --git a/src/openforms/forms/tests/test_serializers.py b/src/openforms/forms/tests/test_serializers.py index 954187588d..6239550095 100644 --- a/src/openforms/forms/tests/test_serializers.py +++ b/src/openforms/forms/tests/test_serializers.py @@ -1,11 +1,13 @@ from unittest.mock import patch +from django.contrib.auth.models import AnonymousUser from django.test import RequestFactory, TestCase from hypothesis import given from hypothesis.extra.django import TestCase as HypothesisTestCase from openforms.accounts.tests.factories import UserFactory +from openforms.config.models.config import GlobalConfiguration from openforms.forms.api.datastructures import FormVariableWrapper from openforms.forms.api.serializers import FormSerializer from openforms.forms.api.serializers.logic.action_serializers import ( @@ -124,7 +126,13 @@ def test_invalid_action(self): class FormSerializerTest(TestCase): - def test_form_with_cosign(self): + @patch( + "openforms.authentication.api.fields.GlobalConfiguration.get_solo", + return_value=GlobalConfiguration( + cosign_request_template="{{ form_name }} cosign request." + ), + ) + def test_form_with_cosign(self, mock_get_solo): form_step = FormStepFactory.create( form__slug="form-with-cosign", form__authentication_backends=["digid"], @@ -154,6 +162,68 @@ def test_form_with_cosign(self): self.assertIsNotNone(cosign_login_info) self.assertEqual(cosign_login_info["identifier"], "digid") + @patch( + "openforms.authentication.api.fields.GlobalConfiguration.get_solo", + return_value=GlobalConfiguration( + cosign_request_template="{{ form_name }} cosign request." + ), + ) + def test_form_without_cosign_link_used_in_email(self, mock_get_solo): + form_step = FormStepFactory.create( + form__slug="form-with-cosign", + form__authentication_backends=["digid"], + form_definition__configuration={ + "components": [ + { + "key": "cosignField", + "label": "Cosign", + "type": "cosign", + } + ] + }, + ) + factory = RequestFactory() + request = factory.get("/foo") + request.user = AnonymousUser() + + serializer = FormSerializer( + instance=form_step.form, context={"request": request} + ) + + cosign_login_options = serializer.data["cosign_login_options"] + self.assertEqual(len(cosign_login_options), 1) + + @patch( + "openforms.authentication.api.fields.GlobalConfiguration.get_solo", + return_value=GlobalConfiguration( + cosign_request_template="{{ form_url }} cosign request." + ), + ) + def test_form_with_cosign_link_used_in_email(self, mock_get_solo): + form_step = FormStepFactory.create( + form__slug="form-with-cosign", + form__authentication_backends=["digid"], + form_definition__configuration={ + "components": [ + { + "key": "cosignField", + "label": "Cosign", + "type": "cosign", + } + ] + }, + ) + factory = RequestFactory() + request = factory.get("/foo") + request.user = AnonymousUser() + + serializer = FormSerializer( + instance=form_step.form, context={"request": request} + ) + + cosign_login_options = serializer.data["cosign_login_options"] + self.assertEqual(len(cosign_login_options), 0) + def test_form_without_cosign(self): form_step = FormStepFactory.create( form__slug="form-without-cosign",