Projet

Général

Profil

roles-add-remeve-member-api-8234.patch

Josué Kouka, 01 décembre 2015 10:03

Télécharger (12,6 ko)

Voir les différences:

Subject: [PATCH 1/2] roles add/remeve member api #8234


 src/authentic2/api_urls.py  |  2 ++
 src/authentic2/api_views.py | 38 ++++++++++++++++++++++++++++++++++----
 tests/conftest.py           | 45 +++++++++++++++++++++++++++++++++++++++++----
 tests/test_api.py           | 41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 118 insertions(+), 8 deletions(-)

diff --git a/src/authentic2/api_urls.py b/src/authentic2/api_urls.py
index 1017978..aa061f5 100644
--- a/src/authentic2/api_urls.py
+++ b/src/authentic2/api_urls.py
@@ -9,5 +9,7 @@ urlpatterns = patterns('',
                            name='a2-api-password-change'),
                        url(r'^user/$', api_views.user,
                            name='a2-api-user'),
+                       url(r'^roles/(?P<role_uuid>[\w+]*)/members/(?P<member_uuid>[\w+]*)/$', api_views.roles, 
+                           name='a2-api-role-member'),
 )
 urlpatterns += api_views.router.urls
diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py
index 5c6fefc..7b14dbf 100644
--- a/src/authentic2/api_views.py
+++ b/src/authentic2/api_views.py
@@ -8,11 +8,13 @@ from django.core.exceptions import MultipleObjectsReturned
 from django.utils.translation import ugettext as _
 from django.views.decorators.vary import vary_on_headers
 from django.views.decorators.cache import cache_control
+from django.shortcuts import get_object_or_404
 
-from django_rbac.utils import get_ou_model
+from django_rbac.utils import get_ou_model, get_role_model
 
-from rest_framework import serializers
-from rest_framework.viewsets import ModelViewSet
+from rest_framework import serializers, authentication
+from rest_framework.views import APIView
+from rest_framework.viewsets import ModelViewSet, ViewSet
 from rest_framework.routers import SimpleRouter
 from rest_framework.generics import GenericAPIView
 from rest_framework.response import Response
@@ -323,6 +325,34 @@ class UsersAPI(ModelViewSet):
         self.check_perm('custom_user.delete_user', instance.ou)
         super(UsersAPI, self).perform_destroy(instance)
 
-
 router = SimpleRouter()
 router.register(r'users', UsersAPI, base_name='a2-api-users')
+
+class RolesAPI(APIView):
+    authentication_class = (authentication.BasicAuthentication)
+    permission_classes = (permissions.IsAuthenticated, HasUserAddPermission)
+
+    def initial(self, request, *args, **kwargs):
+        super(RolesAPI, self).initial(request, *args, **kwargs)
+        Role = get_role_model()
+        perm = 'a2_rbac.change_role'
+        authorized = request.user.has_perm(perm, obj=Role)
+        if not authorized:
+            raise PermissionDenied(u'User not allowed to change role') 
+
+    def dispatch(self, request, *args, **kwargs):
+        Role = get_role_model()
+        User = get_user_model()
+        self.role = get_object_or_404(Role, uuid=kwargs['role_uuid'])
+        self.member = get_object_or_404(User, uuid=kwargs['member_uuid'])
+        return super(RolesAPI, self).dispatch(request, *args, **kwargs)
+
+    def post(self, request, *args, **kwargs):
+        self.role.members.add(self.member)
+        return Response({'detail': _('User successfully added to role')}, status= status.HTTP_201_CREATED)
+
+    def delete(self, request, *args, **kwargs):
+        self.role.members.remove(self.member)
+        return Response({'detail': _('User successfully removed from role')}, status= status.HTTP_200_OK)
+
+roles = RolesAPI.as_view()
diff --git a/tests/conftest.py b/tests/conftest.py
index da27149..6f0c05f 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,12 +6,15 @@ import django_webtest
 
 from django.core.wsgi import get_wsgi_application
 from django.contrib.auth import get_user_model
