def test_xform_delete_cascades_mongo_instances(self): initial_mongo_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] # submit instance for i in range(len(self.surveys)): self._submit_transport_instance(i) # check mongo record exists mongo_count = ParsedInstance.query_mongo(self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] self.assertEqual(mongo_count, initial_mongo_count + len(self.surveys)) # delete form xform_delete_url = reverse(delete_xform, kwargs={ 'username': self.user.username, 'id_string': self.xform.id_string }) self.client.post(xform_delete_url) mongo_count = ParsedInstance.query_mongo(self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] self.assertEqual(mongo_count, initial_mongo_count)
def test_deleted_submission_not_in_export(self): self._publish_transportation_form() initial_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] self._submit_transport_instance(0) self._submit_transport_instance(1) count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] self.assertEqual(count, initial_count+2) # get id of second submission instance_id = Instance.objects.filter( xform=self.xform).order_by('id').reverse()[0].id delete_url = reverse( delete_data, kwargs={"username": self.user.username, "id_string": self.xform.id_string}) params = {'id': instance_id} self.client.post(delete_url, params) count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] self.assertEqual(count, initial_count + 1) # create the export csv_export_url = reverse( 'csv_export', kwargs={"username": self.user.username, "id_string":self.xform.id_string}) response = self.client.get(csv_export_url) self.assertEqual(response.status_code, 200) f = StringIO.StringIO(response.content) csv_reader = csv.reader(f) num_rows = len([row for row in csv_reader]) f.close() # number of rows == 2 i.e. initial_count + header plus one row self.assertEqual(num_rows, initial_count + 2)
def api(request, username=None, id_string=None): ''' Returns all results as JSON. If a parameter string is passed, it takes the 'query' parameter, converts this string to a dictionary, an that is then used as a MongoDB query string. NOTE: only a specific set of operators are allow, currently $or and $and. Please send a request if you'd like another operator to be enabled. NOTE: Your query must be valid JSON, double check it here, http://json.parser.online.fr/ E.g. api?query='{"last_name": "Smith"}' ''' xform, owner = check_and_set_user_and_form(username, id_string, request) if not xform: return HttpResponseForbidden('Not shared.') try: args = {"username": username, "id_string": id_string, "query": request.GET.get('query'), "fields": request.GET.get('fields'), "sort": request.GET.get('sort')} if 'start' in request.GET: args["start"] = int(request.GET.get('start')) if 'limit' in request.GET: args["limit"] = int(request.GET.get('limit')) if 'count' in request.GET: args["count"] = True if int(request.GET.get('count')) > 0 else False cursor = ParsedInstance.query_mongo(**args) except ValueError, e: return HttpResponseBadRequest(e.message)
def delete_data(request, username=None, id_string=None): xform, owner = check_and_set_user_and_form(username, id_string, request) if not xform: return HttpResponseForbidden(_(u'Not shared.')) try: args = {"username": username, "id_string": id_string, "query": request.GET.get('query'), "fields": request.GET.get('fields'), "sort": request.GET.get('sort')} if 'limit' in request.GET: args["limit"] = int(request.GET.get('limit')) cursor = ParsedInstance.query_mongo(**args) except ValueError as e: return HttpResponseBadRequest(e) today = datetime.today().strftime('%Y-%m-%dT%H:%M:%S') ParsedInstance.edit_mongo( args['query'], '{ "$set": {"_deleted_at": "%s" }}' % today) records = list(record for record in cursor) response_text = simplejson.dumps(records) if 'callback' in request.GET and request.GET.get('callback') != '': callback = request.GET.get('callback') response_text = ("%s(%s)" % (callback, response_text)) return HttpResponse(response_text, mimetype='application/json')
def api(request, username=None, id_string=None): """ Returns all results as JSON. If a parameter string is passed, it takes the 'query' parameter, converts this string to a dictionary, an that is then used as a MongoDB query string. NOTE: only a specific set of operators are allow, currently $or and $and. Please send a request if you'd like another operator to be enabled. NOTE: Your query must be valid JSON, double check it here, http://json.parser.online.fr/ E.g. api?query='{"last_name": "Smith"}' """ xform, owner = check_and_set_user_and_form(username, id_string, request) if not xform: return HttpResponseForbidden("Not shared.") try: args = { "username": username, "id_string": id_string, "query": request.GET.get("query"), "fields": request.GET.get("fields"), "sort": request.GET.get("sort"), } if "start" in request.GET: args["start"] = int(request.GET.get("start")) if "limit" in request.GET: args["limit"] = int(request.GET.get("limit")) if "count" in request.GET: args["count"] = True if int(request.GET.get("count")) > 0 else False cursor = ParsedInstance.query_mongo(**args) except ValueError, e: return HttpResponseBadRequest(e.message)
def test_edited_submissions_in_exports(self): self._publish_transportation_form() initial_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] instance_name = 'transport_2011-07-25_19-05-36' path = os.path.join( 'main', 'tests', 'fixtures', 'transportation', 'instances_w_uuid', instance_name, instance_name + '.xml') self._make_submission(path) count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] self.assertEqual(count, initial_count+1) instance = Instance.objects.filter( xform=self.xform).order_by('id').reverse()[0] # make edited submission - simulating what enketo would return instance_name = 'transport_2011-07-25_19-05-36-edited' path = os.path.join( 'main', 'tests', 'fixtures', 'transportation', 'instances_w_uuid', instance_name, instance_name + '.xml') self._make_submission(path) count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]['count'] self.assertEqual(count, initial_count+1) # create the export csv_export_url = reverse( 'csv_export', kwargs={"username": self.user.username, "id_string":self.xform.id_string}) response = self.client.get(csv_export_url) self.assertEqual(response.status_code, 200) f = StringIO.StringIO(response.content) csv_reader = csv.DictReader(f) data = [row for row in csv_reader] f.close() num_rows = len(data) # number of rows == initial_count + 1 self.assertEqual(num_rows, initial_count + 1) key ='transport/loop_over_transport_types_frequency/ambulance/frequency_to_referral_facility' self.assertEqual(data[initial_count][key], "monthly")
def _get_form_data(self, xform, **kwargs): margs = { 'username': xform.user.username, 'id_string': xform.id_string, 'query': kwargs.get('query', None), 'fields': kwargs.get('fields', None), 'sort': kwargs.get('sort', None) } # TODO: Possibly add "url" field to all data records cursor = ParsedInstance.query_mongo(**margs) records = list(record for record in cursor) return records
def test_xform_delete_cascades_mongo_instances(self): initial_mongo_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] # submit instance for i in range(len(self.surveys)): self._submit_transport_instance(i) # check mongo record exists mongo_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] self.assertEqual(mongo_count, initial_mongo_count + len(self.surveys)) # delete form xform_delete_url = reverse(delete_xform, kwargs={ 'username': self.user.username, 'id_string': self.xform.id_string }) self.client.post(xform_delete_url) mongo_count = ParsedInstance.query_mongo( self.user.username, self.xform.id_string, '{}', '[]', '{}', count=True)[0]["count"] self.assertEqual(mongo_count, initial_mongo_count)
def delete_data(request, username=None, id_string=None): query = request.POST.get('query', None) if query is None: return HttpResponseBadRequest(_(u"Invalid query parameter")) try: simplejson.loads(query) except ValueError: return HttpResponseBadRequest(_(u"Invalid query parameter")) xform, owner = check_and_set_user_and_form(username, id_string, request) response_text = u'' if not xform: return HttpResponseForbidden(_(u'Not shared.')) try: query_args = { "username": username, "id_string": id_string, "query": query, "fields": request.POST.get('fields', None), "sort": request.POST.get('sort', None), "limit": 1 } if 'limit' in request.GET: query_args["limit"] = int(request.GET.get('limit')) cursor = ParsedInstance.query_mongo(**query_args) except ValueError as e: return HttpResponseBadRequest(e) else: records = list(record for record in cursor) if records.__len__(): for record in records: Instance.delete_by_uuid( username, id_string, uuid=record['_uuid']) audit = { 'xform': xform.id_string } audit_log(Actions.SUBMISSION_DELETED, request.user, owner, _("Deleted submission with id '%(record_id)s' on '%(id_string)s'.") %\ { 'id_string': xform.id_string, 'record_id': record['_id'] }, audit, request) response_text = simplejson.dumps(records) if 'callback' in request.GET and request.GET.get('callback') != '': callback = request.GET.get('callback') response_text = ("%s(%s)" % (callback, response_text)) return HttpResponse(response_text, mimetype='application/json')
def api(request, username=None, id_string=None): """ Returns all results as JSON. If a parameter string is passed, it takes the 'query' parameter, converts this string to a dictionary, an that is then used as a MongoDB query string. NOTE: only a specific set of operators are allow, currently $or and $and. Please send a request if you'd like another operator to be enabled. NOTE: Your query must be valid JSON, double check it here, http://json.parser.online.fr/ E.g. api?query='{"last_name": "Smith"}' """ if request.method == "OPTIONS": response = HttpResponse() add_cors_headers(response) return response helper_auth_helper(request) helper_auth_helper(request) xform, owner = check_and_set_user_and_form(username, id_string, request) if not xform: return HttpResponseForbidden(_(u'Not shared.')) try: args = { 'username': username, 'id_string': id_string, 'query': request.GET.get('query'), 'fields': request.GET.get('fields'), 'sort': request.GET.get('sort') } if 'start' in request.GET: args["start"] = int(request.GET.get('start')) if 'limit' in request.GET: args["limit"] = int(request.GET.get('limit')) if 'count' in request.GET: args["count"] = True if int(request.GET.get('count')) > 0\ else False cursor = ParsedInstance.query_mongo(**args) except ValueError, e: return HttpResponseBadRequest(e.__str__())
def edit_data(request, username, id_string, data_id): owner = User.objects.get(username=username) xform = get_object_or_404( XForm, user__username=username, id_string=id_string) if not has_edit_permission(xform, owner, request, xform.shared): return HttpResponseForbidden(_(u'Not shared.')) if not hasattr(settings, 'ENKETO_URL'): return HttpResponseRedirect( reverse( 'main.views.show', kwargs={'username': username, 'id_string': id_string} ) ) try: query_args = { "username": username, "id_string": id_string, "query": '{"_id": %s}' % data_id, "fields": None, "sort": None, "limit": 1 } if 'limit' in request.GET: query_args["limit"] = int(request.GET.get('limit')) cursor = ParsedInstance.query_mongo(**query_args) except ValueError as e: return HttpResponseBadRequest(e) else: records = list(record for record in cursor) if records.__len__(): uuid = records[0]["_uuid"] instance = Instance.objects.get(xform=xform, uuid=uuid) url = '%sdata/edit_url' % settings.ENKETO_URL register_openers() response = None # see commit 220f2dad0e for tmp file creation try: formhub_url = "http://%s/" % request.META['HTTP_HOST'] except: formhub_url = "http://formhub.org/" injected_xml = inject_instanceid(instance.xml, instance.uuid) values = { 'format': 'json', 'form_id': xform.id_string, 'server_url': formhub_url + username, 'instance': injected_xml, 'instance_id': instance.uuid, 'return_url': request.build_absolute_uri( reverse( 'odk_viewer.views.instance', kwargs={ 'username': username, 'id_string': id_string} ) + "#/" + str(instance.id)) } data, headers = multipart_encode(values) headers['User-Agent'] = 'formhub' req = urllib2.Request(url, data, headers) try: response = urllib2.urlopen(req) response = json.loads(response.read()) context = RequestContext(request) owner = User.objects.get(username=username) context.profile, created = \ UserProfile.objects.get_or_create(user=owner) context.xform = xform context.content_user = owner context.form_view = True if 'edit_url' in response: audit = { "xform": xform.id_string, "data_id": data_id } audit_log(Actions.SUBMISSION_EDIT_REQUESTED, request.user, owner, _("Requested to edit data with id '%(data_id)s' on '%(id_string)s'.") %\ { 'id_string': xform.id_string, 'data_id': data_id }, audit, request) context.enketo = response['edit_url'] return HttpResponseRedirect(response['edit_url']) else: json_msg = response['reason'] """ return HttpResponse("<script>$('body')</script>") """ context.message = { 'type': 'alert-error', 'text': "Enketo error, reason: " + ( response['reason'] and "Server not found.") } messages.add_message(request, messages.WARNING, json_msg) return render_to_response("profile.html", context_instance=context) except urllib2.URLError: # this will happen if we could not connect to enketo messages.add_message( request, messages.WARNING, _("Enketo error: Unable to open webform url.")) except ValueError, e: messages.add_message( request, messages.WARNING, _("Enketo error: enketo replied %s") % e)