Projet

Général

Profil

0001-api-prevent-password-change-on-get_or_create-34950.patch

Benjamin Dauvergne, 12 août 2019 11:44

Télécharger (6,83 ko)

Voir les différences:

Subject: [PATCH] api: prevent password change on get_or_create (#34950)

 src/authentic2/api_mixins.py |  2 ++
 src/authentic2/api_views.py  | 21 +++++++++++++--------
 tests/test_api.py            |  7 +++++++
 3 files changed, 22 insertions(+), 8 deletions(-)
src/authentic2/api_mixins.py
47 47
                defaults[key] = value
48 48
        with transaction.atomic():
49 49
            instance, created = self.Meta.model._default_manager.get_or_create(**kwargs)
50
            instance._a2_created = created
50 51
            if many_to_many and created:
51 52
                self.update(instance, many_to_many)
52 53
        return instance
......
78 79
                defaults[key] = value
79 80
        with transaction.atomic():
80 81
            instance, created = self.Meta.model._default_manager.get_or_create(**kwargs)
82
            instance._a2_created = created
81 83
            if many_to_many or not created:
82 84
                self.update(instance, validated_data)
83 85
        return instance
src/authentic2/api_views.py
339 339
    send_registration_email = serializers.BooleanField(write_only=True, required=False,
340 340
                                                       default=False)
341 341
    send_registration_email_next_url = serializers.URLField(write_only=True, required=False)
342
    password = serializers.CharField(max_length=128,
343
                                     default=CreateOnlyDefault(utils.generate_password),
344
                                     required=False)
342
    password = serializers.CharField(max_length=128, required=False)
345 343
    force_password_reset = serializers.BooleanField(write_only=True, required=False, default=False)
346 344

  
347 345
    def __init__(self, *args, **kwargs):
......
394 392

  
395 393
        attributes = validated_data.pop('attributes', {})
396 394
        is_verified = validated_data.pop('is_verified', {})
395
        password = validated_data.pop('password', None)
397 396
        self.check_perm('custom_user.add_user', validated_data.get('ou'))
398 397
        instance = super(BaseUserSerializer, self).create(validated_data)
398
        # prevent update on a get_or_create
399
        if not getattr(instance, '_a2_created', True):
400
            return instance
399 401
        for key, value in attributes.items():
400 402
            if is_verified.get(key):
401 403
                setattr(instance.verified_attributes, key, value)
......
405 407
            instance.verified_attributes.first_name = instance.first_name
406 408
        if is_verified.get('last_name'):
407 409
            instance.verified_attributes.last_name = instance.last_name
408
        if 'password' in validated_data:
409
            instance.set_password(validated_data['password'])
410
            instance.save()
410
        if password is not None:
411
            instance.set_password(password)
412
        else:
413
            instance.set_unusable_password()
414
        instance.save()
411 415
        if force_password_reset:
412 416
            PasswordReset.objects.get_or_create(user=instance)
413 417
        if send_registration_email and validated_data.get('email'):
......
433 437
        validated_data.pop('send_registration_email_next_url', None)
434 438
        attributes = validated_data.pop('attributes', {})
435 439
        is_verified = validated_data.pop('is_verified', {})
440
        password = validated_data.pop('password', None)
436 441
        # Double check: to move an user from one ou into another you must be administrator of both
437 442
        self.check_perm('custom_user.change_user', instance.ou)
438 443
        if 'ou' in validated_data:
......
456 461
            instance.verified_attributes.first_name = instance.first_name
457 462
        if is_verified.get('last_name'):
458 463
            instance.verified_attributes.last_name = instance.last_name
459
        if 'password' in validated_data:
460
            instance.set_password(validated_data['password'])
464
        if password is not None:
465
            instance.set_password(password)
461 466
            instance.save()
462 467
        if force_password_reset:
463 468
            PasswordReset.objects.get_or_create(user=instance)
tests/test_api.py
1163 1163
    id = resp.json['id']
1164 1164
    assert User.objects.get(id=id).first_name == 'John'
1165 1165
    assert User.objects.get(id=id).last_name == 'Doe'
1166
    password = User.objects.get(id=id).password
1166 1167

  
1167 1168
    resp = app.post_json('/api/users/?get_or_create=email', params=payload, status=201)
1168 1169
    assert id == resp.json['id']
1169 1170
    assert User.objects.get(id=id).first_name == 'John'
1170 1171
    assert User.objects.get(id=id).last_name == 'Doe'
1172
    assert User.objects.get(id=id).password == password
1171 1173

  
1174
    paylaod = {}
1172 1175
    payload['first_name'] = 'Jane'
1173 1176
    resp = app.post_json('/api/users/?update_or_create=email', params=payload, status=201)
1174 1177
    assert id == resp.json['id']
1175 1178
    assert User.objects.get(id=id).first_name == 'Jane'
1176 1179
    assert User.objects.get(id=id).last_name == 'Doe'
1180
    assert User.objects.get(id=id).password == password
1177 1181

  
1178 1182

  
1179 1183
def test_api_users_get_or_create_email_is_unique(settings, app, admin):
......
1214 1218
    id = resp.json['id']
1215 1219
    assert User.objects.get(id=id).first_name == 'John'
1216 1220
    assert User.objects.get(id=id).last_name == 'Doe'
1221
    password = User.objects.get(id=id).password
1217 1222

  
1218 1223
    resp = app.post_json('/api/users/?get_or_create=first_name&get_or_create=last_name', params=payload, status=201)
1219 1224
    assert id == resp.json['id']
1220 1225
    assert User.objects.get(id=id).first_name == 'John'
1221 1226
    assert User.objects.get(id=id).last_name == 'Doe'
1227
    assert User.objects.get(id=id).password == password
1222 1228

  
1223 1229
    payload['email'] = 'john.doe@example2.net'
1224 1230
    resp = app.post_json('/api/users/?update_or_create=first_name&update_or_create=last_name', params=payload, status=201)
1225 1231
    assert id == resp.json['id']
1226 1232
    assert User.objects.get(id=id).email == 'john.doe@example2.net'
1233
    assert User.objects.get(id=id).password == password
1227 1234

  
1228 1235

  
1229 1236
def test_api_roles_get_or_create(settings, ou1, app, admin):
1230
-