8000 554 role change endpoint by pld · Pull Request #566 · onaio/onadata · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

554 role change endpoint #566

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 22, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 100 additions & 8 deletions onadata/apps/api/tests/viewsets/test_organization_profile_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,32 +207,29 @@ def test_role_for_org_non_owner(self):
# creating org with member
self._org_create()
view = OrganizationProfileViewSet.as_view({
'get': 'retrieve',
'post': 'members'
})

User.objects.create(username='aboy')
data = {'username': 'aboy'}
user_role = 'member'
request = self.factory.post(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)
response = view(request, user='denoinc')

# getting profile
view = OrganizationProfileViewSet.as_view({
'get': 'retrieve'
})
request = self.factory.get('/', **self.extra)
response = view(request, user='denoinc')
self.assertEqual(response.status_code, 200)
self.assertIn('users', response.data.keys())

for user in response.data['users']:
username = user['user']
role = 'owner' if username == 'denoinc' else 'member'
if username == 'denoinc':
self.assertEqual(role, 'owner')
else:
self.assertEqual(role, 'member')
role = user['role']
expected_role = 'owner' if username == 'denoinc' else user_role
self.assertEqual(role, expected_role)

def test_add_members_to_org_with_anonymous_user(self):
self._org_create()
Expand Down Expand Up @@ -332,3 +329,98 @@ def test_publish_xls_form_to_organization_project(self):
self._project_create(project_data)
self._publish_xls_form_to_project()
self.assertTrue(OwnerRole.user_has_role(self.user, self.xform))

def test_put_change_role(self):
self._org_create()
newname = 'aboy'
view = OrganizationProfileViewSet.as_view({
'get': 'retrieve',
'post': 'members',
'put': 'members'
})

User.objects.create(username=newname)
data = {'username': newname}
request = self.factory.post(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data, [u'denoinc', newname])

user_role = 'editor'
data = {'username': newname, 'role': user_role}
request = self.factory.put(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data, [u'denoinc', newname])

# getting profile
request = self.factory.get('/', **self.extra)
response = view(request, user='denoinc')
self.assertEqual(response.status_code, 200)
self.assertIn('users', response.data.keys())

for user in response.data['users']:
username = user['user']
role = user['role']
expected_role = 'owner' if username == 'denoinc' else user_role
self.assertEqual(role, expected_role)

def test_put_require_role(self):
self._org_create()
newname = 'aboy'
view = OrganizationProfileViewSet.as_view({
'get': 'retrieve',
'post': 'members',
'put': 'members'
})

User.objects.create(username=newname)
data = {'username': newname}
request = self.factory.post(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data, [u'denoinc', newname])

data = {'username': newname}
request = self.factory.put(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 400)

def test_put_bad_role(self):
self._org_create()
newname = 'aboy'
view = OrganizationProfileViewSet.as_view({
'get': 'retrieve',
'post': 'members',
'put': 'members'
})

User.objects.create(username=newname)
data = {'username': newname}
request = self.factory.post(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 201)
self.assertEqual(response.data, [u'denoinc', newname])

data = {'username': newname, 'role': 42}
request = self.factory.put(
'/', data=json.dumps(data),
content_type="application/json", **self.extra)

response = view(request, user='denoinc')
self.assertEqual(response.status_code, 400)
48 changes: 43 additions & 5 deletions onadata/apps/api/viewsets/organization_profile_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
add_user_to_organization,
remove_user_from_organization)
from onadata.apps.api import permissions
from onadata.libs.mixins.object_lookup_mixin import ObjectLookupMixin
from onadata.libs.filters import OrganizationPermissionFilter
from onadata.libs.mixins.object_lookup_mixin import ObjectLookupMixin
from onadata.libs.permissions import ROLES
from onadata.libs.serializers.organization_serializer import(
OrganizationSerializer)


def _try_function_org_username(f, organization, username):
def _try_function_org_username(f, organization, username, args=None):
data = []

try:
Expand All @@ -28,12 +29,23 @@ def _try_function_org_username(f, organization, username):
[_(u"User `%(username)s` does not exist."
% {'username': username})]}
else:
f(organization, user)
if args:
f(organization, user, *args)
else:
f(organization, user)
status_code = status.HTTP_201_CREATED

