From d5d1982d50261190f1807b818081ab0d624ccf36 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9ters?= <fpeters@entrouvert.com>
Date: Thu, 16 Feb 2023 13:37:41 +0100
Subject: [PATCH] misc: handle missing title or birthdate profile attributes
 (#74596)

---
 src/authentic2_auth_fedict/adapters.py | 16 +++++++---
 tests/test_all.py                      | 44 ++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 5 deletions(-)

diff --git a/src/authentic2_auth_fedict/adapters.py b/src/authentic2_auth_fedict/adapters.py
index e040ea4..23a61e0 100644
--- a/src/authentic2_auth_fedict/adapters.py
+++ b/src/authentic2_auth_fedict/adapters.py
@@ -185,15 +185,21 @@ class AuthenticAdapter(DefaultAdapter):
                 else:
                     birthdate = ''
             try:
-                Attribute.objects.get(name='birthdate').set_value(user, birthdate, verified=True)
-            except AttributeError:  # native authentic date field
-                birthdate = datetime.datetime.strptime(birthdate, '%d/%m/%Y').date()
-                Attribute.objects.get(name='birthdate').set_value(user, birthdate, verified=True)
+                try:
+                    Attribute.objects.get(name='birthdate').set_value(user, birthdate, verified=True)
+                except AttributeError:  # native authentic date field
+                    birthdate = datetime.datetime.strptime(birthdate, '%d/%m/%Y').date()
+                    Attribute.objects.get(name='birthdate').set_value(user, birthdate, verified=True)
+            except Attribute.DoesNotExist:
+                pass
             if int(nrn[6:9]) % 2:
                 title = 'Monsieur'
             else:
                 title = 'Madame'
-            Attribute.objects.get(name='title').set_value(user, title, verified=True)
+            try:
+                Attribute.objects.get(name='title').set_value(user, title, verified=True)
+            except Attribute.DoesNotExist:
+                pass
 
         if saml_attributes.get('givenName'):
             Attribute.objects.get(name='first_name').set_value(
diff --git a/tests/test_all.py b/tests/test_all.py
index 4d5d723..0f29b77 100644
--- a/tests/test_all.py
+++ b/tests/test_all.py
@@ -250,6 +250,50 @@ def test_provision_new_attributes_verified(app, settings, issuer, user):
     assert backend_user.last_name == 'Bar'
 
 
+def test_missing_title_attribute(app, settings, issuer, user):
+    Attribute.objects.filter(kind='title').delete()
+    # email & title verified
+    user.email = 'john.doe@verified.publik.love'
+    user.email_verified = True
+    user.first_name = 'Johnny'
+    user.last_name = 'Smith'
+    user.save()
+    UserSAMLIdentifier.objects.create(
+        user=user,
+        name_id='c54db0a8ddc24a02a2d057f857d3b102',
+        issuer=Issuer.objects.first(),
+    )
+
+    backend = FedictBackend()
+    request = factory.get(path='/accounts/')
+    request_user = User.objects.create(
+        first_name='Foo',
+        last_name='Bar',
+        email='foo.bar@nowhere.null',
+    )
+    request.user = request_user
+    saml_attributes = {
+        'givenName': ['Doe'],
+        'surname': ['John'],
+        'last_name': ['Doe'],
+        'first_name': ['John'],
+        'username': ['john.doe'],
+        'urn:be:fedict:iam:attr:fedid': ['c54db0a8ddc24a02a2d057f857d3b102'],
+        'egovNRN': ['85073003328'],
+        'is_superuser': ['false'],
+        'issuer': 'https://idp.com/',
+        'name_id_content': 'c54db0a8ddc24a02a2d057f857d3b102',
+        'name_id_format': 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified',
+        'name_id_name_qualifier': 'https://idp.com/idp/saml2/metadata',
+        'name_id_content_orig': 'c54db0a8ddc24a02a2d057f857d3b102',
+    }
+    credentials = {'saml_attributes': saml_attributes}
+    SessionMiddleware().process_request(request)
+    MessageMiddleware().process_request(request)
+    backend_user = backend.authenticate(request, **credentials)
+    assert backend_user == request_user
+
+
 def test_provision_old_account_deleted(app, settings, issuer, user):
     backend = FedictBackend()
     request = factory.get(path='/accounts/')
-- 
2.39.1

