Projet

Général

Profil

0004-api-manage-verified-attributes-fixes-28962.patch

Benjamin Dauvergne, 14 décembre 2018 00:43

Télécharger (9,66 ko)

Voir les différences:

Subject: [PATCH 4/4] api: manage verified attributes (fixes #28962)

 src/authentic2/api_views.py          | 28 +++++++++++++-
 src/authentic2/custom_user/models.py | 20 ++++++++++
 tests/test_api.py                    | 55 ++++++++++++++++++++++++++--
 3 files changed, 98 insertions(+), 5 deletions(-)
src/authentic2/api_views.py
363 363
                            kwargs):
364 364
                        kwargs['allow_blank'] = True
365 365
                self.fields[at.name] = field_class(**kwargs)
366
            self.fields[at.name + '_verified'] = serializers.BooleanField(
367
                source='is_verified.%s' % at.name, required=False)
366 368
        for key in self.fields:
367 369
            if key in app_settings.A2_REQUIRED_FIELDS:
368 370
                self.fields[key].required = True
......
383 385
        force_password_reset = validated_data.pop('force_password_reset', False)
384 386

  
385 387
        attributes = validated_data.pop('attributes', {})
388
        is_verified = validated_data.pop('is_verified', {})
386 389
        self.check_perm('custom_user.add_user', validated_data.get('ou'))
387 390
        instance = super(BaseUserSerializer, self).create(validated_data)
388 391
        for key, value in attributes.iteritems():
389
            setattr(instance.attributes, key, value)
392
            if is_verified.get(key):
393
                setattr(instance.verified_attributes, key, value)
394
            else:
395
                setattr(instance.attributes, key, value)
396
        if is_verified.get('first_name'):
397
            instance.verified_attributes.first_name = instance.first_name
398
        if is_verified.get('last_name'):
399
            instance.verified_attributes.last_name = instance.last_name
390 400
        if 'password' in validated_data:
391 401
            instance.set_password(validated_data['password'])
392 402
            instance.save()
......
414 424
        validated_data.pop('send_registration_email', False)
415 425
        validated_data.pop('send_registration_email_next_url', None)
416 426
        attributes = validated_data.pop('attributes', {})
427
        is_verified = validated_data.pop('is_verified', {})
417 428
        # Double check: to move an user from one ou into another you must be administrator of both
418 429
        self.check_perm('custom_user.change_user', instance.ou)
419 430
        if 'ou' in validated_data:
420 431
            self.check_perm('custom_user.change_user', validated_data.get('ou'))
421 432
        super(BaseUserSerializer, self).update(instance, validated_data)
422 433
        for key, value in attributes.iteritems():
423
            setattr(instance.attributes, key, value)
434
            if is_verified.get(key):
435
                setattr(instance.verified_attributes, key, value)
436
            else:
437
                setattr(instance.attributes, key, value)
438
        for key in is_verified:
439
            if key not in attributes:
440
                if is_verified.get(key):
441
                    setattr(instance.verified_attributes, key, getattr(instance.attributes, key))
442
                else:
443
                    setattr(instance.attributes, key, getattr(instance.attributes, key))
444
        if is_verified.get('first_name'):
445
            instance.verified_attributes.first_name = instance.first_name
446
        if is_verified.get('last_name'):
447
            instance.verified_attributes.last_name = instance.last_name
424 448
        if 'password' in validated_data:
425 449
            instance.set_password(validated_data['password'])
426 450
            instance.save()
src/authentic2/custom_user/models.py
36 36
        values = {}
37 37
        super(Attributes, self).__setattr__('values', values)
38 38
        for atv in self.owner.attribute_values.all():
39
            if verified and not atv.verified:
40
                continue
39 41
            try:
40 42
                attribute = at_map[atv.attribute_id]
41 43
            except KeyError:
......
73 75
        return getattr(obj, cache_name)
74 76

  
75 77

  
78
class IsVerified(object):
79
    def __init__(self, user):
80
        self.user = user
81

  
82
    def __getattr__(self, name):
83
        v = getattr(self.user.attributes, name, None)
84
        return (
85
            v is not None and
86
            v == getattr(self.user.verified_attributes, name, None)
87
        )
88

  
89

  
90
class IsVerifiedDescriptor(object):
91
    def __get__(self, obj, objtype):
92
        return IsVerified(obj)