-from django_rbac.utils import get_ou_model
+from django_rbac.utils import get_ou_model, get_role_model
+
+from django.contrib.contenttypes.models import ContentType
 
 from authentic2.a2_rbac.utils import get_default_ou
 
 import utils
 
+Role = get_role_model()
 
 @pytest.fixture
 def app(request):
@@ -76,12 +79,46 @@ def admin_ou2(db, ou2):
     user.roles.add(ou2.get_admin_role())
     return user
 
-@pytest.fixture(params=['superuser', 'user_ou1', 'user_ou2', 'admin_ou1', 'admin_ou2'])
-def user(request, superuser, user_ou1, user_ou2, admin_ou1, admin_ou2):
-    return locals().get(request.param)
+@pytest.fixture
+def admin_rando_role(db, role_random):
+    user = create_user(username='admin_rando', first_name='admin', last_name='rando',
+           email='admin.rando@weird.com')
+    user.roles.add(role_random.get_admin_role())
+    return user
 
+@pytest.fixture(params=['superuser', 'user_ou1', 'user_ou2', 'admin_ou1', 'admin_ou2', 'admin_rando_role'])
+def user(request, superuser, user_ou1, user_ou2, admin_ou1, admin_ou2, admin_rando_role):
+    return locals().get(request.param)
 
 @pytest.fixture
 def logged_app(app, user):
     return utils.login(app, user)
 
+@pytest.fixture
+def role_random(db):
+    return Role.objects.create(name='rando', slug='rando')
+
+@pytest.fixture
+def role_ou1(db, ou1):
+    return Role.objects.create(name='role_ou1', slug='role_ou1', ou=ou1)
+
+@pytest.fixture
+def role_ou2(db, ou2):
+    return Role.objects.create(name='role_ou2', slug='role_ou2', ou=ou2)
+
+@pytest.fixture(params=['role_random', 'role_ou1', 'role_ou2'])
+def role(request, role_random, role_ou1, role_ou2):
+    return locals().get(request.param)
+
+@pytest.fixture
+def member_rando(db):
+    return create_user(username='test', first_name='test', last_name='test',
+            email='test@test.org')
+
+@pytest.fixture
+def member_fake():
+    return type('user', (object,), {'username':'fake', 'uuid': 'fake_uuid'})
+
+@pytest.fixture(params=['member_rando','member_fake'])
+def member(request, member_rando, member_fake):
+    return locals().get(request.param)
diff --git a/tests/test_api.py b/tests/test_api.py
index 0a62b60..76e668f 100644
--- a/tests/test_api.py
+++ b/tests/test_api.py
@@ -69,3 +69,44 @@ def test_api_users_create(app, user):
         assert new_user.last_name == resp.json['last_name']
         resp2 = app.get('/api/users/%s/' % resp.json['id'])
         assert resp.json == resp2.json
+
+def test_api_role_add_member(app, user, role, member):
+    app.authorization = ('Basic', (user.username, user.username))
+    payload = {
+        'role_uuid': role.uuid,
+        'role_member': member.uuid
+    }
+
+    if member.username == 'fake' or role.name == 'fake':
+        status = 404
+    elif user.is_superuser or role.members.filter(uuid=member.uuid):
+        status = 201
+    else:
+        status = 403
+
+    resp = app.post_json('/api/roles/{0}/members/{1}/'.format(role.uuid, member.uuid), payload, status=status)
+    if status == 404:
+        pass
+    elif user.is_superuser:
+        assert resp.json['detail'] == 'User successfully added to role'
+    else:
+        assert resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role'
+
+def test_api_role_remove_member(app, user, role, member):
+    app.authorization = ('Basic', (user.username, user.username))
+
+    if member.username == 'fake' or role.name == 'fake':
+        status = 404
+    elif user.is_superuser or role.members.filter(uuid=member.uuid):
+        status = 200
+    else:
+        status = 403
+
+    resp = app.delete_json('/api/roles/{0}/members/{1}/'.format(role.uuid, member.uuid), status=status)
+  
+    if status == 404:
+        pass
+    elif user.is_superuser:
+        assert resp.json['detail'] == 'User successfully removed from role'
+    else:
+        assert (resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role')
-- 
2.6.2


From 0b1e833c92d8ce7403877c5cc866aadc308973d7 Mon Sep 17 00:00:00 2001
From: Josue Kouka <jkouka@entrouvert.com>
Date: Tue, 1 Dec 2015 10:00:01 +0100
Subject: [PATCH 2/2] improving role api tests #8234

---
 src/authentic2/api_urls.py  |  2 ++
 src/authentic2/api_views.py | 38 ++++++++++++++++++++++++++++++++++----
 tests/conftest.py           | 45 +++++++++++++++++++++++++++++++++++++++++----
 tests/test_api.py           | 41 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 118 insertions(+), 8 deletions(-)
src/authentic2/api_urls.py
9 9
                           name='a2-api-password-change'),
