Skip to content

Commit

Permalink
Merge pull request #3241 from open-formulieren/feature/3215-eherkenni…
Browse files Browse the repository at this point in the history
…ng-bewinfvoering-prefill

[#3215] Prefill with bewindvoering/machtigen
  • Loading branch information
sergei-maertens authored Jul 17, 2023
2 parents a4b439a + 32a8f8a commit 2a24b94
Show file tree
Hide file tree
Showing 29 changed files with 712 additions and 83 deletions.
9 changes: 9 additions & 0 deletions docs/manual/forms/form_fields.rst
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,15 @@ Registratie
naar het achterliggende registratie systeem, dan kunt u hier een attribuut
kiezen dat beschikbaar is in het achterliggende registratie systeem.

Prefill
-------

* **Plugin**: Welke prefill plugin te gebruiken om data op te halen over de persoon/het bedrijf die ingelogd is.
* **Pluginattribuut**: Welk attribuut van de prefill-backend data te gebruiken om deze component voorin te vullen.
* **Identifier rol**: Bij DigiD Machtigen of eHekerkenning zijn meerdere rollen actief: de gemachtigde (persoon die het
formulier invult), of de 'geauthenticeerde' (persoon of bedrijf voor wie het formulier ingevuld wordt). Deze optie stelt in
voor welke van deze rollen de relevante gegevens voor het geselecteerde attribuut opgevraagd worden.


Globale configuratieopties
==========================
Expand Down
12 changes: 12 additions & 0 deletions src/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7091,6 +7091,13 @@ components:
description: Which attribute from the prefill response should be used to
fill this variable
maxLength: 200
prefillIdentifierRole:
allOf:
- $ref: '#/components/schemas/PrefillIdentifierRoleEnum'
description: In case that multiple identifiers are returned (in the case
of eHerkenning bewindvoering and DigiD Machtigen), should the prefill
data related to the main identifier be used, or that related to the authorised
person?
dataType:
allOf:
- $ref: '#/components/schemas/DataTypeEnum'
Expand Down Expand Up @@ -7929,6 +7936,11 @@ components:
required:
- id
- label
PrefillIdentifierRoleEnum:
enum:
- main
- authorised_person
type: string
PrefillPlugin:
type: object
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,14 +152,19 @@ class DigiDMachtigenOIDCAuthentication(OIDCAuthentication):

def add_claims_to_sessions_if_not_cosigning(self, claim, request):
# set the session auth key only if we're not co-signing
if claim and CO_SIGN_PARAMETER not in request.GET:
config = OpenIDConnectDigiDMachtigenConfig.get_solo()
request.session[FORM_AUTH_SESSION_KEY] = {
"plugin": self.identifier,
"attribute": self.provides_auth,
"value": claim[config.vertegenwoordigde_claim_name],
"machtigen": request.session[DIGID_MACHTIGEN_OIDC_AUTH_SESSION_KEY],
}
if not claim or CO_SIGN_PARAMETER in request.GET:
return

config = self.config_class.get_solo()
machtigen_data = request.session[self.session_key]
request.session[FORM_AUTH_SESSION_KEY] = {
"plugin": self.identifier,
"attribute": self.provides_auth,
"value": claim[config.vertegenwoordigde_claim_name],
"machtigen": {
"identifier_value": machtigen_data.get(config.gemachtigde_claim_name)
},
}

def get_label(self) -> str:
return "DigiD Machtigen"
Expand All @@ -179,16 +184,22 @@ class EHerkenningBewindvoeringOIDCAuthentication(OIDCAuthentication):

def add_claims_to_sessions_if_not_cosigning(self, claim, request):
# set the session auth key only if we're not co-signing
if claim and CO_SIGN_PARAMETER not in request.GET:
config = self.config_class.get_solo()
request.session[FORM_AUTH_SESSION_KEY] = {
"plugin": self.identifier,
"attribute": self.provides_auth,
"value": claim[config.vertegenwoordigde_company_claim_name],
"machtigen": request.session[
EHERKENNING_BEWINDVOERING_OIDC_AUTH_SESSION_KEY
],
}
if not claim or CO_SIGN_PARAMETER in request.GET:
return

config = self.config_class.get_solo()
machtigen_data = request.session[self.session_key]
request.session[FORM_AUTH_SESSION_KEY] = {
"plugin": self.identifier,
"attribute": self.provides_auth,
"value": claim[config.vertegenwoordigde_company_claim_name],
"machtigen": {
# TODO So far the only possibility is that this is a BSN.
"identifier_value": machtigen_data.get(
config.gemachtigde_person_claim_name
)
},
}

def get_label(self) -> str:
return "eHerkenning bewindvoering"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,29 @@
import requests_mock
from furl import furl
from rest_framework import status
from rest_framework.test import APIRequestFactory

from digid_eherkenning_oidc_generics.models import (
OpenIDConnectDigiDMachtigenConfig,
OpenIDConnectEHerkenningBewindvoeringConfig,
OpenIDConnectPublicConfig,
)
from openforms.authentication.constants import (
CO_SIGN_PARAMETER,
FORM_AUTH_SESSION_KEY,
AuthAttribute,
)
from openforms.authentication.contrib.digid_eherkenning_oidc.constants import (
DIGID_MACHTIGEN_OIDC_AUTH_SESSION_KEY,
EHERKENNING_BEWINDVOERING_OIDC_AUTH_SESSION_KEY,
)
from openforms.authentication.contrib.digid_eherkenning_oidc.plugin import (
DigiDMachtigenOIDCAuthentication,
EHerkenningBewindvoeringOIDCAuthentication,
)
from openforms.authentication.views import BACKEND_OUTAGE_RESPONSE_PARAMETER
from openforms.forms.tests.factories import FormFactory
from openforms.submissions.tests.mixins import SubmissionsMixin

default_config = dict(
enabled=True,
Expand Down Expand Up @@ -318,3 +334,115 @@ def test_redirect_with_keycloak_identity_provider_hint(self, m_get_solo):
f"http://testserver{reverse('digid_machtigen_oidc:oidc_authentication_callback')}",
)
self.assertEqual(query_params["kc_idp_hint"], "oidc-digid-machtigen")


class AddClaimsToSessionTests(SubmissionsMixin, TestCase):
def test_handle_return_without_claim_eherkenning_bewindvoering(self):
factory = APIRequestFactory()
request = factory.get("/xyz")
request.session = {}

plugin = EHerkenningBewindvoeringOIDCAuthentication(identifier="boh")
plugin.add_claims_to_sessions_if_not_cosigning(claim="", request=request)

self.assertNotIn(FORM_AUTH_SESSION_KEY, request.session)

def test_handle_return_with_cosign_param_eherkenning_bewindvoering(self):
factory = APIRequestFactory()
request = factory.get(f"/xyz?{CO_SIGN_PARAMETER}=tralala")
request.session = {}

plugin = EHerkenningBewindvoeringOIDCAuthentication(identifier="boh")
plugin.add_claims_to_sessions_if_not_cosigning(claim="tralala", request=request)

self.assertNotIn(FORM_AUTH_SESSION_KEY, request.session)

def test_handle_return_without_claim_digid_machtigen(self):
factory = APIRequestFactory()
request = factory.get("/xyz")
request.session = {}

plugin = DigiDMachtigenOIDCAuthentication(identifier="boh")
plugin.add_claims_to_sessions_if_not_cosigning(claim="", request=request)

self.assertNotIn(FORM_AUTH_SESSION_KEY, request.session)

def test_handle_return_with_cosign_param_digi_machtigen(self):
factory = APIRequestFactory()
request = factory.get(f"/xyz?{CO_SIGN_PARAMETER}=tralala")
request.session = {}

plugin = DigiDMachtigenOIDCAuthentication(identifier="boh")
plugin.add_claims_to_sessions_if_not_cosigning(claim="tralala", request=request)

self.assertNotIn(FORM_AUTH_SESSION_KEY, request.session)

def test_handle_return_eherkenning_bewindvoering(self):
factory = APIRequestFactory()
request = factory.get("/xyz")
request.session = {
EHERKENNING_BEWINDVOERING_OIDC_AUTH_SESSION_KEY: {
"aanvrager.bsn": "222222222"
}
}

plugin = EHerkenningBewindvoeringOIDCAuthentication(identifier="boh")

with patch(
"openforms.authentication.contrib.digid_eherkenning_oidc.plugin.OpenIDConnectEHerkenningBewindvoeringConfig.get_solo",
return_value=OpenIDConnectEHerkenningBewindvoeringConfig(
vertegenwoordigde_company_claim_name="gemachtige.kvk",
gemachtigde_person_claim_name="aanvrager.bsn",
),
):
plugin.add_claims_to_sessions_if_not_cosigning(
claim={
"gemachtige.kvk": "111111111",
},
request=request,
)

self.assertIn(FORM_AUTH_SESSION_KEY, request.session)
self.assertEqual(
{
"plugin": "boh",
"attribute": AuthAttribute.kvk,
"value": "111111111",
"machtigen": {"identifier_value": "222222222"},
},
request.session[FORM_AUTH_SESSION_KEY],
)

def test_handle_return_digid_machtigen(self):
factory = APIRequestFactory()
request = factory.get("/xyz")
request.session = {
DIGID_MACHTIGEN_OIDC_AUTH_SESSION_KEY: {"aanvrager.bsn": "222222222"}
}

plugin = DigiDMachtigenOIDCAuthentication(identifier="boh")

with patch(
"openforms.authentication.contrib.digid_eherkenning_oidc.plugin.OpenIDConnectDigiDMachtigenConfig.get_solo",
return_value=OpenIDConnectDigiDMachtigenConfig(
vertegenwoordigde_claim_name="gemachtige.bsn",
gemachtigde_claim_name="aanvrager.bsn",
),
):
plugin.add_claims_to_sessions_if_not_cosigning(
claim={
"gemachtige.bsn": "111111111",
},
request=request,
)

self.assertIn(FORM_AUTH_SESSION_KEY, request.session)
self.assertEqual(
{
"plugin": "boh",
"attribute": AuthAttribute.bsn,
"value": "111111111",
"machtigen": {"identifier_value": "222222222"},
},
request.session[FORM_AUTH_SESSION_KEY],
)
25 changes: 25 additions & 0 deletions src/openforms/authentication/tests/test_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,31 @@ def test_setting_auth_attributes_flips_hashed_flag(self):
self.assertEqual(submission.auth_info.value, "123456789")
self.assertFalse(submission.auth_info.attribute_hashed)

def test_auth_with_digid_machtigen(self):
submission = SubmissionFactory.create(
form__authentication_backends=["digid_machtigen_oidc"]
)
user = UserFactory()
request = factory.get("/foo")
request.user = user
request.session = {
FORM_AUTH_SESSION_KEY: {
"plugin": "digid_machtigen_oidc",
"attribute": "bsn",
"value": "123123123",
"machtigen": {"identifier_value": "123456782"},
}
}

set_auth_attribute_on_session(sender=None, instance=submission, request=request)

submission.refresh_from_db()

self.assertTrue(submission.is_authenticated)
self.assertEqual(
submission.auth_info.machtigen["identifier_value"], "123456782"
)


class SetCosignDataTests(APITestCase):
def test_set_cosigner_data(self):
Expand Down
2 changes: 2 additions & 0 deletions src/openforms/forms/admin/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class FormVariableAdmin(admin.ModelAdmin):
"source",
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"data_type",
"is_sensitive_data",
"initial_value",
Expand All @@ -29,6 +30,7 @@ class FormVariableAdmin(admin.ModelAdmin):
"source",
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"data_type",
"data_format",
"is_sensitive_data",
Expand Down
1 change: 1 addition & 0 deletions src/openforms/forms/api/serializers/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ class Meta:
"service_fetch_configuration",
"prefill_plugin",
"prefill_attribute",
"prefill_identifier_role",
"data_type",
"data_format",
"is_sensitive_data",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 3.2.20 on 2023-07-07 12:06

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("forms", "0083_alter_form_is_appointment"),
]