93

  
94

  
76 95
class User(AbstractBaseUser, PermissionMixin):
77 96
    """
78 97
    An abstract base class implementing a fully featured User model with
......
111 130
    objects = UserManager.from_queryset(UserQuerySet)()
112 131
    attributes = AttributesDescriptor()
113 132
    verified_attributes = AttributesDescriptor(verified=True)
133
    is_verified = IsVerifiedDescriptor()
114 134

  
115 135
    attribute_values = GenericRelation('authentic2.AttributeValue')
116 136

  
tests/test_api.py
249 249

  
250 250
    resp = app.post_json('/api/users/', params=payload, status=status)
251 251
    if api_user.is_superuser or api_user.roles.exists():
252
        assert set(['ou', 'id', 'uuid', 'is_staff', 'is_superuser', 'first_name', 'last_name',
253
                    'date_joined', 'last_login', 'username', 'password', 'email', 'is_active',
254
                    'title', 'modified', 'email_verified']) == set(resp.json.keys())
252
        assert set(['ou', 'id', 'uuid', 'is_staff', 'is_superuser',
253
                    'first_name', 'first_name_verified', 'last_name',
254
                    'last_name_verified', 'date_joined', 'last_login',
255
                    'username', 'password', 'email', 'is_active', 'title',
256
                    'title_verified', 'modified', 'email_verified']) == set(resp.json.keys())
255 257
        assert resp.json['first_name'] == payload['first_name']
256 258
        assert resp.json['last_name'] == payload['last_name']
257 259
        assert resp.json['email'] == payload['email']
......
260 262
        assert resp.json['uuid']
261 263
        assert resp.json['id']
262 264
        assert resp.json['date_joined']
265
        assert not resp.json['first_name_verified']
266
        assert not resp.json['last_name_verified']
267
        assert not resp.json['title_verified']
263 268
        if api_user.is_superuser:
264 269
            assert resp.json['ou'] == 'default'
265 270
        elif api_user.roles.exists():
......
271 276
        assert new_user.first_name == resp.json['first_name']
272 277
        assert new_user.last_name == resp.json['last_name']
273 278
        assert AttributeValue.objects.with_owner(new_user).count() == 3
279
        assert AttributeValue.objects.with_owner(new_user).filter(verified=True).count() == 0
274 280
        assert AttributeValue.objects.with_owner(new_user).filter(attribute=at).exists()
275 281
        assert (AttributeValue.objects.with_owner(new_user).get(attribute=at).content ==
276 282
                payload['title'])
......
286 292
        resp = app.get('/api/users/1234567890/')
287 293
        assert 'title' not in resp.json
288 294

  
295
    at.disabled = False
296
    at.save()
297
    payload = {
298
        'username': 'john.doe2',
299
        'first_name': 'John',
300
        'first_name_verified': True,
301
        'last_name': 'Doe',
302
        'last_name_verified': True,
303
        'email': 'john.doe@example.net',
304
        'password': 'password',
305
        'title': 'Mr',
306
        'title_verified': True,
307
    }
308
    if api_user.is_superuser:
309
        status = 201
310
    elif api_user.roles.exists():
311
        status = 201
312
        payload['ou'] = api_user.ou.slug
313
    else:
314
        status = 403
315

  
316
    resp = app.post_json('/api/users/', params=payload, status=status)
317
    if api_user.is_superuser or api_user.roles.exists():
318
        assert set(['ou', 'id', 'uuid', 'is_staff', 'is_superuser',
319
                    'first_name', 'first_name_verified', 'last_name',
320
                    'last_name_verified', 'date_joined', 'last_login',
321
                    'username', 'password', 'email', 'is_active', 'title',
322
                    'title_verified', 'modified', 'email_verified']) == set(resp.json.keys())
323
        user = get_user_model().objects.get(pk=resp.json['id'])
324
        assert AttributeValue.objects.with_owner(user).filter(verified=True).count() == 3
325
        assert AttributeValue.objects.with_owner(user).filter(verified=False).count() == 0
326
        assert user.verified_attributes.first_name == 'John'
327
        assert user.verified_attributes.last_name == 'Doe'
328
        assert user.verified_attributes.title == 'Mr'
329
        assert resp.json['first_name_verified']
330
        assert resp.json['last_name_verified']
331
        assert resp.json['title_verified']
332
        resp2 = app.patch_json('/api/users/%s/' % resp.json['uuid'],
333
                               params={'title_verified': False})
334
        assert resp.json['first_name_verified']
335
        assert resp.json['last_name_verified']
336
        assert not resp2.json['title_verified']
337

  
289 338

  
290 339
def test_api_users_create_email_is_unique(settings, app, superuser):
291 340
    from django.contrib.auth import get_user_model
292
-