def custom_response_handler(request, xform, query, export_type, token=None, meta=None): export_type = _get_export_type(export_type) if export_type in external_export_types and \ (token is not None) or (meta is not None): export_type = Export.EXTERNAL_EXPORT # check if we need to re-generate, # we always re-generate if a filter is specified if should_regenerate_export(xform, export_type, request): export = _generate_new_export(request, xform, query, export_type) else: export = newset_export_for(xform, export_type) if not export.filename: # tends to happen when using newset_export_for. export = _generate_new_export(request, xform, query, export_type) log_export(request, xform, export_type) if export_type == Export.EXTERNAL_EXPORT: return external_export_response(export) # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] id_string = None if request.GET.get('raw') else xform.id_string response = response_with_mimetype_and_name( Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def zip_export(request, username, id_string): owner = get_object_or_404(User, username=username) xform = get_object_or_404(XForm, id_string=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) if request.GET.get('raw'): id_string = None attachments = Attachment.objects.filter(instance__xform=xform) zip_file = create_attachments_zipfile(attachments) audit = { "xform": xform.id_string, "export_type": Export.ZIP_EXPORT } audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name('zip', id_string, file_path=zip_file, use_local_filesystem=True) return response
def zip_export(request, username, id_string): owner = get_object_or_404(User, username=username) xform = get_object_or_404(XForm, id_string=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) if request.GET.get('raw'): id_string = None attachments = Attachment.objects.filter(instance__xform=xform) zip_file = create_attachments_zipfile(attachments) audit = {"xform": xform.id_string, "export_type": Export.ZIP_EXPORT} audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name('zip', id_string, file_path=zip_file, use_local_filesystem=True) return response
def download_xlsform(request, username, id_string): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = User.objects.get(username=username) helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): return HttpResponseForbidden('Not shared.') file_path = xform.xls.name default_storage = get_storage_class()() if default_storage.exists(file_path): audit = {"xform": xform.id_string} audit_log( Actions.FORM_XLS_DOWNLOADED, request.user, xform.user, _("Downloaded XLS file for form '%(id_string)s'.") % {"id_string": xform.id_string}, audit, request) split_path = file_path.split(os.extsep) extension = 'xls' if len(split_path) > 1: extension = split_path[len(split_path) - 1] response = response_with_mimetype_and_name('vnd.ms-excel', id_string, show_date=False, extension=extension, file_path=file_path) return response else: messages.add_message( request, messages.WARNING, _(u'No XLS file for your form ' u'<strong>%(id)s</strong>') % {'id': id_string}) return HttpResponseRedirect("/%s" % username)
def attachment_url(request, size='medium'): """ Redirects to image attachment of the specified size, defaults to 'medium'. """ media_file = request.GET.get('media_file') no_redirect = request.GET.get('no_redirect') if not media_file: return HttpResponseNotFound(_(u'Attachment not found')) result = Attachment.objects.filter(media_file=media_file)[0:1] if result.count() == 0: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if size == 'original' and no_redirect == 'true': response = response_with_mimetype_and_name( attachment.mimetype, attachment.name, extension=attachment.extension, file_path=attachment.media_file.name) return response if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) media_url = image_url(attachment, size) if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def download_jsonform(request, username, id_string): """ XForm JSON view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({ 'user__username__iexact': username, 'id_string__iexact': id_string }) if request.method == "OPTIONS": response = HttpResponse() add_cors_headers(response) return response helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): response = HttpResponseForbidden(_(u'Not shared.')) add_cors_headers(response) return response response = response_with_mimetype_and_name( 'json', id_string, show_date=False) if 'callback' in request.GET and request.GET.get('callback') != '': callback = request.GET.get('callback') response.content = "%s(%s)" % (callback, xform.json) else: add_cors_headers(response) response.content = xform.json return response
def download_metadata(request, username, id_string, data_id): xform = get_object_or_404(XForm, user__username__iexact=username, id_string__exact=id_string) owner = xform.user # FIXME: couldn't non-owner users be allowed to access these files even # without the form being entirely public (shared=True)? if username == request.user.username or xform.shared: data = get_object_or_404(MetaData, pk=data_id) file_path = data.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): audit = {'xform': xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, t("Document '%(filename)s' for '%(id_string)s' downloaded.") % { 'id_string': xform.id_string, 'filename': "%s.%s" % (filename, extension) }, audit, request) response = response_with_mimetype_and_name(data.data_file_type, filename, extension=extension, show_date=False, file_path=file_path) return response else: return HttpResponseNotFound() return HttpResponseForbidden(t('Permission denied.'))
def download_xlsform(request, username, id_string): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = User.objects.get(username=username) helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): return HttpResponseForbidden('Not shared.') file_path = xform.xls.name default_storage = get_storage_class()() if default_storage.exists(file_path): audit = { "xform": xform.id_string } audit_log( Actions.FORM_XLS_DOWNLOADED, request.user, xform.user, _("Downloaded XLS file for form '%(id_string)s'.") % { "id_string": xform.id_string }, audit, request) split_path = file_path.split(os.extsep) extension = 'xls' if len(split_path) > 1: extension = split_path[len(split_path) - 1] response = response_with_mimetype_and_name( 'vnd.ms-excel', id_string, show_date=False, extension=extension, file_path=file_path) return response else: messages.add_message(request, messages.WARNING, _(u'No XLS file for your form ' u'<strong>%(id)s</strong>') % {'id': id_string}) return HttpResponseRedirect("/%s" % username)
def export_download(request, username, id_string, export_type, filename): owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(t('Not shared.')) # find the export entry in the db export = get_object_or_404(Export, xform=xform, filename=filename) ext, mime_type = export_def_from_filename(export.filename) audit = {"xform": xform.id_string, "export_type": export.export_type} audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, t("Downloaded %(export_type)s export '%(filename)s' " "on '%(id_string)s'.") % { 'export_type': export.export_type.upper(), 'filename': export.filename, 'id_string': xform.id_string, }, audit, request) if request.GET.get('raw'): id_string = None default_storage = get_storage_class()() if not isinstance(default_storage, FileSystemStorage): return HttpResponseRedirect(default_storage.url(export.filepath)) basename = os.path.splitext(export.filename)[0] response = response_with_mimetype_and_name(mime_type, name=basename, extension=ext, file_path=export.filepath, show_date=False) return response
def download_metadata(request, username, id_string, data_id): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = xform.user if username == request.user.username or xform.shared: data = get_object_or_404(MetaData, pk=data_id) file_path = data.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Document '%(filename)s' for '%(id_string)s' downloaded.") % { 'id_string': xform.id_string, 'filename': "%s.%s" % (filename, extension) }, audit, request) response = response_with_mimetype_and_name( data.data_file_type, filename, extension=extension, show_date=False, file_path=file_path) return response else: return HttpResponseNotFound() return HttpResponseForbidden(_(u'Permission denied.'))
def attachment_url(request, size='medium'): """ Redirects to image attachment of the specified size, defaults to 'medium'. """ media_file = request.GET.get('media_file') no_redirect = request.GET.get('no_redirect') if not media_file: return HttpResponseNotFound(_(u'Attachment not found')) result = Attachment.objects.filter(media_file=media_file).order_by()[0:1] if not result: return HttpResponseNotFound(_(u'Attachment not found')) attachment = result[0] if size == 'original' and no_redirect == 'true': response = response_with_mimetype_and_name( attachment.mimetype, attachment.name, extension=attachment.extension, file_path=attachment.media_file.name) return response if not attachment.mimetype.startswith('image'): return redirect(attachment.media_file.url) media_url = image_url(attachment, size) if media_url: return redirect(media_url) return HttpResponseNotFound(_(u'Error: Attachment not found'))
def retrieve(self, request, *args, **kwargs): lookup_field = self.lookup_field lookup = self.kwargs.get(lookup_field) if lookup == self.public_forms_endpoint: self.object_list = self._get_public_forms_queryset() page = self.paginate_queryset(self.object_list) if page is not None: serializer = self.get_pagination_serializer(page) else: serializer = self.get_serializer(self.object_list, many=True) return Response(serializer.data) xform = self.get_object() query = request.GET.get("query", {}) export_type = kwargs.get('format') if export_type is None or export_type in ['json']: # perform default viewset retrieve, no data export return super(XFormViewSet, self).retrieve(request, *args, **kwargs) export_type = _get_export_type(export_type) # check if we need to re-generate, # we always re-generate if a filter is specified if should_regenerate_export(xform, export_type, request): export = _generate_new_export(request, xform, query, export_type) else: export = newset_export_for(xform, export_type) # log download as well audit = { "xform": xform.id_string, "export_type": export_type } log.audit_log( log.Actions.EXPORT_DOWNLOADED, request.user, xform.user, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename: # tends to happen when using newset_export_for. raise Http404("File does not exist!") # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] id_string = None if request.GET.get('raw') else xform.id_string response = response_with_mimetype_and_name( Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def download_media_data(request, username, id_string, data_id): xform = get_object_or_404( XForm, user__username=username, id_string=id_string) owner = xform.user data = get_object_or_404(MetaData, id=data_id) dfs = get_storage_class()() if request.GET.get('del', False): if username == request.user.username: try: # ensure filename is not an empty string if data.data_file.name != '': dfs.delete(data.data_file.name) data.delete() audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Media download '%(filename)s' deleted from " "'%(id_string)s'.") % { 'id_string': xform.id_string, 'filename': os.path.basename(data.data_file.name) }, audit, request) return HttpResponseRedirect(reverse(show, kwargs={ 'username': username, 'id_string': id_string })) except Exception as e: return HttpResponseServerError(e) else: if username: # == request.user.username or xform.shared: if data.data_file.name == '' and data.data_value is not None: return HttpResponseRedirect(data.data_value) file_path = data.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') if dfs.exists(file_path): audit = { 'xform': xform.id_string } audit_log( Actions.FORM_UPDATED, request.user, owner, _("Media '%(filename)s' downloaded from " "'%(id_string)s'.") % { 'id_string': xform.id_string, 'filename': os.path.basename(file_path) }, audit, request) response = response_with_mimetype_and_name( data.data_file_type, filename, extension=extension, show_date=False, file_path=file_path) return response else: return HttpResponseNotFound() return HttpResponseForbidden(_(u'Permission denied.'))
def retrieve(self, request, *args, **kwargs): export = self.get_object() filename, extension = os.path.splitext(export.filename) extension = extension[1:] return response_with_mimetype_and_name(Export.EXPORT_MIMES[extension], filename, extension=extension, file_path=export.filepath, show_date=False)
def retrieve(self, request, *args, **kwargs): export = self.get_object() filename, extension = os.path.splitext(export.filename) extension = extension[1:] return response_with_mimetype_and_name( Export.EXPORT_MIMES[extension], filename, extension=extension, file_path=export.filepath, show_date=False)
def download_xlsform(request, username, id_string): xform = get_object_or_404(XForm, user__username__iexact=username, id_string__exact=id_string) owner = User.objects.get(username__iexact=username) helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): return HttpResponseForbidden('Not shared.') file_path = xform.xls.name default_storage = get_storage_class()() if file_path != '' and default_storage.exists(file_path): audit = { "xform": xform.id_string } audit_log( Actions.FORM_XLS_DOWNLOADED, request.user, xform.user, _("Downloaded XLS file for form '%(id_string)s'.") % { "id_string": xform.id_string }, audit, request) if file_path.endswith('.csv'): with default_storage.open(file_path) as ff: xls_io = convert_csv_to_xls(ff.read()) response = StreamingHttpResponse( xls_io, content_type='application/vnd.ms-excel; charset=utf-8') response[ 'Content-Disposition'] = 'attachment; filename=%s.xls' % xform.id_string return response split_path = file_path.split(os.extsep) extension = 'xls' if len(split_path) > 1: extension = split_path[len(split_path) - 1] response = response_with_mimetype_and_name( 'vnd.ms-excel', id_string, show_date=False, extension=extension, file_path=file_path) return response else: messages.add_message(request, messages.WARNING, _(u'No XLS file for your form ' u'<strong>%(id)s</strong>') % {'id': id_string}) return HttpResponseRedirect("/%s" % username)
def get_media_file_response(metadata, request=None): def get_data_value_objects(value): model = None if value.startswith('dataview'): model = DataView elif value.startswith('xform'): model = XForm if model: parts = value.split() if len(parts) > 1: name = parts[2] if len(parts) > 2 else None return (get_object_or_404(model, pk=parts[1]), name) return (None, None) if metadata.data_file: file_path = metadata.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): response = response_with_mimetype_and_name(metadata.data_file_type, filename, extension=extension, show_date=False, file_path=file_path, full_mime=True) return response else: return HttpResponseNotFound() else: try: URLValidator()(metadata.data_value) except ValidationError: obj, filename = get_data_value_objects(metadata.data_value) if obj: dataview = obj if isinstance(obj, DataView) else False xform = obj.xform if isinstance(obj, DataView) else obj return custom_response_handler(request, xform, {}, Export.CSV_EXPORT, filename=filename, dataview=dataview) return HttpResponseRedirect(metadata.data_value)
def download_media_data(request, username, id_string, data_id): xform = get_object_or_404(XForm, user__username=username, id_string=id_string) owner = xform.user data = get_object_or_404(MetaData, id=data_id) dfs = get_storage_class()() if request.GET.get("del", False): if username == request.user.username: try: dfs.delete(data.data_file.name) data.delete() audit = {"xform": xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, _("Media download '%(filename)s' deleted from " "'%(id_string)s'.") % {"id_string": xform.id_string, "filename": os.path.basename(data.data_file.name)}, audit, request, ) return HttpResponseRedirect(reverse(show, kwargs={"username": username, "id_string": id_string})) except Exception: return HttpResponseServerError() else: if username: # == request.user.username or xform.shared: file_path = data.data_file.name filename, extension = os.path.splitext(file_path.split("/")[-1]) extension = extension.strip(".") if dfs.exists(file_path): audit = {"xform": xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, _("Media '%(filename)s' downloaded from " "'%(id_string)s'.") % {"id_string": xform.id_string, "filename": os.path.basename(file_path)}, audit, request, ) response = response_with_mimetype_and_name( data.data_file_type, filename, extension=extension, show_date=False, file_path=file_path ) return response else: return HttpResponseNotFound() return HttpResponseForbidden(_(u"Permission denied."))
def get_media_file_response(metadata): if metadata.data_file: file_path = metadata.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): response = response_with_mimetype_and_name( metadata.data_file_type, filename, extension=extension, show_date=False, file_path=file_path, full_mime=True) return response else: return HttpResponseNotFound() else: return HttpResponseRedirect(metadata.data_value)
def export_download(request, username, id_string, export_type, filename): """ Export download view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({'user': owner, 'id_string__iexact': id_string}) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) # find the export entry in the db export = get_object_or_404(Export, xform=xform, filename=filename) if (export_type == Export.GOOGLE_SHEETS_EXPORT or export_type == Export.EXTERNAL_EXPORT) and \ export.export_url is not None: return HttpResponseRedirect(export.export_url) ext, mime_type = export_def_from_filename(export.filename) audit = {"xform": xform.id_string, "export_type": export.export_type} audit_log(Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded %(export_type)s export '%(filename)s' " "on '%(id_string)s'.") % { 'export_type': export.export_type.upper(), 'filename': export.filename, 'id_string': xform.id_string, }, audit, request) if request.GET.get('raw'): id_string = None default_storage = get_storage_class()() if not isinstance(default_storage, FileSystemStorage): return HttpResponseRedirect(default_storage.url(export.filepath)) basename = os.path.splitext(export.filename)[0] response = response_with_mimetype_and_name( mime_type, name=basename, extension=ext, file_path=export.filepath, show_date=False) return response
def zip_export(request, username, id_string): owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) if request.GET.get('raw'): id_string = None attachments = Attachment.objects.filter(instance__xform=xform) zip_file = None try: zip_file = create_attachments_zipfile(attachments) audit = { "xform": xform.id_string, "export_type": Export.ZIP_EXPORT } audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded ZIP export on '%(id_string)s'.") % { 'id_string': xform.id_string, }, audit, request) if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name('zip', id_string) response.write(FileWrapper(zip_file)) response['Content-Length'] = zip_file.tell() zip_file.seek(0) finally: zip_file and zip_file.close() return response
def download_xform(request, username, id_string): """ Download XForm XML view. """ user = get_object_or_404(User, username__iexact=username) xform = get_form({'user': user, 'id_string__iexact': id_string}) profile, __ = UserProfile.objects.get_or_create(user=user) if profile.require_auth: authenticator = HttpDigestAuthenticator() if not authenticator.authenticate(request): return authenticator.build_challenge_response() audit = {"xform": xform.id_string} audit_log(Actions.FORM_XML_DOWNLOADED, request.user, xform.user, _("Downloaded XML for form '%(id_string)s'.") % {"id_string": xform.id_string}, audit, request) response = response_with_mimetype_and_name( 'xml', id_string, show_date=False) response.content = xform.xml return response
def download_jsonform(request, username, id_string): owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, user__username__iexact=username, id_string__exact=id_string) if request.method == "OPTIONS": response = HttpResponse() add_cors_headers(response) return response helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): response = HttpResponseForbidden(_(u"Not shared.")) add_cors_headers(response) return response response = response_with_mimetype_and_name("json", id_string, show_date=False) if "callback" in request.GET and request.GET.get("callback") != "": callback = request.GET.get("callback") response.content = "%s(%s)" % (callback, xform.json) else: add_cors_headers(response) response.content = xform.json return response
def get_media_file_response( metadata: MetaData, request: Request = None ) -> HttpResponse: if metadata.data_file: file_path = metadata.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): response = response_with_mimetype_and_name( metadata.data_file_type, filename, extension=extension, show_date=False, file_path=file_path, full_mime=True) return response else: return HttpResponseNotFound() elif not metadata.is_paired_data: return HttpResponseRedirect(metadata.data_value) # When `request.user` is authenticated, their authentication is lost with # an HTTP redirection. We use KoBoCAT to proxy the response from KPI headers = {} if not request.user.is_anonymous: token = Token.objects.get(user=request.user) headers['Authorization'] = f'Token {token.key}' # Send the request internally to avoid extra traffic on the public interface internal_url = metadata.data_value.replace(settings.KOBOFORM_URL, settings.KOBOFORM_INTERNAL_URL) response = requests.get(internal_url, headers=headers) return HttpResponse( content=response.content, status=response.status_code, content_type=response.headers['content-type'], )
def data_export(request, username, id_string, export_type): owner = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, id_string__exact=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) query = request.GET.get("query") extension = export_type # check if we should force xlsx force_xlsx = request.GET.get('xls') != 'true' if export_type == Export.XLS_EXPORT and force_xlsx: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' audit = { "xform": xform.id_string, "export_type": export_type } # check if we need to re-generate, # we always re-generate if a filter is specified if should_create_new_export(xform, export_type) or query or\ 'start' in request.GET or 'end' in request.GET: # check for start and end params if 'start' in request.GET or 'end' in request.GET: if not query: query = '{}' query = json.dumps( _set_submission_time_to_query(json.loads(query), request)) try: export = generate_export( export_type, extension, username, id_string, None, query) audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: return HttpResponseNotFound(_("No records found to export")) else: export = newset_export_for(xform, export_type) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename: # tends to happen when using newset_export_for. return HttpResponseNotFound("File does not exist!") # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name( Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def retrieve(self, request, *args, **kwargs): xform = self.get_object() query = request.GET.get("query", {}) export_type = kwargs.get('format') if export_type is None or export_type in ['json']: # perform default viewset retrieve, no data export return super(XFormViewSet, self).retrieve(request, *args, **kwargs) if export_type in EXPORT_EXT.keys(): export_type = EXPORT_EXT[export_type] else: raise exceptions.ParseError( _(u"'%(export_type)s' format not known or not implemented!" % {'export_type': export_type})) if export_type == Export.XLS_EXPORT: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' else: extension = export_type audit = {"xform": xform.id_string, "export_type": export_type} # check if we need to re-generate, # we always re-generate if a filter is specified if should_regenerate_export(xform, export_type, request): format_date_for_mongo = lambda x, datetime: datetime.strptime( x, '%y_%m_%d_%H_%M_%S').strftime('%Y-%m-%dT%H:%M:%S') # check for start and end params if 'start' in request.GET or 'end' in request.GET: query = json.loads(query) \ if isinstance(query, basestring) else query query[SUBMISSION_TIME] = {} try: if request.GET.get('start'): query[SUBMISSION_TIME]['$gte'] = format_date_for_mongo( request.GET['start'], datetime) if request.GET.get('end'): query[SUBMISSION_TIME]['$lte'] = format_date_for_mongo( request.GET['end'], datetime) except ValueError: raise exceptions.ParseError( _("Dates must be in the format YY_MM_DD_hh_mm_ss")) else: query = json.dumps(query) try: export = generate_export(export_type, extension, xform.user.username, xform.id_string, None, query) log.audit_log( log.Actions.EXPORT_CREATED, request.user, xform.user, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: raise Http404(_("No records found to export")) else: export = newset_export_for(xform, export_type) # log download as well log.audit_log( log.Actions.EXPORT_DOWNLOADED, request.user, xform.user, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename: # tends to happen when using newset_export_for. raise Http404("File does not exist!") # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] id_string = None if request.GET.get('raw') else xform.id_string response = response_with_mimetype_and_name(Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def download_xform(request, username, id_string): user = get_object_or_404(User, username__iexact=username) xform = get_object_or_404(XForm, user=user, id_string__exact=id_string) profile, created = UserProfile.objects.get_or_create(user=user) if (profile.require_auth and (digest_response := digest_authentication(request))): return digest_response audit = {"xform": xform.id_string} audit_log( Actions.FORM_XML_DOWNLOADED, request.user, xform.user, t("Downloaded XML for form '%(id_string)s'.") % {"id_string": xform.id_string}, audit, request) response = response_with_mimetype_and_name('xml', id_string, show_date=False) response.content = xform.xml return response def download_xlsform(request, username, id_string): xform = get_object_or_404(XForm, user__username__iexact=username, id_string__exact=id_string) owner = User.objects.get(username__iexact=username) helper_auth_helper(request) if not has_permission(xform, owner, request, xform.shared): return HttpResponseForbidden('Not shared.')
def data_export(request, username, id_string, export_type): """ Data export view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({'user': owner, 'id_string__iexact': id_string}) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) query = request.GET.get("query") extension = export_type # check if we should force xlsx force_xlsx = request.GET.get('xls') != 'true' if export_type == Export.XLS_EXPORT and force_xlsx: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' audit = {"xform": xform.id_string, "export_type": export_type} options = { "extension": extension, "username": username, "id_string": id_string } if query: options['query'] = query # check if we need to re-generate, # we always re-generate if a filter is specified if should_create_new_export(xform, export_type, options) or query or\ 'start' in request.GET or 'end' in request.GET: # check for start and end params start, end = _get_start_end_submission_time(request) options.update({"start": start, "end": end}) try: export = generate_export(export_type, xform, None, options) audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: return HttpResponseNotFound(_("No records found to export")) except SPSSIOError as e: return HttpResponseBadRequest(str(e)) else: export = newest_export_for(xform, export_type, options) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename and not export.error_message: # tends to happen when using newset_export_for. return HttpResponseNotFound("File does not exist!") elif not export.filename and export.error_message: return HttpResponseBadRequest(str(export.error_message)) # get extension from file_path, exporter could modify to # xlsx if it exceeds limits __, extension = os.path.splitext(export.filename) extension = extension[1:] if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name(Export.EXPORT_MIMES[extension], id_string, extension=extension, file_path=export.filepath) return response
def get_media_file_response(metadata, request=None): """ Returns a HTTP response for media files. HttpResponse 200 if it represents a file on disk. HttpResponseRedirect 302 incase the metadata represents a url. HttpResponseNotFound 404 if the metadata file cannot be found. """ def get_data_value_objects(value): """ Returns a tuple of a DataView or XForm and the name of the media file. Looks for 'dataview 123 fruits.csv' or 'xform 345 fruits.csv'. """ model = None if value.startswith('dataview'): model = DataView elif value.startswith('xform'): model = XForm if model: parts = value.split() if len(parts) > 1: name = parts[2] if len(parts) > 2 else None return (get_object_or_404(model, pk=parts[1]), name) return (None, None) if metadata.data_file: file_path = metadata.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') dfs = get_storage_class()() if dfs.exists(file_path): response = response_with_mimetype_and_name( metadata.data_file_type, filename, extension=extension, show_date=False, file_path=file_path, full_mime=True) return response return HttpResponseNotFound() try: URLValidator()(metadata.data_value) except ValidationError: obj, filename = get_data_value_objects(metadata.data_value) if obj: dataview = obj if isinstance(obj, DataView) else False xform = obj.xform if isinstance(obj, DataView) else obj return custom_response_handler( request, xform, {}, Export.CSV_EXPORT, filename=filename, dataview=dataview) return HttpResponseRedirect(metadata.data_value)
def retrieve(self, request, *args, **kwargs): xform = self.get_object() query = request.GET.get("query", {}) export_type = kwargs.get('format') if export_type is None or export_type in ['json']: # perform default viewset retrieve, no data export return super(XFormViewSet, self).retrieve(request, *args, **kwargs) if export_type in EXPORT_EXT.keys(): export_type = EXPORT_EXT[export_type] else: raise exceptions.ParseError( _(u"'%(export_type)s' format not known or not implemented!" % {'export_type': export_type}) ) if export_type == Export.XLS_EXPORT: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' else: extension = export_type audit = { "xform": xform.id_string, "export_type": export_type } # check if we need to re-generate, # we always re-generate if a filter is specified if should_regenerate_export(xform, export_type, request): format_date_for_mongo = lambda x, datetime: datetime.strptime( x, '%y_%m_%d_%H_%M_%S').strftime('%Y-%m-%dT%H:%M:%S') # check for start and end params if 'start' in request.GET or 'end' in request.GET: query = json.loads(query) \ if isinstance(query, basestring) else query query[SUBMISSION_TIME] = {} try: if request.GET.get('start'): query[SUBMISSION_TIME]['$gte'] = format_date_for_mongo( request.GET['start'], datetime) if request.GET.get('end'): query[SUBMISSION_TIME]['$lte'] = format_date_for_mongo( request.GET['end'], datetime) except ValueError: raise exceptions.ParseError( _("Dates must be in the format YY_MM_DD_hh_mm_ss") ) else: query = json.dumps(query) try: export = generate_export( export_type, extension, xform.user.username, xform.id_string, None, query ) log.audit_log( log.Actions.EXPORT_CREATED, request.user, xform.user, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: raise Http404(_("No records found to export")) else: export = newset_export_for(xform, export_type) # log download as well log.audit_log( log.Actions.EXPORT_DOWNLOADED, request.user, xform.user, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename: # tends to happen when using newset_export_for. raise Http404("File does not exist!") # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] id_string = None if request.GET.get('raw') else xform.id_string response = response_with_mimetype_and_name( Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def data_export(request, username, id_string, export_type): """ Data export view. """ owner = get_object_or_404(User, username__iexact=username) xform = get_form({'user': owner, 'id_string__iexact': id_string}) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) query = request.GET.get("query") extension = export_type # check if we should force xlsx force_xlsx = request.GET.get('xls') != 'true' if export_type == Export.XLS_EXPORT and force_xlsx: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' audit = {"xform": xform.id_string, "export_type": export_type} options = { "extension": extension, "username": username, "id_string": id_string } if query: options['query'] = query # check if we need to re-generate, # we always re-generate if a filter is specified if should_create_new_export(xform, export_type, options) or query or\ 'start' in request.GET or 'end' in request.GET: # check for start and end params start, end = _get_start_end_submission_time(request) options.update({"start": start, "end": end}) try: export = generate_export(export_type, xform, None, options) audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: return HttpResponseNotFound(_("No records found to export")) except SPSSIOError as e: return HttpResponseBadRequest(str(e)) else: export = newest_export_for(xform, export_type, options) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded %(export_type)s export on '%(id_string)s'.") % {'id_string': xform.id_string, 'export_type': export_type.upper()}, audit, request) if not export.filename and not export.error_message: # tends to happen when using newset_export_for. return HttpResponseNotFound("File does not exist!") elif not export.filename and export.error_message: return HttpResponseBadRequest(str(export.error_message)) # get extension from file_path, exporter could modify to # xlsx if it exceeds limits __, extension = os.path.splitext(export.filename) extension = extension[1:] if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name( Export.EXPORT_MIMES[extension], id_string, extension=extension, file_path=export.filepath) return response
def data_export(request, username, id_string, export_type): owner = get_object_or_404(User, username=username) xform = get_object_or_404(XForm, id_string=id_string, user=owner) helper_auth_helper(request) if not has_permission(xform, owner, request): return HttpResponseForbidden(_(u'Not shared.')) query = request.GET.get("query") extension = export_type # check if we should force xlsx force_xlsx = request.GET.get('xls') != 'true' if export_type == Export.XLS_EXPORT and force_xlsx: extension = 'xlsx' elif export_type in [Export.CSV_ZIP_EXPORT, Export.SAV_ZIP_EXPORT]: extension = 'zip' audit = { "xform": xform.id_string, "export_type": export_type } # check if we need to re-generate, # we always re-generate if a filter is specified if should_create_new_export(xform, export_type) or query or\ 'start' in request.GET or 'end' in request.GET: format_date_for_mongo = lambda x, datetime: datetime.strptime( x, '%y_%m_%d_%H_%M_%S').strftime('%Y-%m-%dT%H:%M:%S') # check for start and end params if 'start' in request.GET or 'end' in request.GET: if not query: query = '{}' query = json.loads(query) query[SUBMISSION_TIME] = {} try: if request.GET.get('start'): query[SUBMISSION_TIME]['$gte'] = format_date_for_mongo( request.GET['start'], datetime) if request.GET.get('end'): query[SUBMISSION_TIME]['$lte'] = format_date_for_mongo( request.GET['end'], datetime) except ValueError: return HttpResponseBadRequest( _("Dates must be in the format YY_MM_DD_hh_mm_ss")) else: query = json.dumps(query) try: export = generate_export( export_type, extension, username, id_string, None, query) audit_log( Actions.EXPORT_CREATED, request.user, owner, _("Created %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) except NoRecordsFoundError: return HttpResponseNotFound(_("No records found to export")) else: export = newset_export_for(xform, export_type) # log download as well audit_log( Actions.EXPORT_DOWNLOADED, request.user, owner, _("Downloaded %(export_type)s export on '%(id_string)s'.") % { 'id_string': xform.id_string, 'export_type': export_type.upper() }, audit, request) if not export.filename: # tends to happen when using newset_export_for. return HttpResponseNotFound("File does not exist!") # get extension from file_path, exporter could modify to # xlsx if it exceeds limits path, ext = os.path.splitext(export.filename) ext = ext[1:] if request.GET.get('raw'): id_string = None response = response_with_mimetype_and_name( Export.EXPORT_MIMES[ext], id_string, extension=ext, file_path=export.filepath) return response
def download_media_data(request, username, id_string, data_id): xform = get_object_or_404(XForm, user__username__iexact=username, id_string__exact=id_string) owner = xform.user data = get_object_or_404(MetaData, id=data_id) dfs = get_storage_class()() if request.GET.get('del', False): if username == request.user.username: try: # ensure filename is not an empty string if data.data_file.name != '': dfs.delete(data.data_file.name) data.delete() audit = {'xform': xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, t("Media download '%(filename)s' deleted from " "'%(id_string)s'.") % { 'id_string': xform.id_string, 'filename': os.path.basename(data.data_file.name) }, audit, request) if 'HTTP_REFERER' in request.META and request.META[ 'HTTP_REFERER'].strip(): return HttpResponseRedirect(request.META['HTTP_REFERER']) return HttpResponseRedirect( reverse(show, kwargs={ 'username': username, 'id_string': id_string })) except Exception as e: return HttpResponseServerError(e) else: if not xform.shared: # raise an exception if the requesting user is not allowed to # submit to this form (and therefore should not see this form media) check_submission_permissions(request, xform) if data.data_file.name == '' and data.data_value is not None: return HttpResponseRedirect(data.data_value) file_path = data.data_file.name filename, extension = os.path.splitext(file_path.split('/')[-1]) extension = extension.strip('.') if dfs.exists(file_path): audit = {'xform': xform.id_string} audit_log( Actions.FORM_UPDATED, request.user, owner, t("Media '%(filename)s' downloaded from " "'%(id_string)s'.") % { 'id_string': xform.id_string, 'filename': os.path.basename(file_path) }, audit, request) response = response_with_mimetype_and_name(data.data_file_type, filename, extension=extension, show_date=False, file_path=file_path) return response else: return HttpResponseNotFound() return HttpResponseForbidden(t('Permission denied.'))