operations = [
migrations.AddField(
model_name="formvariable",
name="prefill_identifier_role",
field=models.CharField(
choices=[("main", "Main"), ("authorised_person", "Authorised person")],
default="main",
help_text="In case that multiple identifiers are returned (in the case of eHerkenning bewindvoering and DigiD Machtigen), should the prefill data related to the main identifier be used, or that related to the authorised person?",
max_length=100,
verbose_name="prefill identifier role",
),
),
]
17 changes: 17 additions & 0 deletions src/openforms/forms/models/form_variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
is_layout_component,
iter_components,
)
from openforms.prefill.constants import IdentifierRoles
from openforms.variables.constants import FormVariableDataTypes, FormVariableSources
from openforms.variables.utils import check_initial_value

Expand Down Expand Up @@ -87,6 +88,12 @@ def create_for_formstep(self, form_step: "FormStep") -> List["FormVariable"]:
default="",
skip_exc=KeyError,
),
prefill_identifier_role=glom(
component,
Path("prefill", "identifierRole"),
default=IdentifierRoles.main,
skip_exc=KeyError,
),
key=component["key"],
name=component.get("label") or component["key"],
is_sensitive_data=component.get("isSensitiveData", False),
Expand Down Expand Up @@ -154,6 +161,16 @@ class FormVariable(models.Model):
blank=True,
max_length=200,
)
prefill_identifier_role = models.CharField(
verbose_name=_("prefill identifier role"),
help_text=_(
"In case that multiple identifiers are returned (in the case of eHerkenning bewindvoering and DigiD "
"Machtigen), should the prefill data related to the main identifier be used, or that related to the authorised person?"
),
choices=IdentifierRoles.choices,
default=IdentifierRoles.main,
max_length=100,
)
data_type = models.CharField(
verbose_name=_("data type"),
help_text=_("The type of the value that will be associated with this variable"),
Expand Down
Loading

0 comments on commit 2a24b94

Please sign in to comment.