Skip to content
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

Ensure project owners are able to view all their collaborators from the project list #2073

Merged
merged 6 commits into from
May 7, 2021
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
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,12 @@ def test_member_sees_orgs_added_to(self):
request = self.factory.get('/', **self.extra)
response = view(request)
self.assertEqual(response.status_code, 200)
self.assertDictEqual(dict(response.data[0]), expected_data)
response_data = dict(response.data[0])
returned_users = response_data.pop('users')
expected_users = expected_data.pop('users')
self.assertDictEqual(response_data, expected_data)
for user in expected_users:
self.assertIn(user, returned_users)

def test_role_for_org_non_owner(self):
# creating org with member
Expand Down
54 changes: 44 additions & 10 deletions onadata/apps/api/tests/viewsets/test_project_viewset.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,50 @@ def test_project_list_returns_projects_for_active_users_only(self):
break
self.assertTrue(shared_project_in_response)

def test_project_list_returns_users_own_project_is_shared_to(self):
"""
Ensure that the project list responses for project owners
contains all the users the project has been shared too
"""
self._project_create()
alice_data = {'username': 'alice', 'email': '[email protected]'}
alice_profile = self._create_user_profile(alice_data)

share_project = ShareProject(
self.project, 'alice', 'manager'
)
share_project.save()

# Ensure alice is in the list of users
# When an owner requests for the project data
req = self.factory.get('/', **self.extra)
resp = self.view(req)

self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data[0]['users']), 2)
shared_users = [user['user'] for user in resp.data[0]['users']]
self.assertIn(alice_profile.user.username, shared_users)

# Ensure project managers can view all users the project was shared to
davis_data = {'username': 'davis', 'email': '[email protected]'}
davis_profile = self._create_user_profile(davis_data)
dave_extras = {
'HTTP_AUTHORIZATION': f'Token {davis_profile.user.auth_token}'
}
share_project = ShareProject(
self.project, davis_profile.user.username, 'manager'
)
share_project.save()

req = self.factory.get('/', **dave_extras)
resp = self.view(req)

self.assertEqual(resp.status_code, 200)
self.assertEqual(len(resp.data[0]['users']), 3)
shared_users = [user['user'] for user in resp.data[0]['users']]
self.assertIn(alice_profile.user.username, shared_users)
self.assertIn(self.user.username, shared_users)

def test_projects_get(self):
self._project_create()
view = ProjectViewSet.as_view({
Expand Down Expand Up @@ -2408,16 +2452,6 @@ def test_project_list_by_owner(self):
'is_org': False, 'role': 'readonly', 'user': u'alice',
'metadata': {}}, users)

request = self.factory.get('/', **self.extra)
response = view(request, pk=projectid)

# Should not list collaborators
users = response.data[0]['users']
self.assertEqual(response.status_code, 200)
self.assertNotIn({'first_name': u'Bob', 'last_name': u'erama',
'is_org': False, 'role': 'readonly',
'user': u'alice', 'metadata': {}}, users)

def test_projects_soft_delete(self):
self._project_create()

Expand Down
13 changes: 10 additions & 3 deletions onadata/libs/serializers/project_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
from onadata.apps.api.tools import (get_organization_members_team,
get_or_create_organization_owners_team)
from onadata.apps.logger.models import Project, XForm
from onadata.libs.permissions import (OwnerRole, ReadOnlyRole, get_role,
is_organization)
from onadata.libs.permissions import (
OwnerRole, ReadOnlyRole, ManagerRole, get_role, is_organization)
from onadata.libs.serializers.dataview_serializer import \
DataViewMinimalSerializer
from onadata.libs.serializers.fields.json_field import JsonField
Expand Down Expand Up @@ -133,13 +133,20 @@ def get_users(project, context, all_perms=True):
return users

data = {}
request_user_perms = [
perm.permission.codename
for perm in project.projectuserobjectpermission_set.filter(
user=context["request"].user)]
request_user_role = get_role(request_user_perms, project)
request_user_is_admin = request_user_role in [
OwnerRole.name, ManagerRole.name]
for perm in project.projectuserobjectpermission_set.all():
if perm.user_id not in data:
user = perm.user

if all_perms or user in [
context['request'].user, project.organization
]:
] or request_user_is_admin:
data[perm.user_id] = {
'permissions': [],
'is_org': is_organization(user.profile),
Expand Down