def test_form_clone_endpoint(self): self._publish_xls_form_to_project() alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) view = XFormViewSet.as_view({ 'post': 'clone' }) formid = self.xform.pk count = XForm.objects.count() data = {'username': '******'} request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertEqual(response.status_code, 400) data = {'username': '******'} request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertFalse(self.user.has_perm('can_add_xform', alice_profile)) self.assertEqual(response.status_code, 403) ManagerRole.add(self.user, alice_profile) request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertTrue(self.user.has_perm('can_add_xform', alice_profile)) self.assertEqual(response.status_code, 201) self.assertEqual(count + 1, XForm.objects.count())
def test_form_clone_endpoint(self): self._publish_xls_form_to_project() alice_data = {"username": "******", "email": "*****@*****.**"} alice_profile = self._create_user_profile(alice_data) view = XFormViewSet.as_view({"post": "clone"}) formid = self.xform.pk count = XForm.objects.count() data = {"username": "******"} request = self.factory.post("/", data=data, **self.extra) response = view(request, pk=formid) self.assertEqual(response.status_code, 400) data = {"username": "******"} request = self.factory.post("/", data=data, **self.extra) response = view(request, pk=formid) self.assertFalse(self.user.has_perm("can_add_xform", alice_profile)) self.assertEqual(response.status_code, 403) ManagerRole.add(self.user, alice_profile) request = self.factory.post("/", data=data, **self.extra) response = view(request, pk=formid) self.assertTrue(self.user.has_perm("can_add_xform", alice_profile)) self.assertEqual(response.status_code, 201) self.assertEqual(count + 1, XForm.objects.count())
def test_project_manager_can_assign_form_to_project_no_perm(self): # user must have owner/manager permissions view = ProjectViewSet.as_view({ 'post': 'forms', 'get': 'retrieve' }) self._publish_xls_form_to_project() # alice user is not manager to both projects alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) self.assertFalse(ManagerRole.user_has_role(alice_profile.user, self.project)) formid = self.xform.pk project_name = u'another project' self._project_create({'name': project_name}) self.assertTrue(self.project.name == project_name) ManagerRole.add(alice_profile.user, self.project) self.assertTrue(ManagerRole.user_has_role(alice_profile.user, self.project)) self._login_user_and_profile(alice_data) project_id = self.project.pk post_data = {'formid': formid} request = self.factory.post('/', data=post_data, **self.extra) response = view(request, pk=project_id) self.assertEqual(response.status_code, 403)
def test_form_clone_endpoint(self): self._publish_xls_form_to_project() alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) view = XFormViewSet.as_view({'post': 'clone'}) formid = self.xform.pk count = XForm.objects.count() data = {'username': '******'} request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertEqual(response.status_code, 400) self.assertEqual(response.get('Last-Modified'), None) data = {'username': '******'} request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertFalse(self.user.has_perm('can_add_xform', alice_profile)) self.assertEqual(response.status_code, 403) ManagerRole.add(self.user, alice_profile) request = self.factory.post('/', data=data, **self.extra) response = view(request, pk=formid) self.assertTrue(self.user.has_perm('can_add_xform', alice_profile)) self.assertEqual(response.status_code, 201) self.assertEqual(count + 1, XForm.objects.count())
def test_manager_role_add(self): bob, created = UserProfile.objects.get_or_create(user=self.user) alice = self._create_user('alice', 'alice') self.assertFalse(alice.has_perm(CAN_ADD_XFORM_TO_PROFILE, bob)) ManagerRole.add(alice, bob) self.assertTrue(alice.has_perm(CAN_ADD_XFORM_TO_PROFILE, bob))
def test_manager_has_role(self): bob = UserProfile.objects.create(user=self.user) alice = self._create_user('alice', 'alice') self.assertFalse(ManagerRole.has_role(alice, bob)) ManagerRole.add(alice, bob) self.assertTrue(ManagerRole.has_role(alice, bob))
def test_reassign_role(self): self._publish_transportation_form() alice = self._create_user('alice', 'alice') self.assertFalse(ManagerRole.has_role(alice, self.xform)) ManagerRole.add(alice, self.xform) self.assertTrue(ManagerRole.has_role(alice, self.xform)) ReadOnlyRole.add(alice, self.xform) self.assertFalse(ManagerRole.has_role(alice, self.xform)) self.assertTrue(ReadOnlyRole.has_role(alice, self.xform))
def do_publish_xlsform(user, post, files, owner, id_string=None, project=None): if id_string and project: xform = get_object_or_404(XForm, user=owner, id_string=id_string, project=project) if not ManagerRole.user_has_role(user, xform): raise exceptions.PermissionDenied(_( "{} has no manager/owner role to the form {}". format( user, xform))) elif not user.has_perm('can_add_xform', owner.profile): raise exceptions.PermissionDenied( detail=_(u"User %(user)s has no permission to add xforms to " "account %(account)s" % {'user': user.username, 'account': owner.username})) def set_form(): if project: args = dict({'project': project.pk}.items() + post.items()) else: args = post form = QuickConverter(args, files) return form.publish(owner, id_string=id_string, created_by=user) return publish_form(set_form)
def publish_project_xform(request, project): def set_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') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied( _("{} has no manager/owner role to the form {}".format( request.user, xform))) xform.project = project xform.save() set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def publish_project_xform(request, project): def set_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') } form = QuickConverter(props, request.FILES) return form.publish(project.organization, created_by=request.user) xform = None if 'formid' in request.DATA: xform = get_object_or_404(XForm, pk=request.DATA.get('formid')) if not ManagerRole.user_has_role(request.user, xform): raise exceptions.PermissionDenied(_( "{} has no manager/owner role to the form {}". format( request.user, xform))) xform.project = project xform.save() set_project_perms_to_xform(xform, project) else: xform = publish_form(set_form) return xform
def test_owner_cannot_remove_self_if_no_other_owner(self): self._project_create() view = ProjectViewSet.as_view({ 'put': 'share' }) ManagerRole.add(self.user, self.project) tom_data = {'username': '******', 'email': '*****@*****.**'} bob_profile = self._create_user_profile(tom_data) OwnerRole.add(bob_profile.user, self.project) 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(bob_profile.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(bob_profile.user, self.project))
def has_object_permission(self, request, view, obj): """ Custom has_object_permission method """ if (request.method == 'DELETE' and view.action == 'destroy') or ( request.method == 'PATCH' and view.action == 'partial_update'): return ManagerRole.user_has_role(request.user, obj.instance.xform) return super(SubmissionReviewPermissions, self).has_object_permission(request, view, obj)
def has_object_permission(self, request, view, obj): """ Custom has_object_permission method """ if (request.method == 'DELETE' and view.action == 'destroy') or ( request.method == 'PATCH' and view.action == 'partial_update'): return ManagerRole.user_has_role(request.user, obj.instance.xform) return super(SubmissionReviewPermissions, self).has_object_permission( request, view, obj)
def publish_project_xform(request, project): def set_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(): 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)) set_project_perms_to_xform_async.delay(xform.pk, project.pk) else: xform = publish_form(set_form) return xform
def test_project_manager_can_delete_xform(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(ManagerRole.user_has_role(alice, self.project)) data = {'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=projectid) self.assertEqual(response.status_code, 204) self.assertTrue(ManagerRole.user_has_role(alice, self.project)) self.assertTrue(alice.has_perm('delete_xform', self.xform))
def _create_submission_review(self): """ Utility method creates Submission Review """ instance_id = self._first_xform_instance.id # Ensure Managers can create a Submission Review self._create_user_and_login('bob', '1234') ManagerRole.add(self.user, self._first_xform_instance.xform) submission_data = { 'note': "Supreme Overload!", 'instance': instance_id } view = SubmissionReviewViewSet.as_view({'post': 'create'}) request = self.factory.post('/', data=submission_data, **self.extra) response = view(request=request) self.assertEqual(201, response.status_code) self.assertEqual("Supreme Overload!", response.data['note']) self.assertEqual(instance_id, response.data['instance']) return response.data
def test_project_manager_can_assign_form_to_project(self): view = ProjectViewSet.as_view({ 'post': 'forms', 'get': 'retrieve' }) self._publish_xls_form_to_project() # alice user as manager to both projects alice_data = {'username': '******', 'email': '*****@*****.**'} alice_profile = self._create_user_profile(alice_data) ShareProject(self.project, 'alice', 'manager').save() self.assertTrue(ManagerRole.user_has_role(alice_profile.user, self.project)) formid = self.xform.pk old_project = self.project project_name = u'another project' self._project_create({'name': project_name}) self.assertTrue(self.project.name == project_name) ShareProject(self.project, 'alice', 'manager').save() self.assertTrue(ManagerRole.user_has_role(alice_profile.user, self.project)) self._login_user_and_profile(alice_data) project_id = self.project.pk post_data = {'formid': formid} request = self.factory.post('/', data=post_data, **self.extra) response = view(request, pk=project_id) self.assertEqual(response.status_code, 201) self.assertTrue(self.project.xform_set.filter(pk=self.xform.pk)) self.assertFalse(old_project.xform_set.filter(pk=self.xform.pk)) # check if form added appears in the project details request = self.factory.get('/', **self.extra) response = view(request, pk=self.project.pk) self.assertIn('forms', response.data.keys()) self.assertEqual(len(response.data['forms']), 1)
def test_manager_has_role(self): bob, created = UserProfile.objects.get_or_create(user=self.user) alice = self._create_user('alice', 'alice') self.assertFalse(ManagerRole.user_has_role(alice, bob)) self.assertFalse(ManagerRole.has_role(perms_for(alice, bob), bob)) ManagerRole.add(alice, bob) self.assertTrue(ManagerRole.user_has_role(alice, bob)) self.assertTrue(ManagerRole.has_role(perms_for(alice, bob), bob))
def test_manager_has_role(self): bob, created = UserProfile.objects.get_or_create(user=self.user) alice = self._create_user('alice', 'alice') self.assertFalse(ManagerRole.user_has_role(alice, bob)) self.assertFalse(ManagerRole.has_role( perms_for(alice, bob), bob)) ManagerRole.add(alice, bob) self.assertTrue(ManagerRole.user_has_role(alice, bob)) self.assertTrue(ManagerRole.has_role( perms_for(alice, bob), bob))
def test_reassign_role(self): self._publish_transportation_form() alice = self._create_user('alice', 'alice') self.assertFalse(ManagerRole.user_has_role(alice, self.xform)) ManagerRole.add(alice, self.xform) self.assertTrue(ManagerRole.user_has_role(alice, self.xform)) self.assertTrue( ManagerRole.has_role(perms_for(alice, self.xform), self.xform)) ReadOnlyRole.add(alice, self.xform) self.assertFalse(ManagerRole.user_has_role(alice, self.xform)) self.assertTrue(ReadOnlyRole.user_has_role(alice, self.xform)) self.assertFalse( ManagerRole.has_role(perms_for(alice, self.xform), self.xform)) self.assertTrue( ReadOnlyRole.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 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