return [data, status_code]


def _update_username_role(organization, username, role_cls):
f = lambda org, user, role_cls: role_cls.add(user, organization)
return _try_function_org_username(f,
organization,
username,
[role_cls])


def _add_username_to_organization(organization, username):
return _try_function_org_username(add_user_to_organization,
organization,
Expand Down Expand Up @@ -142,6 +154,21 @@ class OrganizationProfileViewSet(ObjectLookupMixin, ModelViewSet):
>
> ["member1"]

## Change the role of a user in an organization

To change the role of a user in an organization pass the username and role
`{"username": "member1", "role": "owner|manager|editor|dataentry|readonly"}`.

<pre class="prettyprint"><b>PUT</b> /api/v1/orgs/{username}/members</pre>
> Example
>
> curl -X PUT -d '{"username": "member1", "role": "editor"}' \
https://ona.io/api/v1/orgs/modilabs/members -H "Content-Type: application/json"

> Response
>
> ["member1"]

## Remove a user from an organization

To remove a user from an organization requires a JSON payload of
Expand All @@ -163,20 +190,31 @@ class OrganizationProfileViewSet(ObjectLookupMixin, ModelViewSet):
permission_classes = [permissions.DjangoObjectPermissions]
filter_backends = (OrganizationPermissionFilter,)

@action(methods=['DELETE', 'GET', 'POST'])
@action(methods=['DELETE', 'GET', 'POST', 'PUT'])
def members(self, request, *args, **kwargs):
organization = self.get_object()
status_code = status.HTTP_200_OK
data = []
username = request.DATA.get('username') or request.QUERY_PARAMS.get(
'username')

if request.method in ['DELETE', 'POST'] and not username:
if request.method in ['DELETE', 'POST', 'PUT'] and not username:
status_code = status.HTTP_400_BAD_REQUEST
data = {'username': [_(u"This field is required.")]}
elif request.method == 'POST':
data, status_code = _add_username_to_organization(
organization, username)
elif request.method == 'PUT':
role = request.DATA.get('role')
role_cls = ROLES.get(role)

if not role or not role_cls:
status_code = status.HTTP_400_BAD_REQUEST
message = (_(u"'%s' is not a valid role." % role) if role
else _(u"This field is required."))
data = {'role': [message]}
else:
_update_username_role(organization, username, role_cls)
elif request.method == 'DELETE':
data, status_code = _remove_username_to_organization(
organization, username)
Expand Down
10 changes: 10 additions & 0 deletions onadata/libs/permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from guardian.shortcuts import (
assign_perm,
remove_perm,
get_perms,
get_users_with_perms)

from onadata.apps.api.models import OrganizationProfile
Expand Down Expand Up @@ -188,6 +189,15 @@ def get_role(permissions, obj):
return role.name


def get_role_in_org(user, organization):
perms = get_perms(user, organization)

if 'is_org_owner' in perms:
return OwnerRole.name
else:
return get_role(perms, organization) or MemberRole.name


def get_object_users_with_permissions(obj, exclude=None):
"""Returns users, roles and permissions for a object.
"""
Expand Down
10 changes: 2 additions & 8 deletions onadata/libs/serializers/organization_serializer.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
from django.contrib.auth.models import User
from django.core.validators import ValidationError
from rest_framework import serializers
from guardian.shortcuts import get_perms

from onadata.apps.api import tools
from onadata.apps.api.models import OrganizationProfile
from onadata.apps.api.tools import get_organization_members
from onadata.apps.main.forms import RegistrationFormUserProfile
from onadata.libs.permissions import MemberRole, OwnerRole


def get_role_for_org(user, organization):
return OwnerRole.name if 'is_org_owner' in get_perms(
user, organization) else MemberRole.name
from onadata.libs.permissions import get_role_in_org


class OrganizationSerializer(serializers.HyperlinkedModelSerializer):
Expand Down Expand Up @@ -85,5 +79,5 @@ def get_org_permissions(self, obj):

return [{
'user': u.username,
'role': get_role_for_org(u, obj)
'role': get_role_in_org(u, obj)
} for u in members]
0