10 10
                       url(r'^user/$', api_views.user,
11 11
                           name='a2-api-user'),
12
                       url(r'^roles/(?P<role_uuid>[\w+]*)/members/(?P<member_uuid>[\w+]*)/$', api_views.roles, 
13
                           name='a2-api-role-member'),
12 14
)
13 15
urlpatterns += api_views.router.urls
src/authentic2/api_views.py
8 8
from django.utils.translation import ugettext as _
9 9
from django.views.decorators.vary import vary_on_headers
10 10
from django.views.decorators.cache import cache_control
11
from django.shortcuts import get_object_or_404
11 12

  
12
from django_rbac.utils import get_ou_model
13
from django_rbac.utils import get_ou_model, get_role_model
13 14

  
14
from rest_framework import serializers
15
from rest_framework.viewsets import ModelViewSet
15
from rest_framework import serializers, authentication
16
from rest_framework.views import APIView
17
from rest_framework.viewsets import ModelViewSet, ViewSet
16 18
from rest_framework.routers import SimpleRouter
17 19
from rest_framework.generics import GenericAPIView
18 20
from rest_framework.response import Response
......
323 325
        self.check_perm('custom_user.delete_user', instance.ou)
324 326
        super(UsersAPI, self).perform_destroy(instance)
325 327

  
326

  
327 328
router = SimpleRouter()
328 329
router.register(r'users', UsersAPI, base_name='a2-api-users')
330

  
331
class RolesAPI(APIView):
332
    authentication_class = (authentication.BasicAuthentication)
333
    permission_classes = (permissions.IsAuthenticated, HasUserAddPermission)
334

  
335
    def initial(self, request, *args, **kwargs):
336
        super(RolesAPI, self).initial(request, *args, **kwargs)
337
        Role = get_role_model()
338
        perm = 'a2_rbac.change_role'
339
        authorized = request.user.has_perm(perm, obj=Role)
340
        if not authorized:
341
            raise PermissionDenied(u'User not allowed to change role') 
342

  
343
    def dispatch(self, request, *args, **kwargs):
344
        Role = get_role_model()
345
        User = get_user_model()
346
        self.role = get_object_or_404(Role, uuid=kwargs['role_uuid'])
347
        self.member = get_object_or_404(User, uuid=kwargs['member_uuid'])
348
        return super(RolesAPI, self).dispatch(request, *args, **kwargs)
349

  
350
    def post(self, request, *args, **kwargs):
351
        self.role.members.add(self.member)
352
        return Response({'detail': _('User successfully added to role')}, status= status.HTTP_201_CREATED)
353

  
354
    def delete(self, request, *args, **kwargs):
355
        self.role.members.remove(self.member)
356
        return Response({'detail': _('User successfully removed from role')}, status= status.HTTP_200_OK)
357

  
358
roles = RolesAPI.as_view()
tests/conftest.py
6 6

  
7 7
from django.core.wsgi import get_wsgi_application
8 8
from django.contrib.auth import get_user_model
9
from django_rbac.utils import get_ou_model
9
from django_rbac.utils import get_ou_model, get_role_model
10

  
11
from django.contrib.contenttypes.models import ContentType
10 12

  
11 13
from authentic2.a2_rbac.utils import get_default_ou
12 14

  
13 15
import utils
14 16

  
17
Role = get_role_model()
15 18

  
16 19
@pytest.fixture
17 20
def app(request):
......
76 79
    user.roles.add(ou2.get_admin_role())
