Projet

Général

Profil

0001-api-include-roles-in-users-API-25645.patch

Frédéric Péters, 30 octobre 2018 10:29

Télécharger (8,07 ko)

Voir les différences:

Subject: [PATCH] api: include roles in users API (#25645)

 src/authentic2/api_views.py | 94 ++++++++++++++++++++-----------------
 tests/test_api.py           | 55 +++++++++++++++++++++-
 2 files changed, 104 insertions(+), 45 deletions(-)
src/authentic2/api_views.py
308 308
    return hash(tuple((at.name, at.required) for at in attributes))
309 309

  
310 310

  
311
class RoleSerializer(serializers.ModelSerializer):
312
    ou = serializers.SlugRelatedField(
313
        many=False,
314
        required=False,
315
        default=CreateOnlyDefault(get_default_ou),
316
        queryset=get_ou_model().objects.all(),
317
        slug_field='slug')
318

  
319
    @property
320
    def user(self):
321
        return self.context['request'].user
322

  
323
    def __init__(self, instance=None, **kwargs):
324
        super(RoleSerializer, self).__init__(instance, **kwargs)
325
        if self.instance:
326
            self.fields['ou'].read_only = True
327

  
328
    def create(self, validated_data):
329
        ou = validated_data.get('ou')
330
        # Creating roles also means being allowed to within the OU:
331
        if not self.user.has_ou_perm('a2_rbac.add_role', ou):
332
            raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou))
333
        return super(RoleSerializer, self).create(validated_data)
334

  
335
    def update(self, instance, validated_data):
336
        # Check role-updating permissions:
337
        if not self.user.has_perm('a2_rbac.change_role', obj=instance):
338
            raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
339
        super(RoleSerializer, self).update(instance, validated_data)
340
        return instance
341

  
342
    def partial_update(self, instance, validated_data):
343
        # Check role-updating permissions:
344
        if not self.user.has_perm('a2_rbac.change_role', obj=instance):
345
            raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
346
        super(RoleSerializer, self).partial_update(instance, validated_data)
347
        return instance
348

  
349
    class Meta:
350
        model = get_role_model()
351
        fields = ('uuid', 'name', 'slug', 'ou',)
352
        extra_kwargs = {'uuid': {'read_only': True}}
353

  
354

  
355
class RoleCustomField(RoleSerializer):
356
    class Meta(RoleSerializer.Meta):
357
        fields = ('uuid', 'name', 'slug',)
358

  
359

  
311 360
class BaseUserSerializer(serializers.ModelSerializer):
312 361
    ou = serializers.SlugRelatedField(
313 362
        queryset=get_ou_model().objects.all(),
......
322 371
                                     default=CreateOnlyDefault(utils.generate_password),
323 372
                                     required=False)
324 373
    force_password_reset = serializers.BooleanField(write_only=True, required=False, default=False)
374
    roles = RoleCustomField(many=True, read_only=True)
325 375

  
326 376
    def __init__(self, *args, **kwargs):
327 377
        super(BaseUserSerializer, self).__init__(*args, **kwargs)
......
450 500
        exclude = ('date_joined', 'user_permissions', 'groups', 'last_login')
451 501

  
452 502

  
453
class RoleSerializer(serializers.ModelSerializer):
454
    ou = serializers.SlugRelatedField(
455
        many=False,
456
        required=False,
457
        default=CreateOnlyDefault(get_default_ou),
458
        queryset=get_ou_model().objects.all(),
459
        slug_field='slug')
460

  
461
    @property
462
    def user(self):
463
        return self.context['request'].user
464

  
465
    def __init__(self, instance=None, **kwargs):
466
        super(RoleSerializer, self).__init__(instance, **kwargs)
467
        if self.instance:
468
            self.fields['ou'].read_only = True
469

  
470
    def create(self, validated_data):
471
        ou = validated_data.get('ou')
472
        # Creating roles also means being allowed to within the OU:
473
        if not self.user.has_ou_perm('a2_rbac.add_role', ou):
474
            raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou))
475
        return super(RoleSerializer, self).create(validated_data)
476

  
477
    def update(self, instance, validated_data):
478
        # Check role-updating permissions:
479
        if not self.user.has_perm('a2_rbac.change_role', obj=instance):
480
            raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
481
        super(RoleSerializer, self).update(instance, validated_data)
482
        return instance
483

  
484
    def partial_update(self, instance, validated_data):
485
        # Check role-updating permissions:
486
        if not self.user.has_perm('a2_rbac.change_role', obj=instance):
487
            raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
488
        super(RoleSerializer, self).partial_update(instance, validated_data)
489
        return instance
490

  
491
    class Meta:
492
        model = get_role_model()
493
        fields = ('uuid', 'name', 'slug', 'ou',)
494
        extra_kwargs = {'uuid': {'read_only': True}}
495

  
496

  
497 503
class UsersFilter(FilterSet):
498 504
    class Meta:
499 505
        model = get_user_model()
tests/test_api.py
241 241
    if api_user.is_superuser or api_user.roles.exists():
242 242
        assert set(['ou', 'id', 'uuid', 'is_staff', 'is_superuser', 'first_name', 'last_name',
243 243
                    'date_joined', 'last_login', 'username', 'password', 'email', 'is_active',
244
                    'title', 'modified', 'email_verified']) == set(resp.json.keys())
244
                    'title', 'modified', 'email_verified', 'roles']) == set(resp.json.keys())
245 245
        assert resp.json['first_name'] == payload['first_name']
246 246
        assert resp.json['last_name'] == payload['last_name']
247 247
        assert resp.json['email'] == payload['email']
......
934 934
    assert response.json['checks'][3]['result'] is True
935 935
    assert response.json['checks'][4]['label'] == 'must contain "ok"'
936 936
    assert response.json['checks'][4]['result'] is True
937

  
938

  
939
def test_roles_in_users_api(app, admin):
940

  
941
    User = get_user_model()
942
    user1 = User(username='john.doe', email='john.doe@example.com')
943
    user1.set_password('password')
944
    user1.save()
945
    user2 = User(username='bob.smith', email='bob.smith@example.com')
946
    user2.set_password('password')
947
    user2.save()
948

  
949
    Role = get_role_model()
950
    role1 = Role.objects.create(name='Role1')
951
    role1.members.add(user1)
952
    role2 = Role.objects.create(name='Role2')
953
    role2.members.add(user1)
954
    role2.members.add(user2)
955
    role3 = Role.objects.create(name='Role3')
956
    role3.members.add(user2)
957

  
958
    app.authorization = ('Basic', (admin.username, admin.username))
959
    response = app.get(u'/api/users/', status=200)
960
    assert len(response.json['results']) == 3
961
    for user in response.json['results']:
962
        assert user['roles']
963
        for role in user['roles']:
964
            keys = ['slug', 'name', 'uuid']
965
            for key, value in role.items():
966
                assert key in keys
967
                assert value
968
                keys.remove(key)
969

  
970
    url = u'/api/users/%s/' % admin.uuid
971
    response = app.get(url, status=200)
972
    assert len(response.json['roles']) == 1
973
    assert response.json['roles'][0]['slug'] == '_a2-manager'
974

  
975
    url = u'/api/users/%s/' % user1.uuid
976
    response = app.get(url, status=200)
977
    assert len(response.json['roles']) == 2
978
    user_roles = ['Role1', 'Role2']
979
    for role in response.json['roles']:
980
        assert role['name'] in user_roles
981
        user_roles.remove(role['name'])
982

  
983
    url = u'/api/users/%s/' % user2.uuid
984
    response = app.get(url, status=200)
985
    assert len(response.json['roles']) == 2
986
    user_roles = ['Role2', 'Role3']
987
    for role in response.json['roles']:
988
        assert role['name'] in user_roles
989
        user_roles.remove(role['name'])
937
-