roles-add-remeve-member-api-8234.patch
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 |
- |