77 80
    return user
78 81

  
79
@pytest.fixture(params=['superuser', 'user_ou1', 'user_ou2', 'admin_ou1', 'admin_ou2'])
80
def user(request, superuser, user_ou1, user_ou2, admin_ou1, admin_ou2):
81
    return locals().get(request.param)
82
@pytest.fixture
83
def admin_rando_role(db, role_random):
84
    user = create_user(username='admin_rando', first_name='admin', last_name='rando',
85
           email='admin.rando@weird.com')
86
    user.roles.add(role_random.get_admin_role())
87
    return user
82 88

  
89
@pytest.fixture(params=['superuser', 'user_ou1', 'user_ou2', 'admin_ou1', 'admin_ou2', 'admin_rando_role'])
90
def user(request, superuser, user_ou1, user_ou2, admin_ou1, admin_ou2, admin_rando_role):
91
    return locals().get(request.param)
83 92

  
84 93
@pytest.fixture
85 94
def logged_app(app, user):
86 95
    return utils.login(app, user)
87 96

  
97
@pytest.fixture
98
def role_random(db):
99
    return Role.objects.create(name='rando', slug='rando')
100

  
101
@pytest.fixture
102
def role_ou1(db, ou1):
103
    return Role.objects.create(name='role_ou1', slug='role_ou1', ou=ou1)
104

  
105
@pytest.fixture
106
def role_ou2(db, ou2):
107
    return Role.objects.create(name='role_ou2', slug='role_ou2', ou=ou2)
108

  
109
@pytest.fixture(params=['role_random', 'role_ou1', 'role_ou2'])
110
def role(request, role_random, role_ou1, role_ou2):
111
    return locals().get(request.param)
112

  
113
@pytest.fixture
114
def member_rando(db):
115
    return create_user(username='test', first_name='test', last_name='test',
116
            email='test@test.org')
117

  
118
@pytest.fixture
119
def member_fake():
120
    return type('user', (object,), {'username':'fake', 'uuid': 'fake_uuid'})
121

  
122
@pytest.fixture(params=['member_rando','member_fake'])
123
def member(request, member_rando, member_fake):
124
    return locals().get(request.param)
tests/test_api.py
69 69
        assert new_user.last_name == resp.json['last_name']
70 70
        resp2 = app.get('/api/users/%s/' % resp.json['id'])
71 71
        assert resp.json == resp2.json
72

  
73
def test_api_role_add_member(app, user, role, member):
74
    app.authorization = ('Basic', (user.username, user.username))
75
    payload = {
76
        'role_uuid': role.uuid,
77
        'role_member': member.uuid
78
    }
79

  
80
    if member.username == 'fake' or role.name == 'fake':
81
        status = 404
82
    elif user.is_superuser or role.members.filter(uuid=member.uuid):
83
        status = 201
84
    else:
85
        status = 403
86

  
87
    resp = app.post_json('/api/roles/{0}/members/{1}/'.format(role.uuid, member.uuid), payload, status=status)
88
    if status == 404:
89
        pass
90
    elif user.is_superuser:
91
        assert resp.json['detail'] == 'User successfully added to role'
92
    else:
93
        assert resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role'
94

  
95
def test_api_role_remove_member(app, user, role, member):
96
    app.authorization = ('Basic', (user.username, user.username))
97

  
98
    if member.username == 'fake' or role.name == 'fake':
99
        status = 404
100
    elif user.is_superuser or role.members.filter(uuid=member.uuid):
101
        status = 200
102
    else:
103
        status = 403
104

  
105
    resp = app.delete_json('/api/roles/{0}/members/{1}/'.format(role.uuid, member.uuid), status=status)
106
  
107
    if status == 404:
108
        pass
109
    elif user.is_superuser:
110
        assert resp.json['detail'] == 'User successfully removed from role'
111
    else:
