From 313e17e416eb7b0b2b632f014493707c5a4b0be3 Mon Sep 17 00:00:00 2001 From: Josue Kouka Date: Mon, 30 Nov 2015 11:34:38 +0100 Subject: [PATCH 1/1] 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[\w+]*)/members/(?P[\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