Projet

Général

Profil

0001-auth_saml-always-add-mapping-as-MappingError-details.patch

Benjamin Dauvergne, 15 octobre 2020 17:48

Télécharger (5,04 ko)

Voir les différences:

Subject: [PATCH] auth_saml: always add mapping as MappingError details
 (#47760)

 src/authentic2_auth_saml/adapters.py | 24 +++++++++++++-----------
 tests/test_auth_saml.py              | 24 +++++++++++++++++-------
 2 files changed, 30 insertions(+), 18 deletions(-)
src/authentic2_auth_saml/adapters.py
36 36
    details = None
37 37

  
38 38
    def __init__(self, message, details=None):
39
        if details:
40
            self.details = details
39
        self.details = details or {}
41 40
        super(MappingError, self).__init__(message)
42 41

  
43 42
    def __str__(self):
......
104 103
        if not isinstance(attribute_mapping, list):
105 104
            raise MappingError('invalid A2_ATTRIBUTE_MAPPING')
106 105

  
106
        if self.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping):
107
            user.save()
108

  
109
    def apply_attribute_mapping(self, user, idp, saml_attributes, attribute_mapping):
107 110
        user_modified = False
108 111
        for mapping in attribute_mapping:
109 112
            if not isinstance(mapping, dict):
......
116 119
                    method = getattr(self, 'action_' + action.replace('-', '_'))
117 120
                except AttributeError:
118 121
                    pass
119
            if not method:
120
                raise MappingError('invalid action %r' % action)
121 122
            try:
123
                if not method:
124
                    raise MappingError('invalid action')
122 125
                logger.debug('auth_saml: applying provisionning mapping %s', mapping)
123 126
                if method(user, idp, saml_attributes, mapping):
124 127
                    user_modified = True
125 128
            except MappingError as e:
129
                e.details['mapping'] = mapping
126 130
                if mandatory:
127 131
                    # it's mandatory, provisionning should fail completely
128 132
                    raise e
129 133
                else:
130
                    logger.debug('auth_saml: action mapping %r failed: %s', mapping, e)
131

  
132
        if user_modified:
133
            user.save()
134
                    logger.warning('auth_saml: mapping action failed: %s', e)
135
        return user_modified
134 136

  
135 137
    def action_rename(self, user, idp, saml_attributes, mapping):
136 138
        from_name = mapping.get('from')
......
152 154
            raise MappingError('missing saml_attribute key')
153 155

  
154 156
        if saml_attribute not in saml_attributes:
155
            raise MappingError('unknown saml_attribute', details={'saml_attribute': saml_attribute})
157
            raise MappingError('unknown saml_attribute')
156 158
        value = saml_attributes[saml_attribute]
157 159
        return self.set_user_attribute(user, attribute, value)
158 160

  
159 161
    def set_user_attribute(self, user, attribute, value):
160 162
        if isinstance(value, list):
161 163
            if len(value) == 0:
162
                raise MappingError('no value for %s' % attribute, details={'attribute': attribute})
164
                raise MappingError('no value')
163 165
            if len(value) > 1:
164
                raise MappingError('too many values for %s' % attribute, details={'attribute': attribute})
166
                raise MappingError('too many values', details={'value': value})
165 167
            value = value[0]
166 168
        if attribute in ('first_name', 'last_name', 'email', 'username'):
167 169
            if getattr(user, attribute) != value:
tests/test_auth_saml.py
15 15
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 16

  
17 17
import os
18
import logging
18
import re
19 19

  
20 20
import pytest
21 21

  
......
138 138

  
139 139
    # simulate no attribute value
140 140
    saml_attributes['first_name'] = []
141
    mapping = {
142
        'attribute': 'first_name',
143
        'saml_attribute': 'first_name',
144
    }
145
    with pytest.raises(MappingError, match='no value for first_name'):
146
        adapter.action_set_attribute(user, idp, saml_attributes, mapping)
141
    attribute_mapping = [
142
        {
143
            'mandatory': True,
144
            'attribute': 'first_name',
145
            'saml_attribute': 'first_name',
146
        }
147
    ]
148

  
149
    # fail fast
150
    with pytest.raises(MappingError, match='no value.*first_name'):
151
        adapter.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping)
147 152

  
153
    # or log a warning
154
    caplog.clear()
155
    del attribute_mapping[0]['mandatory']
156
    adapter.apply_attribute_mapping(user, idp, saml_attributes, attribute_mapping)
157
    assert re.match('.*no value.*first_name', caplog.records[0].message)
148 158

  
149 159

  
150 160
def test_login_with_conditionnal_authenticators(db, app, settings, caplog):
151
-