Projet

Général

Profil

0001-add-role-creation-API-20706.patch

Paul Marillonnet, 28 février 2018 15:20

Télécharger (9,81 ko)

Voir les différences:

Subject: [PATCH] add role-creation API (#20706)

 src/authentic2/api_views.py |  59 +++++++++++++++++
 tests/conftest.py           |   4 +-
 tests/test_api.py           | 156 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 217 insertions(+), 2 deletions(-)
src/authentic2/api_views.py
444 444
        exclude = ('date_joined', 'user_permissions', 'groups', 'last_login')
445 445

  
446 446

  
447
class RoleSerializer(serializers.ModelSerializer):
448
    ou = serializers.SlugRelatedField(
449
        many=False,
450
        required=False,
451
        default=get_default_ou,
452
        queryset=get_ou_model().objects.all(),
453
        slug_field='slug')
454

  
455
    @property
456
    def user(self):
457
        return self.context['request'].user
458

  
459
    def __init__(self, instance=None, **kwargs):
460
        super(RoleSerializer, self).__init__(instance, **kwargs)
461
        if self.instance:
462
            self.fields['ou'].read_only = True
463

  
464
    def create(self, validated_data):
465
        ou = validated_data.get('ou')
466
        # Creating roles also means being allowed to within the OU:
467
        if not self.user.has_ou_perm('a2_rbac.add_role', ou):
468
            raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou))
469
        return super(RoleSerializer, self).create(validated_data)
470

  
471
    def update(self, instance, validated_data):
472
        # Check role-updating permissions:
473
        if not self.user.has_perm('a2_rbac.change_role', obj=instance):
474
            raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
475
        super(RoleSerializer, self).update(instance, validated_data)
476
        return instance
477

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

  
485
    class Meta:
486
        model = get_role_model()
487
        fields = ('uuid', 'name', 'slug', 'description', 'ou',)
488
        extra_kwargs = {'uuid': {'read_only': True}}
489

  
490

  
447 491
class UsersFilter(FilterSet):
448 492
    class Meta:
449 493
        model = get_user_model()
......
576 620
        return Response({'result': 1})
577 621

  
578 622

  
623
class RolesAPI(ExceptionHandlerMixin, ModelViewSet):
624
    permission_classes = (permissions.IsAuthenticated,)
625
    serializer_class = RoleSerializer
626
    lookup_field = 'slug'
627

  
628
    def get_queryset(self):
629
        return self.request.user.filter_by_perm('a2_rbac.view_role', get_role_model().objects.all())
630

  
631
    def perform_destroy(self, instance):
632
        if not self.request.user.has_perm(perm='a2_rbac.delete_role', obj=instance):
633
            raise PermissionDenied(u'User %s can\'t create role %s' % (request.user, instance))
634
        super(RolesAPI, self).perform_destroy(instance)
635

  
636

  
579 637
class RoleMembershipsAPI(ExceptionHandlerMixin, APIView):
580 638
    permission_classes = (permissions.IsAuthenticated,)
581 639

  
......
620 678
router = SimpleRouter()
621 679
router.register(r'users', UsersAPI, base_name='a2-api-users')
622 680
router.register(r'ous', OrganizationalUnitAPI, base_name='a2-api-ous')
681
router.register(r'roles', RolesAPI, base_name='a2-api-roles')
623 682

  
624 683

  
625 684
class CheckPasswordSerializer(serializers.Serializer):
tests/conftest.py
134 134

  
135 135

  
136 136
@pytest.fixture
137
def simple_role(db):
138
    return Role.objects.create(name='simple role', slug='simple-role', ou=get_default_ou())
137
def simple_role(db, ou1):
138
    return Role.objects.create(name='simple role', slug='simple-role', ou=ou1)
139 139

  
140 140

  
141 141
@pytest.fixture
tests/test_api.py
668 668

  
669 669
    assert mail.to[0] == new_email
670 670
    assert 'http://testserver/accounts/change-email/verify/' in mail.body
671

  
672

  
673
def test_api_delete_role(app, admin_ou1, simple_role):
674
    app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username))
675
    Role = get_role_model()
676

  
677
    app.delete('/api/roles/simple-role/')
678
    assert not len(Role.objects.filter(slug='simple-role'))
679

  
680

  
681
def test_api_delete_role_unauthorized(app, simple_user, simple_role):
682
    app.authorization = ('Basic', (simple_user.username, simple_user.username))
683
    Role = get_role_model()
684

  
685
    app.delete('/api/roles/simple-role/', status=404)
686
    assert len(Role.objects.filter(slug='simple-role'))
687

  
688

  
689
def test_api_patch_role(app, admin_ou1, simple_role):
690
    app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username))
691
    Role = get_role_model()
692

  
693
    role_data = {
694
        'slug': 'updated-role',
695
    }
696
    resp = app.patch_json('/api/roles/simple-role/', params=role_data)
697
    assert not len(Role.objects.filter(slug='simple-role'))
698
    assert len(Role.objects.filter(slug='updated-role'))
