Projet

Général

Profil

0003-auth_saml-set-attributes-using-model-67025.patch

Valentin Deniaud, 17 août 2022 11:43

Télécharger (6,31 ko)

Voir les différences:

Subject: [PATCH 3/8] auth_saml: set attributes using model (#67025)

 src/authentic2_auth_saml/adapters.py | 38 +++++++++++++++-------------
 tests/test_auth_saml.py              | 35 ++++++++++++-------------
 2 files changed, 38 insertions(+), 35 deletions(-)
src/authentic2_auth_saml/adapters.py
133 133
        if not isinstance(attribute_mapping, list):
134 134
            raise MappingError(_('invalid A2_ATTRIBUTE_MAPPING'))
135 135

  
136
        if self.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping):
137
            user.save()
136
        self.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping)
138 137

  
139 138
    def apply_attribute_mapping(self, user, idp, saml_attributes, attribute_mapping):
140 139
        self.rename_attributes(idp, saml_attributes)
140
        self.set_attributes(user, idp, saml_attributes)
141 141

  
142
        user_modified = False
143 142
        for mapping in attribute_mapping:
144 143
            if not isinstance(mapping, dict):
145 144
                raise MappingError(_('invalid mapping action "%(mapping)s"'), mapping=mapping)
......
155 154
                if not method:
156 155
                    raise MappingError(_('invalid action'))
157 156
                logger.debug('auth_saml: applying provisionning mapping %s', mapping)
158
                if method(user, idp, saml_attributes, mapping):
159
                    user_modified = True
157
                method(user, idp, saml_attributes, mapping)
160 158
            except MappingError as e:
161 159
                if mandatory:
162 160
                    # it's mandatory, provisionning should fail completely
163 161
                    raise e
164 162
                logger.warning('auth_saml: mapping action failed: %s', e)
165
        return user_modified
166 163

  
167 164
    def rename_attributes(self, idp, saml_attributes):
168 165
        for action in idp['authenticator'].rename_attribute_actions.all():
169 166
            if action.from_name in saml_attributes:
170 167
                saml_attributes[action.to_name] = saml_attributes[action.from_name]
171 168

  
172
    def action_set_attribute(self, user, idp, saml_attributes, mapping):
173
        attribute = mapping.get('attribute')
174
        if not attribute or not isinstance(attribute, str):
175
            raise MappingError(_('missing attribute key'))
169
    def set_attributes(self, user, idp, saml_attributes):
170
        user_modified = False
171
        for action in idp['authenticator'].set_attribute_actions.all():
172
            try:
173
                user_modified |= self.set_user_attribute(user, action, saml_attributes)
174
            except MappingError as e:
175
                logger.warning('auth_saml: mapping action failed: %s', e)
176
                if action.mandatory:
177
                    # it's mandatory, provisionning should fail completely
178
                    raise e
176 179

  
177
        saml_attribute = mapping.get('saml_attribute')
178
        if not saml_attribute or not isinstance(saml_attribute, str):
179
            raise MappingError(_('missing saml_attribute key'))
180
        if user_modified:
181
            user.save()
180 182

  
181
        if saml_attribute not in saml_attributes:
182
            raise MappingError(_('unknown saml_attribute (%s)') % saml_attribute)
183
        value = saml_attributes[saml_attribute]
184
        return self.set_user_attribute(user, attribute, value)
183
    def set_user_attribute(self, user, action, saml_attributes):
184
        if action.saml_attribute not in saml_attributes:
185
            raise MappingError(_('unknown saml_attribute (%s)') % action.saml_attribute)
185 186

  
186
    def set_user_attribute(self, user, attribute, value):
187
        attribute = action.attribute
188
        value = saml_attributes[action.saml_attribute]
187 189
        if isinstance(value, list):
188 190
            if len(value) == 0:
189 191
                raise MappingError(_('no value for attribute "%(attribute)s"'), attribute=attribute)
tests/test_auth_saml.py
28 28
from authentic2.custom_user.models import DeletedUser
29 29
from authentic2.models import Attribute
30 30
from authentic2_auth_saml.adapters import AuthenticAdapter, MappingError
31
from authentic2_auth_saml.models import RenameAttributeAction, SAMLAuthenticator
31
from authentic2_auth_saml.models import RenameAttributeAction, SAMLAuthenticator, SetAttributeAction
32 32

  
33 33
from .utils import login
34 34

  
......
78 78
        enabled=True,
79 79
        metadata='meta1.xml',
80 80
        slug='idp1',
81
        a2_attribute_mapping=[
82
            {
83
                'attribute': 'email',
84
                'saml_attribute': 'mail',
85
                'mandatory': True,
86
            },
87
            {
88
                'attribute': 'title',
89
                'saml_attribute': 'title',
90
            },
91
            {
92
                'attribute': 'first_name',
93
                'saml_attribute': 'first_name',
94
            },
95
        ],
81
    )
82
    SetAttributeAction.objects.create(
83
        authenticator=authenticator,
84
        attribute='email',
85
        saml_attribute='mail',
86
        mandatory=True,
87
    )
88
    SetAttributeAction.objects.create(
89
        authenticator=authenticator,
90
        attribute='title',
91
        saml_attribute='title',
92
    )
93
    SetAttributeAction.objects.create(
94
        authenticator=authenticator,
95
        attribute='first_name',
96
        saml_attribute='first_name',
96 97
    )
97 98
    RenameAttributeAction.objects.create(
98 99
        authenticator=authenticator,
......
157 158
    adapter, idp, saml_attributes, title_attribute, user, rf
158 159
):
159 160
    saml_attributes['http://nice/attribute/givenName'] = []
160
    idp['A2_ATTRIBUTE_MAPPING'][-1]['mandatory'] = True
161
    SetAttributeAction.objects.filter(attribute='first_name').update(mandatory=True)
161 162
    with pytest.raises(MappingError, match='no value'):
162 163
        adapter.apply_attribute_mapping(user, idp, saml_attributes, idp['A2_ATTRIBUTE_MAPPING'])
163 164

  
164
-