def test_widget_permission_change(self): self._create_widget() alice_data = {'username': '******', 'email': '*****@*****.**'} self._login_user_and_profile(alice_data) data = { 'title': "Widget those", } OwnerRole.add(self.user, self.project) OwnerRole.add(self.user, self.xform) request = self.factory.patch('/', data=data, **self.extra) response = self.view(request, pk=self.widget.pk) self.assertEquals(response.status_code, 200) self.assertEquals(response.data['title'], 'Widget those') ReadOnlyRole.add(self.user, self.project) ReadOnlyRole.add(self.user, self.xform) request = self.factory.patch('/', data=data, **self.extra) response = self.view(request, pk=self.widget.pk) self.assertEquals(response.status_code, 200) self.assertEquals(response.data['title'], 'Widget those')
def set_object_permissions(sender, instance=None, created=False, **kwargs): # seems the super is not called, have to get xform from here xform = XForm.objects.get(pk=instance.pk) if created: from onadata.libs.permissions import OwnerRole OwnerRole.add(instance.user, xform) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, xform) from onadata.libs.utils.project_utils import set_project_perms_to_xform set_project_perms_to_xform(xform, instance.project) if hasattr(instance, 'has_external_choices') \ and instance.has_external_choices: instance.xls.seek(0) f = sheet_to_csv(instance.xls.read(), 'external_choices') f.seek(0, os.SEEK_END) size = f.tell() f.seek(0) from onadata.apps.main.models.meta_data import MetaData data_file = InMemoryUploadedFile( file=f, field_name='data_file', name='itemsets.csv', content_type='text/csv', size=size, charset=None ) MetaData.media_upload(xform, data_file)
def add_xform_to_project(xform, project, creator): """Adds an xform to a project""" # remove xform from any previous relation to a project xform.projectxform_set.all().delete() # make new connection instance = ProjectXForm.objects.create( xform=xform, project=project, created_by=creator) instance.save() # check if the project is a public and make the form public if project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() for perm in get_object_users_with_permissions(project): user = perm['user'] if user != creator: ReadOnlyRole.add(user, xform) else: OwnerRole.add(user, xform) return instance
def add_xform_to_project(xform, project, creator): """Adds an xform to a project""" # remove xform from any previous relation to a project xform.projectxform_set.all().delete() # make new connection instance = ProjectXForm.objects.create(xform=xform, project=project, created_by=creator) instance.save() # check if the project is a public and make the form public if project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() for perm in get_object_users_with_permissions(project): user = perm['user'] if user != creator: ReadOnlyRole.add(user, xform) else: OwnerRole.add(user, xform) return instance
def update(self, instance, validated_data): metadata = JsonField.to_json(validated_data.get('metadata')) if metadata is None: metadata = dict() owner = validated_data.get('organization') if self.partial and metadata: if not isinstance(instance.metadata, dict): instance.metadata = {} instance.metadata.update(metadata) validated_data['metadata'] = instance.metadata if self.partial and owner: # give the new owner permissions set_owners_permission(owner, instance) if is_organization(owner.profile): owners_team = get_organization_owners_team(owner.profile) members_team = get_organization_members_team(owner.profile) OwnerRole.add(owners_team, instance) ReadOnlyRole.add(members_team, instance) # clear cache safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk)) project = super(ProjectSerializer, self)\ .update(instance, validated_data) project.xform_set.exclude(shared=project.shared)\ .update(shared=project.shared, shared_data=project.shared) return instance
def test_owner_cannot_remove_self_if_no_other_owner(self): self._project_create() view = ProjectViewSet.as_view({'put': 'share'}) data = {'username': '******', 'remove': True, 'role': 'owner'} request = self.factory.put('/', data=data, **self.extra) response = view(request, pk=self.project.pk) self.assertEqual(response.status_code, 400) error = {'remove': [u"Project requires at least one owner"]} self.assertEquals(response.data, error) self.assertTrue(OwnerRole.user_has_role(self.user, self.project)) alice_data = {'username': '******', 'email': '*****@*****.**'} profile = self._create_user_profile(alice_data) OwnerRole.add(profile.user, self.project) view = ProjectViewSet.as_view({'put': 'share'}) data = {'username': '******', 'remove': True, 'role': 'owner'} request = self.factory.put('/', data=data, **self.extra) response = view(request, pk=self.project.pk) self.assertEqual(response.status_code, 204) self.assertFalse(OwnerRole.user_has_role(self.user, self.project))
def set_object_permissions(sender, instance=None, created=False, **kwargs): # seems the super is not called, have to get xform from here xform = XForm.objects.get(pk=instance.pk) if created: from onadata.libs.permissions import OwnerRole OwnerRole.add(instance.user, xform) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, xform) from onadata.libs.utils.project_utils import set_project_perms_to_xform set_project_perms_to_xform(xform, instance.project) if hasattr(instance, 'has_external_choices') \ and instance.has_external_choices: instance.xls.seek(0) f = sheet_to_csv(instance.xls.read(), 'external_choices') f.seek(0, os.SEEK_END) size = f.tell() f.seek(0) from onadata.apps.main.models.meta_data import MetaData data_file = InMemoryUploadedFile(file=f, field_name='data_file', name='itemsets.csv', content_type='text/csv', size=size, charset=None) MetaData.media_upload(xform, data_file)
def set_project_perms_to_xform(xform, project): # allows us to still use xform.shared and xform.shared_data as before # only switch if xform.shared is False xform_is_shared = xform.shared or xform.shared_data if not xform_is_shared and project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() owners = project.organization.team_set.filter( name="{}#{}".format(project.organization.username, OWNER_TEAM_NAME), organization=project.organization) if owners: OwnerRole.add(owners[0], xform) for perm in get_object_users_with_permissions(project, with_group_users=True): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if user != xform.created_by: role.add(user, xform) else: OwnerRole.add(user, xform)
def test_move_project_owner(self): # create project and publish form to project self._publish_xls_form_to_project() alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) alice = alice_profile.user projectid = self.project.pk self.assertFalse(OwnerRole.user_has_role(alice, self.project)) view = ProjectViewSet.as_view({ 'patch': 'partial_update' }) data_patch = { 'owner': 'http://testserver/api/v1/users/%s' % alice.username } request = self.factory.patch('/', data=data_patch, **self.extra) response = view(request, pk=projectid) self.project.reload() self.assertEqual(response.status_code, 200) self.assertEquals(self.project.organization, alice) self.assertTrue(OwnerRole.user_has_role(alice, self.project))
def update(self, instance, validated_data): metadata = JsonField.to_json(validated_data.get('metadata')) if metadata is None: metadata = dict() owner = validated_data.get('organization') if self.partial and metadata: if not isinstance(instance.metadata, dict): instance.metadata = {} instance.metadata.update(metadata) validated_data['metadata'] = instance.metadata if self.partial and owner: # give the new owner permissions set_owners_permission(owner, instance) if is_organization(owner.profile): owners_team = get_or_create_organization_owners_team( owner.profile) members_team = get_organization_members_team(owner.profile) OwnerRole.add(owners_team, instance) ReadOnlyRole.add(members_team, instance) # clear cache safe_delete('{}{}'.format(PROJ_PERM_CACHE, instance.pk)) project = super(ProjectSerializer, self)\ .update(instance, validated_data) project.xform_set.exclude(shared=project.shared)\ .update(shared=project.shared, shared_data=project.shared) return instance
def test_org_members_added_to_projects(self): # create org self._org_create() view = OrganizationProfileViewSet.as_view({ 'post': 'members', 'get': 'retrieve', 'put': 'members' }) # create aboy self.profile_data['username'] = "******" aboy = self._create_user_profile().user data = {'username': '******', 'role': 'owner'} request = self.factory.post( '/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request, user='******') self.assertEqual(response.status_code, 201) # create a proj project_data = { 'owner': self.company_data['user'] } self._project_create(project_data) self._publish_xls_form_to_project() # create alice self.profile_data['username'] = "******" alice = self._create_user_profile().user alice_data = {'username': '******', 'role': 'owner'} request = self.factory.post( '/', data=json.dumps(alice_data), content_type="application/json", **self.extra) response = view(request, user='******') self.assertEqual(response.status_code, 201) # Assert that user added in org is added to teams in proj self.assertTrue(OwnerRole.user_has_role(aboy, self.project)) self.assertTrue(OwnerRole.user_has_role(alice, self.project)) self.assertTrue(OwnerRole.user_has_role(aboy, self.xform)) self.assertTrue(OwnerRole.user_has_role(alice, self.xform)) # Org admins are added to owners in project projectView = ProjectViewSet.as_view({ 'get': 'retrieve' }) request = self.factory.get('/', **self.extra) response = projectView(request, pk=self.project.pk) project_users = response.data.get('users') users_in_users = [user['user'] for user in project_users] self.assertIn('bob', users_in_users) self.assertIn('denoinc', users_in_users) self.assertIn('aboy', users_in_users) self.assertIn('alice', users_in_users)
def set_object_permissions(sender, instance=None, created=False, **kwargs): if created: from onadata.libs.permissions import OwnerRole OwnerRole.add(instance.user, instance) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, instance) from onadata.libs.utils.project_utils import set_project_perms_to_xform set_project_perms_to_xform(instance, instance.project)
def test_widget_permission_create(self): alice_data = {'username': '******', 'email': '*****@*****.**'} self._login_user_and_profile(alice_data) view = WidgetViewSet.as_view({'post': 'create'}) data = { 'title': "Widget that", 'content_object': 'http://testserver/api/v1/forms/%s' % self.xform.pk, 'description': "Test widget", 'aggregation': "Sum", 'widget_type': "charts", 'view_type': "horizontal-bar", 'column': "age", 'group_by': '' } # to do: test random user with auth but no perms request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 400) # owner OwnerRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201) # readonly ReadOnlyRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201) # dataentryonlyrole DataEntryOnlyRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201)
def test_widget_permission_create(self): alice_data = {'username': '******', 'email': '*****@*****.**'} self._login_user_and_profile(alice_data) view = WidgetViewSet.as_view({ 'post': 'create' }) data = { 'title': "Widget that", 'content_object': 'http://testserver/api/v1/forms/%s' % self.xform.pk, 'description': "Test widget", 'aggregation': "Sum", 'widget_type': "charts", 'view_type': "horizontal-bar", 'column': "age", 'group_by': '' } # to do: test random user with auth but no perms request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 400) # owner OwnerRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201) # readonly ReadOnlyRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201) # dataentryonlyrole DataEntryOnlyRole.add(self.user, self.project) request = self.factory.post('/', data=json.dumps(data), content_type="application/json", **self.extra) response = view(request) self.assertEquals(response.status_code, 201)
def set_project_perms_to_xform(xform, project): if project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() for perm in get_object_users_with_permissions(project): user = perm["user"] if user != xform.created_by: ReadOnlyRole.add(user, xform) else: OwnerRole.add(user, xform)
def test_reassign_role_owner_to_editor(self): self._publish_transportation_form() alice = self._create_user('alice', 'alice') self.assertFalse(OwnerRole.has_role(alice, self.xform)) OwnerRole.add(alice, self.xform) self.assertTrue(OwnerRole.has_role(alice, self.xform)) EditorRole.add(alice, self.xform) self.assertFalse(OwnerRole.has_role(alice, self.xform)) self.assertTrue(EditorRole.has_role(alice, self.xform))
def set_object_permissions(sender, instance=None, created=False, **kwargs): if created: from onadata.libs.permissions import OwnerRole OwnerRole.add(instance.user, instance) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, instance) from onadata.libs.utils.project_utils import set_project_perms_to_xform set_project_perms_to_xform(instance, instance.project) # clear cache safe_delete('{}{}'.format(PROJ_FORMS_CACHE, instance.project.pk)) safe_delete('{}{}'.format(IS_ORG, instance.pk))
def set_object_permissions(sender, instance=None, created=False, **kwargs): """ Apply the relevant object permissions for the form to all users who should have access to it. """ if instance.project: # clear cache safe_delete('{}{}'.format(PROJ_FORMS_CACHE, instance.project.pk)) safe_delete('{}{}'.format(PROJ_BASE_FORMS_CACHE, instance.project.pk)) # seems the super is not called, have to get xform from here xform = XForm.objects.get(pk=instance.pk) if created: from onadata.libs.permissions import OwnerRole OwnerRole.add(instance.user, xform) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, xform) from onadata.libs.utils.project_utils import set_project_perms_to_xform_async # noqa try: set_project_perms_to_xform_async.delay(xform.pk, instance.project.pk) except OperationalError: from onadata.libs.utils.project_utils import set_project_perms_to_xform # noqa set_project_perms_to_xform(xform, instance.project) if hasattr(instance, 'has_external_choices') \ and instance.has_external_choices: instance.xls.seek(0) f = sheet_to_csv(instance.xls.read(), 'external_choices') f.seek(0, os.SEEK_END) size = f.tell() f.seek(0) from onadata.apps.main.models.meta_data import MetaData data_file = InMemoryUploadedFile( file=f, field_name='data_file', name='itemsets.csv', content_type='text/csv', size=size, charset=None ) MetaData.media_upload(xform, data_file)
def test_publish_xlsform(self): view = XFormViewSet.as_view({'post': 'create'}) data = { 'owner': 'http://testserver/api/v1/users/bob', 'public': False, 'public_data': False, 'description': u'transportation_2011_07_25', 'downloadable': True, 'allows_sms': False, 'encrypted': False, 'sms_id_string': u'transportation_2011_07_25', 'id_string': u'transportation_2011_07_25', 'title': u'transportation_2011_07_25', 'bamboo_dataset': u'' } path = os.path.join(settings.PROJECT_ROOT, "apps", "main", "tests", "fixtures", "transportation", "transportation.xls") with open(path) as xls_file: post_data = {'xls_file': xls_file} request = self.factory.post('/', data=post_data, **self.extra) response = view(request) self.assertEqual(response.status_code, 201) xform = self.user.xforms.all()[0] data.update( {'url': 'http://testserver/api/v1/forms/%s' % xform.pk}) self.assertDictContainsSubset(data, response.data) self.assertTrue(OwnerRole.user_has_role(self.user, xform)) self.assertEquals("owner", response.data['users'][0]['role'])
def test_publish_xlsform(self): view = XFormViewSet.as_view({"post": "create"}) data = { "owner": "http://testserver/api/v1/users/bob", "public": False, "public_data": False, "description": u"transportation_2011_07_25", "downloadable": True, "allows_sms": False, "encrypted": False, "sms_id_string": u"transportation_2011_07_25", "id_string": u"transportation_2011_07_25", "title": u"transportation_2011_07_25", "bamboo_dataset": u"", } path = os.path.join( settings.ONADATA_DIR, "apps", "main", "tests", "fixtures", "transportation", "transportation.xls" ) with open(path) as xls_file: post_data = {"xls_file": xls_file} request = self.factory.post("/", data=post_data, **self.extra) response = view(request) self.assertEqual(response.status_code, 201) xform = self.user.xforms.all()[0] data.update({"url": "http://testserver/api/v1/forms/%s" % xform.pk}) self.assertDictContainsSubset(data, response.data) self.assertTrue(OwnerRole.user_has_role(self.user, xform)) self.assertEquals("owner", response.data["users"][0]["role"])
def test_publish_xlsform(self): view = XFormViewSet.as_view({ 'post': 'create' }) data = { 'owner': 'http://testserver/api/v1/users/bob', 'public': False, 'public_data': False, 'description': u'transportation_2011_07_25', 'downloadable': True, 'allows_sms': False, 'encrypted': False, 'sms_id_string': u'transportation_2011_07_25', 'id_string': u'transportation_2011_07_25', 'title': u'transportation_2011_07_25', 'bamboo_dataset': u'' } path = os.path.join( settings.PROJECT_ROOT, "apps", "main", "tests", "fixtures", "transportation", "transportation.xls") with open(path) as xls_file: post_data = {'xls_file': xls_file} request = self.factory.post('/', data=post_data, **self.extra) response = view(request) self.assertEqual(response.status_code, 201) xform = self.user.xforms.all()[0] data.update({ 'url': 'http://testserver/api/v1/forms/%s' % xform.pk }) self.assertDictContainsSubset(data, response.data) self.assertTrue(OwnerRole.user_has_role(self.user, xform)) self.assertEquals("owner", response.data['users'][0]['role'])
def test_publish_select_external_xlsform(self): view = XFormViewSet.as_view({'post': 'create'}) path = os.path.join(settings.PROJECT_ROOT, "apps", "api", "tests", "fixtures", "select_one_external.xlsx") with open(path) as xls_file: meta_count = MetaData.objects.count() post_data = {'xls_file': xls_file} request = self.factory.post('/', data=post_data, **self.extra) response = view(request) self.assertEqual(response.status_code, 201) self.assertEqual(meta_count + 1, MetaData.objects.count()) xform = self.user.xforms.all()[0] metadata = xform.metadata_set.all()[0] self.assertEqual('itemsets.csv', metadata.data_value) self.assertTrue(OwnerRole.user_has_role(self.user, xform)) self.assertTrue(OwnerRole.user_has_role(self.user, metadata)) self.assertEquals("owner", response.data['users'][0]['role'])
def test_publish_xls_form_to_organization_project(self): self._org_create() project_data = { 'owner': self.company_data['user'] } self._project_create(project_data) self._publish_xls_form_to_project() self.assertTrue(OwnerRole.user_has_role(self.user, self.xform))
def set_project_perms_to_xform(xform, project): # allows us to still use xform.shared and xform.shared_data as before # only switch if xform.shared is False xform_is_shared = xform.shared or xform.shared_data if not xform_is_shared and project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() for perm in get_object_users_with_permissions(project): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if user != xform.created_by: role.add(user, xform) else: OwnerRole.add(user, xform)
def set_object_permissions(sender, instance=None, created=False, **kwargs): if created: OwnerRole.add(instance.user, instance) OwnerRole.add(instance.user, instance.xform_ptr) if instance.created_by and instance.user != instance.created_by: OwnerRole.add(instance.created_by, instance) OwnerRole.add(instance.created_by, instance.xform_ptr) set_project_perms_to_xform(instance, instance.project) set_project_perms_to_xform(instance.xform_ptr, instance.project)
def test_publish_select_external_xlsform(self): view = XFormViewSet.as_view({ 'post': 'create' }) path = os.path.join( settings.PROJECT_ROOT, "apps", "api", "tests", "fixtures", "select_one_external.xlsx") with open(path) as xls_file: meta_count = MetaData.objects.count() post_data = {'xls_file': xls_file} request = self.factory.post('/', data=post_data, **self.extra) response = view(request) self.assertEqual(response.status_code, 201) self.assertEqual(meta_count + 1, MetaData.objects.count()) xform = self.user.xforms.all()[0] metadata = xform.metadata_set.all()[0] self.assertEqual('itemsets.csv', metadata.data_value) self.assertTrue(OwnerRole.user_has_role(self.user, xform)) self.assertTrue(OwnerRole.user_has_role(self.user, metadata)) self.assertEquals("owner", response.data['users'][0]['role'])
def set_project_perms_to_xform(xform, project): """ Apply project permissions to a form, this usually happens when a new form is being published or it is being moved to a new project. """ # allows us to still use xform.shared and xform.shared_data as before # only switch if xform.shared is False xform_is_shared = xform.shared or xform.shared_data if not xform_is_shared and project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() # clear existing permissions for perm in get_object_users_with_permissions( xform, with_group_users=True): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if role and (user != xform.user and project.user != user and project.created_by != user): role.remove_obj_permissions(user, xform) owners = project.organization.team_set.filter( name="{}#{}".format(project.organization.username, OWNER_TEAM_NAME), organization=project.organization) if owners: OwnerRole.add(owners[0], xform) for perm in get_object_users_with_permissions( project, with_group_users=True): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if user == xform.created_by: OwnerRole.add(user, xform) else: if role: role.add(user, xform)
def set_project_perms_to_xform(xform, project): """ Apply project permissions to a form, this usually happens when a new form is being published or it is being moved to a new project. """ # allows us to still use xform.shared and xform.shared_data as before # only switch if xform.shared is False xform_is_shared = xform.shared or xform.shared_data if not xform_is_shared and project.shared != xform.shared: xform.shared = project.shared xform.shared_data = project.shared xform.save() # clear existing permissions for perm in get_object_users_with_permissions(xform, with_group_users=True): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if role and (user != xform.user and project.user != user and project.created_by != user): role.remove_obj_permissions(user, xform) owners = project.organization.team_set.filter( name="{}#{}".format(project.organization.username, OWNER_TEAM_NAME), organization=project.organization) if owners: OwnerRole.add(owners[0], xform) for perm in get_object_users_with_permissions(project, with_group_users=True): user = perm['user'] role_name = perm['role'] role = ROLES.get(role_name) if user == xform.created_by: OwnerRole.add(user, xform) else: if role: role.add(user, xform)
def test_project_users_get_readonly_role_on_add_form(self): self._project_create() alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) ReadOnlyRole.add(alice_profile.user, self.project) self.assertTrue(ReadOnlyRole.user_has_role(alice_profile.user, self.project)) self._publish_xls_form_to_project() self.assertTrue(ReadOnlyRole.user_has_role(alice_profile.user, self.xform)) self.assertFalse(OwnerRole.user_has_role(alice_profile.user, self.xform))
def test_project_users_get_readonly_role_on_add_form(self): self._project_create() alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) ReadOnlyRole.add(alice_profile.user, self.project) self.assertTrue( ReadOnlyRole.user_has_role(alice_profile.user, self.project)) self._publish_xls_form_to_project() self.assertTrue( ReadOnlyRole.user_has_role(alice_profile.user, self.xform)) self.assertFalse( OwnerRole.user_has_role(alice_profile.user, self.xform))
def test_owner_cannot_remove_self_if_no_other_owner(self): self._project_create() view = ProjectViewSet.as_view({ 'put': 'share' }) data = {'username': '******', 'remove': True, 'role': 'owner'} request = self.factory.put('/', data=data, **self.extra) response = view(request, pk=self.project.pk) self.assertEqual(response.status_code, 400) error = {'remove': [u"Project requires at least one owner"]} self.assertEquals(response.data, error) self.assertTrue(OwnerRole.user_has_role(self.user, self.project)) alice_data = {'username': '******', 'email': '*****@*****.**'} profile = self._create_user_profile(alice_data) OwnerRole.add(profile.user, self.project) view = ProjectViewSet.as_view({ 'put': 'share' }) data = {'username': '******', 'remove': True, 'role': 'owner'} request = self.factory.put('/', data=data, **self.extra) response = view(request, pk=self.project.pk) self.assertEqual(response.status_code, 204) self.assertFalse(OwnerRole.user_has_role(self.user, self.project))
def test_submission_review_created_by_filter(self): """ Test we can filter by created_by """ review_one_data = self._create_submission_review() submission_review = SubmissionReview.objects.get( id=review_one_data['id']) self._create_user_and_login('dave', '1234') extra = {'HTTP_AUTHORIZATION': 'Token %s' % self.user.auth_token} # Ensure user is an Admin OwnerRole.add(self.user, submission_review.instance.xform) review_two_data = { 'note': "Sup ?", 'instance': review_one_data['instance'], 'status': SubmissionReview.APPROVED } view = SubmissionReviewViewSet.as_view({ 'post': 'create', 'get': 'list' }) request = self.factory.post('/', data=review_two_data, **extra) response = view(request=request) self.assertEqual(201, response.status_code) review_two_data = response.data self.assertEqual(2, len(SubmissionReview.objects.all())) # Can filter submission review list by created_by request = self.factory.get('/', {'created_by': self.user.id}, **self.extra) response = view(request=request) self.assertEqual(200, response.status_code) self.assertEqual(1, len(response.data)) self.assertEqual(review_two_data['id'], response.data[0]['id'])
def test_creator_permissions(self): """ Test that the creator of the organization has the necessary permissions """ self._org_create() request = self.factory.get('/', **self.extra) response = self.view(request) self.assertNotEqual(response.get('Cache-Control'), None) self.assertEqual(response.status_code, 200) orgs = OrganizationProfile.objects.filter(creator=self.user) self.assertEqual(orgs.count(), 1) org = orgs.first() self.assertTrue(OwnerRole.user_has_role(self.user, org)) self.assertTrue( OwnerRole.user_has_role(self.user, org.userprofile_ptr)) members_view = OrganizationProfileViewSet.as_view({ 'post': 'members', 'delete': 'members' }) # New admins should also have the required permissions self.profile_data['username'] = "******" dave = self._create_user_profile().user data = {'username': '******', 'role': 'owner'} request = self.factory.post( '/', data=json.dumps(data), content_type="application/json", **self.extra) response = members_view(request, user='******') self.assertEqual(response.status_code, 201) # Ensure user has role self.assertTrue(OwnerRole.user_has_role(dave, org)) self.assertTrue( OwnerRole.user_has_role(dave, org.userprofile_ptr)) # Permissions should be removed when the user is removed from # organization request = self.factory.delete('/', data=json.dumps(data), content_type="application/json", **self.extra) response = members_view(request, user='******') expected_results = [u'denoinc'] self.assertEqual(expected_results, response.data) # Ensure permissions are removed self.assertFalse(OwnerRole.user_has_role(dave, org)) self.assertFalse( OwnerRole.user_has_role(dave, org.userprofile_ptr))
def validate_content_object(self, value): request = self.context.get('request') users = get_users_with_perms( value.project, attach_perms=False, with_group_users=False ) profile = value.project.organization.profile # Shared or an admin in the organization if request.user not in users and not\ is_organization(profile) and not\ OwnerRole.user_has_role(request.user, profile): raise serializers.ValidationError(_( u"You don't have permission to the Project." )) return value
def test_cannot_share_project_to_owner(self): # create project and publish form to project self._publish_xls_form_to_project() data = {'username': self.user.username, 'role': ManagerRole.name, 'email_msg': 'I have shared the project with you'} request = self.factory.post('/', data=data, **self.extra) view = ProjectViewSet.as_view({ 'post': 'share' }) response = view(request, pk=self.project.pk) self.assertEqual(response.status_code, 400) self.assertEqual(response.data['username'], [u"Cannot share project" u" with the owner"]) self.assertTrue(OwnerRole.user_has_role(self.user, self.project))
def test_reassign_role_owner_to_editor(self): self._publish_transportation_form() alice = self._create_user('alice', 'alice') self.assertFalse(OwnerRole.user_has_role(alice, self.xform)) OwnerRole.add(alice, self.xform) self.assertTrue(OwnerRole.user_has_role(alice, self.xform)) self.assertTrue( OwnerRole.has_role(perms_for(alice, self.xform), self.xform)) EditorRole.add(alice, self.xform) self.assertFalse(OwnerRole.user_has_role(alice, self.xform)) self.assertTrue(EditorRole.user_has_role(alice, self.xform)) self.assertFalse( OwnerRole.has_role(perms_for(alice, self.xform), self.xform)) self.assertTrue( EditorRole.has_role(perms_for(alice, self.xform), self.xform))
def test_create_organization_creates_team_and_perms(self): # create a user - bob profile = tools.create_organization_object("modilabs", self.user) profile.save() self.assertIsInstance(profile, OrganizationProfile) organization_profile = OrganizationProfile.objects.get( user__username="******") # check organization was created self.assertTrue(organization_profile.is_organization) self.assertTrue(hasattr(profile, 'metadata')) # check that the default team was created team_name = "modilabs#%s" % Team.OWNER_TEAM_NAME team = Team.objects.get(organization=organization_profile.user, name=team_name) self.assertIsInstance(team, Team) self.assertIn(team.group_ptr, self.user.groups.all()) self.assertTrue(self.user.has_perm('api.is_org_owner')) # Assert that the user has the OwnerRole for the Organization self.assertTrue( OwnerRole.user_has_role(self.user, organization_profile))
def test_reassign_role_owner_to_editor(self): """ Test role reassignment owner to editor. """ self._publish_transportation_form() alice = self._create_user('alice', 'alice') self.assertFalse(OwnerRole.user_has_role(alice, self.xform)) OwnerRole.add(alice, self.xform) self.assertTrue(OwnerRole.user_has_role(alice, self.xform)) self.assertTrue( OwnerRole.has_role(perms_for(alice, self.xform), self.xform)) EditorRole.add(alice, self.xform) self.assertFalse(OwnerRole.user_has_role(alice, self.xform)) self.assertTrue(EditorRole.user_has_role(alice, self.xform)) self.assertFalse( OwnerRole.has_role(perms_for(alice, self.xform), self.xform)) self.assertTrue( EditorRole.has_role(perms_for(alice, self.xform), self.xform))
def _check_is_admin_or_manager( # pylint: disable=no-self-use self, user: User, xform: XForm) -> bool: return OwnerRole.user_has_role( user, xform) or ManagerRole.user_has_role(user, xform)
def publish_project_xform(request, project): """ Publish XLSForm to a project given a request. """ def set_form(): """ Instantiates QuickConverter form to publish a form. """ props = { 'project': project.pk, 'dropbox_xls_url': request.data.get('dropbox_xls_url'), 'xls_url': request.data.get('xls_url'), 'csv_url': request.data.get('csv_url'), 'text_xls_form': request.data.get('text_xls_form') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None def id_string_exists_in_account(): """ Checks if an id_string exists in an account, returns True if it exists otherwise returns False. """ try: XForm.objects.get(user=project.organization, id_string=xform.id_string) except XForm.DoesNotExist: return False return True if 'formid' in request.data: xform = get_object_or_404(XForm, pk=request.data.get('formid')) safe_delete('{}{}'.format(PROJ_FORMS_CACHE, xform.project.pk)) safe_delete('{}{}'.format(PROJ_BASE_FORMS_CACHE, xform.project.pk)) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) msg = 'Form with the same id_string already exists in this account' # Without this check, a user can't transfer a form to projects that # he/she owns because `id_string_exists_in_account` will always # return true if project.organization != xform.user and \ id_string_exists_in_account(): raise exceptions.ParseError(_(msg)) xform.user = project.organization xform.project = project try: with transaction.atomic(): xform.save() except IntegrityError: raise exceptions.ParseError(_(msg)) else: # First assign permissions to the person who uploaded the form OwnerRole.add(request.user, xform) try: # Next run async task to apply all other perms set_project_perms_to_xform_async.delay(xform.pk, project.pk) except OperationalError: # Apply permissions synchrounously set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def set_owners_permission(user, project): """Give the user owner permission""" OwnerRole.add(user, project)
def publish_project_xform(request, project): """ Publish XLSForm to a project given a request. """ def set_form(): """ Instantiates QuickConverter form to publish a form. """ props = { 'project': project.pk, 'dropbox_xls_url': request.data.get('dropbox_xls_url'), 'xls_url': request.data.get('xls_url'), 'csv_url': request.data.get('csv_url'), 'text_xls_form': request.data.get('text_xls_form') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None def id_string_exists_in_account(): """ Checks if an id_string exists in an account, returns True if it exists otherwise returns False. """ try: XForm.objects.get( user=project.organization, id_string=xform.id_string) except XForm.DoesNotExist: return False return True if 'formid' in request.data: xform = get_object_or_404(XForm, pk=request.data.get('formid')) safe_delete('{}{}'.format(PROJ_FORMS_CACHE, xform.project.pk)) safe_delete('{}{}'.format(PROJ_BASE_FORMS_CACHE, xform.project.pk)) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) msg = 'Form with the same id_string already exists in this account' # Without this check, a user can't transfer a form to projects that # he/she owns because `id_string_exists_in_account` will always # return true if project.organization != xform.user and \ id_string_exists_in_account(): raise exceptions.ParseError(_(msg)) xform.user = project.organization xform.project = project try: with transaction.atomic(): xform.save() except IntegrityError: raise exceptions.ParseError(_(msg)) else: # First assign permissions to the person who uploaded the form OwnerRole.add(request.user, xform) try: # Next run async task to apply all other perms set_project_perms_to_xform_async.delay(xform.pk, project.pk) except OperationalError: # Apply permissions synchrounously set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def test_form_id_filter_for_require_auth_account(self): """ Test formList formID filter for account that requires authentication """ # Bob submit forms xls_path = os.path.join(settings.PROJECT_ROOT, "apps", "main", "tests", "fixtures", "tutorial.xls") self._publish_xls_form_to_project(xlsform_path=xls_path) xls_file_path = os.path.join(settings.PROJECT_ROOT, "apps", "logger", "fixtures", "external_choice_form_v1.xlsx") self._publish_xls_form_to_project(xlsform_path=xls_file_path) # Set require auth to true self.user.profile.require_auth = True self.user.profile.save() request = self.factory.get('/', {'formID': self.xform.id_string}) response = self.view(request, username=self.user.username) self.assertEqual(response.status_code, 401) # Test for authenticated user but unrecognized formID auth = DigestAuth('bob', 'bobbob') request = self.factory.get('/', {'formID': 'unrecognizedID'}) request.META.update(auth(request.META, response)) response = self.view(request, username=self.user.username) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, []) # Test for authenticated user and valid formID request = self.factory.get('/', {'formID': self.xform.id_string}) self.assertTrue(self.user.profile.require_auth) response = self.view(request, username=self.user.username) self.assertEqual(response.status_code, 401) auth = DigestAuth('bob', 'bobbob') request.META.update(auth(request.META, response)) response = self.view(request, username=self.user.username) self.assertEqual(response.status_code, 200) path = os.path.join( os.path.dirname(__file__), '..', 'fixtures', 'formList2.xml') with open(path, encoding='utf-8') as f: form_list = f.read().strip() data = {"hash": self.xform.hash, "pk": self.xform.pk, 'version': self.xform.version} content = response.render().content.decode('utf-8') self.assertEqual(content, form_list % data) # Test for shared forms # Create user Alice alice_data = { 'username': '******', 'email': '*****@*****.**', 'password1': 'alice', 'password2': 'alice' } alice_profile = self._create_user_profile(alice_data) # check that she can authenticate successfully request = self.factory.get('/') response = self.view(request) self.assertEqual(response.status_code, 401) auth = DigestAuth('alice', 'alice') request.META.update(auth(request.META, response)) response = self.view(request) self.assertEqual(response.status_code, 200) self.assertFalse( ReadOnlyRole.user_has_role(alice_profile.user, self.project)) # share Bob's project with Alice data = { 'username': '******', 'role': ReadOnlyRole.name } request = self.factory.post('/', data=data, **self.extra) share_view = ProjectViewSet.as_view({'post': 'share'}) project_id = self.project.pk response = share_view(request, pk=project_id) self.assertEqual(response.status_code, 204) self.assertTrue( ReadOnlyRole.user_has_role(alice_profile.user, self.project)) request = self.factory.get('/', {'formID': self.xform.id_string}) response = self.view(request) self.assertEqual(response.status_code, 401) auth = DigestAuth('alice', 'alice') request.META.update(auth(request.META, response)) response = self.view(request, username='******') self.assertEqual(response.status_code, 200) path = os.path.join( os.path.dirname(__file__), '..', 'fixtures', 'formList2.xml') with open(path, encoding='utf-8') as f: form_list = f.read().strip() data = {"hash": self.xform.hash, "pk": self.xform.pk, "version": self.xform.version} content = response.render().content.decode('utf-8') self.assertEqual(content, form_list % data) # Bob's profile bob_profile = self.user # Submit form as Alice self._login_user_and_profile(extra_post_data=alice_data) self.assertEqual(self.user.username, 'alice') path = os.path.join( settings.PROJECT_ROOT, "apps", "main", "tests", "fixtures", "good_eats_multilang", "good_eats_multilang.xls") self._publish_xls_form_to_project(xlsform_path=path) self.assertTrue(OwnerRole.user_has_role(alice_profile.user, self.xform)) # Share Alice's form with Bob ReadOnlyRole.add(bob_profile, self.xform) self.assertTrue(ReadOnlyRole.user_has_role(bob_profile, self.xform)) # Get unrecognized formID as bob request = self.factory.get('/', {'formID': 'unrecognizedID'}) response = self.view(request, username=bob_profile.username) self.assertEqual(response.status_code, 401) auth = DigestAuth('bob', 'bobbob') request.META.update(auth(request.META, response)) response = self.view(request, username=bob_profile.username) self.assertEqual(response.status_code, 200) self.assertEqual(response.data, []) # Get Alice's form as Bob request = self.factory.get('/', {'formID': 'good_eats_multilang'}) response = self.view(request, username=bob_profile.username) self.assertEqual(response.status_code, 401) auth = DigestAuth('bob', 'bobbob') request.META.update(auth(request.META, response)) response = self.view(request, username=bob_profile.username) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), 1) self.assertEqual(response.data[0]['formID'], 'good_eats_multilang')
def handle(self, *args, **options): # XForms for xform in queryset_iterator(XForm.objects.all()): OwnerRole.add(xform.user, xform) # UserProfile for profile in queryset_iterator(UserProfile.objects.all()): set_api_permissions_for_user(profile.user) OwnerRole.add(profile.user, profile) if profile.created_by is not None: OwnerRole.add(profile.created_by, profile) # OrganizationProfile for profile in queryset_iterator(OrganizationProfile.objects.all()): OwnerRole.add(profile.user, profile) if profile.created_by is not None: OwnerRole.add(profile.created_by, profile) if profile.creator is not None: OwnerRole.add(profile.creator, profile) # Project for project in queryset_iterator(Project.objects.all()): OwnerRole.add(project.organization, project) OwnerRole.add(project.created_by, project)