699

  
700
    # The role API won't change the organizational unit attribute:
701
    role = Role.objects.get(slug='updated-role')
702
    assert role.ou.slug == get_default_ou().slug
703
    assert role.ou.slug != 'ou1'
704

  
705

  
706
def test_api_patch_role_unauthorized(app, simple_user, simple_role):
707
    app.authorization = ('Basic', (simple_user.username, simple_user.username))
708
    Role = get_role_model()
709

  
710
    role_data = {
711
        'slug': 'updated-role',
712
    }
713
    resp = app.patch_json('/api/roles/simple-role/', params=role_data, status=404)
714
    assert len(Role.objects.filter(slug='simple-role'))
715
    assert not len(Role.objects.filter(slug='updated-role'))
716

  
717

  
718
def test_api_put_role(app, admin_ou1, simple_role, ou1):
719
    app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username))
720
    Role = get_role_model()
721

  
722
    role_data = {
723
        'name': 'updated-role',
724
        'slug': 'updated-role',
725
        'ou': 'ou1'
726
    }
727
    resp = app.put_json('/api/roles/simple-role/', params=role_data)
728
    assert not len(Role.objects.filter(slug='simple-role'))
729
    assert len(Role.objects.filter(slug='updated-role'))
730

  
731
    # The role API won't change the organizational unit attribute:
732
    role = Role.objects.get(slug='updated-role')
733
    assert role.ou.slug == get_default_ou().slug
734
    assert role.ou.slug != 'ou1'
735

  
736

  
737
def test_api_put_role_unauthorized(app, simple_user, simple_role, ou1):
738
    app.authorization = ('Basic', (simple_user.username, simple_user.username))
739
    Role = get_role_model()
740

  
741
    role_data = {
742
        'name': 'updated-role',
743
        'slug': 'updated-role',
744
        'ou': 'ou1'
745
    }
746
    resp = app.put_json('/api/roles/simple-role/', params=role_data, status=404)
747
    assert len(Role.objects.filter(slug='simple-role'))
748
    assert not len(Role.objects.filter(slug='updated-role'))
749

  
750

  
751
def test_api_post_role(app, admin_ou1, ou1):
752
    app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username))
753

  
754
    role_data = {
755
        'slug': 'coffee-manager',
756
        'name': 'Coffee Manager',
757
        'ou': 'ou1'
758
        }
759
    resp = app.post_json('/api/roles/', params=role_data)
760
    assert isinstance(resp.json, dict)
761
    Role = get_role_model()
762

  
763
    # Check attribute values against the server's response:
764
    for key, value in role_data.items():
765
        assert key in resp.json.keys()
766
        assert value in resp.json.values()
767

  
768
    # Check attributes values against the DB:
769
    posted_role = Role.objects.get(slug='coffee-manager')
770
    assert posted_role.slug == role_data['slug']
771
    assert posted_role.name == role_data['name']
772
    assert posted_role.ou.slug == 'ou1'
773

  
774

  
775
def test_api_post_role_no_ou(app, superuser):
776
    app.authorization = ('Basic', (superuser.username, superuser.username))
777
    Role = get_role_model()
778

  
779
    role_data = {
780
        'slug': 'tea-manager',
781
        'name': 'Tea Manager',
782
        }
783
    resp = app.post_json('/api/roles/', params=role_data)
784
    new_role = Role.objects.get(slug='tea-manager')
785
    default_ou = get_default_ou()
786
    assert new_role.ou == default_ou
787

  
788

  
789
def test_api_post_role_unauthorized(app, simple_user, ou1):
790
    app.authorization = ('Basic', (simple_user.username, simple_user.username))
791
    Role = get_role_model()
792

  
793
    role_data = {
794
        'slug': 'mocca-manager',
795
        'name': 'Mocca Manager',
796
        'ou': 'ou1'
797
        }
798

  
799
    resp = app.post_json('/api/roles/', params=role_data, status=403)
800
    assert not len(Role.objects.filter(slug='mocca-manager'))
801

  
802

  
803
def test_api_get_role_description(app, admin_rando_role, role_random):
804
    app.authorization = ('Basic', (admin_rando_role.username, admin_rando_role.username))
805
    resp = app.get('/api/roles/rando/')
806

  
807
    assert resp.json['slug'] == 'rando'
808
    assert resp.json['ou'] == 'ou_rando'
809

  
810

  
811
def test_api_get_role_not_found(app, superuser):
812
    app.authorization = ('Basic', (superuser.username, superuser.username))
813
    resp = app.get('/api/roles/thisisnotavalidroleslug/', status=404)
814

  
815

  
816
def test_api_get_role_list(app, admin_ou1, simple_role, role_random):
817
    app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username))
818
    resp = app.get('/api/roles/')
819

  
820
    role_fields = ['slug', 'uuid', 'name', 'ou']
821

  
822
    assert len(resp.json['results'])
823

  
824
    for role_dict in resp.json['results']:
825
        for field in role_fields:
826
            assert field in role_dict
671
-