From 60cce0c5145b88092042ef93f22a77848cb4cc2c Mon Sep 17 00:00:00 2001 From: Josue Kouka Date: Fri, 16 Oct 2015 14:15:10 +0200 Subject: [PATCH] webservice add remove user from role 8234 --- src/authentic2/api_urls.py | 2 ++ src/authentic2/api_views.py | 41 ++++++++++++++++++++++++++++++-- src/authentic2/idp/saml/tests.py | 10 ++++++-- src/authentic2/tests/test_all.py | 51 +++++++++++++++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 5 deletions(-) diff --git a/src/authentic2/api_urls.py b/src/authentic2/api_urls.py index 0e470cf..6464b10 100644 --- a/src/authentic2/api_urls.py +++ b/src/authentic2/api_urls.py @@ -9,4 +9,6 @@ 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_add_member, + name='a2-api-role-member'), ) diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index b404837..aeb2b04 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -7,11 +7,14 @@ 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.http import HttpResponse -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.generics import GenericAPIView +from rest_framework.views import APIView +from rest_framework.generics import GenericAPIView from rest_framework.response import Response from rest_framework import authentication, permissions, status from rest_framework.exceptions import PermissionDenied @@ -202,3 +205,37 @@ def user(request): if request.user.is_anonymous(): return {} return request.user.to_json() + + +class RoleView(APIView): + + authentication_classes = (authentication.BasicAuthentication,) + permission_classes = (permissions.IsAuthenticated, + HasUserAddPermission) + + 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']) + + perm = 'a2_rbac.change_role' + authorized = request.user.has_perm(perm, obj=Role) + + if not authorized: + return HttpResponse(status=status.HTTP_403_FORBIDDEN) + + return super(RoleView, self).dispatch(request, *args, **kwargs) + + def post(self, request, *args, **kwargs): + self.role.members.add(self.member) + self.role.save() + return Response({'message': _('user added to role')}, status.HTTP_201_CREATED) + + def delete(self, request, *args, **kwargs): + self.role.members.remove(self.member) + self.role.save() + return Response({'message': _('user deleted from role')}, status.HTTP_200_OK) + +roles_add_member = RoleView.as_view() diff --git a/src/authentic2/idp/saml/tests.py b/src/authentic2/idp/saml/tests.py index fe8f59f..c71cfe2 100644 --- a/src/authentic2/idp/saml/tests.py +++ b/src/authentic2/idp/saml/tests.py @@ -258,8 +258,13 @@ class SamlSSOTestCase(SamlBaseTestCase): % saml_response) with self.assertRaises(lasso.ProfileRequestDeniedError): assertion = self.parse_authn_response(saml_response) - self.assertIn('samlp:StatusMessage', saml_response_decoded) - self.assertIn('User canceled login process', saml_response_decoded) + namespaces = {'samlp': lasso.SAML2_PROTOCOL_HREF} + constraints = ( + ("/samlp:Response/samlp:Status/samlp:StatusCode/@Value", lasso.SAML2_STATUS_CODE_RESPONDER), + ("/samlp:Response/samlp:Status/samlp:StatusCode/samlp:StatusCode/@Value", lasso.SAML2_STATUS_CODE_REQUEST_DENIED), + ("/samlp:Response/samlp:Status/samlp:StatusMessage", 'User canceled login process') + ) + self.assertXPathConstraints(saml_response_decoded, constraints, namespaces) else: response = client.post(url, { 'username': self.email, @@ -281,6 +286,7 @@ class SamlSSOTestCase(SamlBaseTestCase): base64.b64decode(saml_response) except TypeError: self.fail('SAMLResponse is not base64 encoded: %s' % saml_response) + login = self.parse_authn_response(saml_response) assertion = login.assertion assertion_xml = assertion.exportToXml() diff --git a/src/authentic2/tests/test_all.py b/src/authentic2/tests/test_all.py index d1f614f..75eca70 100644 --- a/src/authentic2/tests/test_all.py +++ b/src/authentic2/tests/test_all.py @@ -84,7 +84,7 @@ class SerializerTests(TestCase): 'is_superuser': False, 'last_login': u.last_login, 'date_joined': u.date_joined, - 'groups': [], + 'group': [], 'user_permissions': [], 'password': '', 'ou': None, @@ -1200,3 +1200,52 @@ class PasswordResetTest(Authentic2TestCase): response = client.post(reset_url, {'new_password1': 'newPassword1', 'new_password2': 'newPassword1'}) self.assertRedirects(response, ENTROUVERT_COM) + + +class RolesTest(Authentic2TestCase): + + def setUp(self,): + + from rest_framework import test + + self.auth_client = test.APIClient() + + User = get_user_model() + Role = get_role_model() + + role = Role.objects.first() + super_user = User.objects.create(username='super', email='super@super.com', is_superuser=True) + super_user.set_password('super_user') + super_user.save() + + cred = base64.b64encode('%s:%s' %(super_user.username.encode('utf-8'), 'super_user')) + self.auth_client.credentials(HTTP_AUTHORIZATION='Basic %s' % cred) + + user = User.objects.create(username='john', email='john@doe.com', password='password') + user.set_password('password') + user.save() + + self.role_uuid = role.uuid + self.member_uuid = user.uuid + self.url = self._build_url(role.uuid, user.uuid) + self.payload = {'role_uuid': self.role_uuid, 'member_uuid': self.member_uuid} + + def _build_url(self, role_uuid, member_uuid): + return reverse('a2-api-role-member', kwargs={'role_uuid': self.role_uuid, 'member_uuid':self.member_uuid}) + + def test_add_member_to_role(self,): + response = self.auth_client.post(self.url,content_type='application/json', data= self.payload ) + self.assertEqual(response.status_code, 201) + + def test_remove_member_from_role(self,): + response = self.auth_client.delete(self.url) + self.assertEqual(response.status_code, 200) + + def test_access_forbiden(self,): + response = self.client.post(self.url, data=self.payload) + self.assertEqual(response.status_code, 403) + + def test_role_not_found(self,): + response = self.auth_client.post(self._build_url('fake_role_uuid','fake_member_uuid'), content_type='application/json', data= self.payload) + + self.assertEqual(response.status_code, 404) -- 2.6.1