112
        assert (resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role')
72
- 
src/authentic2/api_views.py
330 330

  
331 331
class RolesAPI(APIView):
332 332
    authentication_class = (authentication.BasicAuthentication)
333
    permission_classes = (permissions.IsAuthenticated, HasUserAddPermission)
333
    permission_classes = (permissions.IsAuthenticated,)
334 334

  
335 335
    def initial(self, request, *args, **kwargs):
336 336
        super(RolesAPI, self).initial(request, *args, **kwargs)
337
        Role = get_role_model()
338 337
        perm = 'a2_rbac.change_role'
339
        authorized = request.user.has_perm(perm, obj=Role)
338
        authorized = request.user.has_perm(perm, obj=self.role)
340 339
        if not authorized:
341 340
            raise PermissionDenied(u'User not allowed to change role') 
342 341

  
tests/conftest.py
35 35
    OU = get_ou_model()
36 36
    return OU.objects.create(name='OU2', slug='ou2')
37 37

  
38
@pytest.fixture
39
def ou_rando(db):
40
    OU = get_ou_model()
41
    return OU.objects.create(name='ou_rando', slug='ou_rando')
42

  
38 43
def create_user(**kwargs):
39 44
    User = get_user_model()
40 45
    password = kwargs.pop('password', None) or kwargs['username']
......
80 85
    return user
81 86

  
82 87
@pytest.fixture
83
def admin_rando_role(db, role_random):
88
def admin_rando_role(db, role_random, ou_rando):
84 89
    user = create_user(username='admin_rando', first_name='admin', last_name='rando',
85
           email='admin.rando@weird.com')
90
           email='admin.rando@weird.com', ou=ou_rando)
86 91
    user.roles.add(role_random.get_admin_role())
87 92
    return user
88 93

  
......
95 100
    return utils.login(app, user)
96 101

  
97 102
@pytest.fixture
98
def role_random(db):
99
    return Role.objects.create(name='rando', slug='rando')
103
def role_random(db, ou_rando):
104
    return Role.objects.create(name='rando', slug='rando',  ou=ou_rando)
100 105

  
101 106
@pytest.fixture
102 107
def role_ou1(db, ou1):
tests/test_api.py
17 17
    assert resp.json['previous'] is None
18 18
    assert resp.json['next'] is None
19 19
    if user.is_superuser:
20
        count = 5
20
        count = 6
21 21
    elif user.roles.exists():
22 22
        count = 2
23 23
    else:
......
77 77
        'role_member': member.uuid
78 78
    }
79 79

  
80
    authorized = user.is_superuser or user.has_perm('a2_rbac.change_role', role)
81

  
80 82
    if member.username == 'fake' or role.name == 'fake':
81 83
        status = 404
82
    elif user.is_superuser or role.members.filter(uuid=member.uuid):
84
    elif authorized :
83 85
        status = 201
84 86
    else:
85 87
        status = 403
......
87 89
    resp = app.post_json('/api/roles/{0}/members/{1}/'.format(role.uuid, member.uuid), payload, status=status)
88 90
    if status == 404:
89 91
        pass
90
    elif user.is_superuser:
92
    elif authorized :
91 93
        assert resp.json['detail'] == 'User successfully added to role'
92 94
    else:
93
        assert resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role'
95
        assert resp.json['detail'] == 'User not allowed to change role'
94 96

  
95 97
def test_api_role_remove_member(app, user, role, member):
96 98
    app.authorization = ('Basic', (user.username, user.username))
97 99

  
100
    authorized = user.is_superuser or user.has_perm('a2_rbac.change_role', role)
101
    
98 102
    if member.username == 'fake' or role.name == 'fake':
99 103
        status = 404
100
    elif user.is_superuser or role.members.filter(uuid=member.uuid):
104
    elif authorized :
101 105
        status = 200
102 106
    else:
103 107
        status = 403
......
106 110
  
107 111
    if status == 404:
108 112
        pass
109
    elif user.is_superuser:
113
    elif authorized :
110 114
        assert resp.json['detail'] == 'User successfully removed from role'
111 115
    else:
112
        assert (resp.json['detail'] == 'Vous n\'avez pas la permission d\'effectuer cette action.' or resp.json['detail'] == 'User not allowed to change role')
116
        assert resp.json['detail'] == 'User not allowed to change role'
113
-