Exemple #1
0
def custom_response_handler(request,
                            xform,
                            query,
                            export_type,
                            token=None,
                            meta=None,
                            dataview=False,
                            filename=None):
    """
    Returns a HTTP response with export file for download.
    """
    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

    options = parse_request_export_options(request.query_params)

    dataview_pk = hasattr(dataview, 'pk') and dataview.pk
    options["dataview_pk"] = dataview_pk

    if dataview:
        columns_with_hxl = get_columns_with_hxl(xform.survey.get('children'))

        if columns_with_hxl:
            options['include_hxl'] = include_hxl_row(dataview.columns,
                                                     list(columns_with_hxl))
    try:
        query = filter_queryset_xform_meta_perms_sql(xform, request.user,
                                                     query)
    except NoRecordsPermission:
        return Response(data=json.dumps(
            {"details": _("You don't have permission")}),
                        status=status.HTTP_403_FORBIDDEN,
                        content_type="application/json")

    if query:
        options['query'] = query

    remove_group_name = options.get("remove_group_name")

    export_id = request.query_params.get("export_id")

    if export_id:
        export = get_object_or_404(Export, id=export_id, xform=xform)
    else:
        if export_type == Export.GOOGLE_SHEETS_EXPORT:

            return Response(data=json.dumps(
                {"details": _("Sheets export only supported in async mode")}),
                            status=status.HTTP_403_FORBIDDEN,
                            content_type="application/json")

        # check if we need to re-generate,
        # we always re-generate if a filter is specified
        def _new_export():
            return _generate_new_export(request,
                                        xform,
                                        query,
                                        export_type,
                                        dataview_pk=dataview_pk)

        if should_create_new_export(xform,
                                    export_type,
                                    options,
                                    request=request):
            export = _new_export()
        else:
            export = newest_export_for(xform, export_type, options)

            if not export.filename and not export.error_message:
                export = _new_export()

        log_export(request, xform, export_type)

        if export_type == Export.EXTERNAL_EXPORT:
            return external_export_response(export)

    if export.filename is None and export.error_message:
        raise exceptions.ParseError(export.error_message)

    # get extension from file_path, exporter could modify to
    # xlsx if it exceeds limits
    _path, ext = os.path.splitext(export.filename)
    ext = ext[1:]

    show_date = True
    if filename is None and export.status == Export.SUCCESSFUL:
        filename = _generate_filename(request,
                                      xform,
                                      remove_group_name,
                                      dataview_pk=dataview_pk)
    else:
        show_date = False
    response = response_with_mimetype_and_name(Export.EXPORT_MIMES[ext],
                                               filename,
                                               extension=ext,
                                               show_date=show_date,
                                               file_path=export.filepath)

    return response
Exemple #2
0
def process_async_export(request, xform, export_type, options=None):
    """
    Check if should generate export or just return the latest export.
    Rules for regenerating an export are:
        1. Filter included on the exports.
        2. New submission done.
        3. Always regenerate external exports.
            (External exports uses templates and the template might have
             changed)
    :param request:
    :param xform:
    :param export_type:
    :param options: additional export params that may include
        query: export filter
        token: template url for xls external reports
        meta: metadataid that contains the external xls report template url
        remove_group_name: Flag to determine if group names should appear
    :return: response dictionary
    """
    # maintain the order of keys while processing the export

    export_type = _get_export_type(export_type)
    token = options.get("token")
    meta = options.get("meta")
    query = options.get("query")

    try:
        query = filter_queryset_xform_meta_perms_sql(xform, request.user,
                                                     query)
    except NoRecordsPermission:
        payload = {"details": _("You don't have permission")}
        return Response(data=json.dumps(payload),
                        status=status.HTTP_403_FORBIDDEN,
                        content_type="application/json")
    else:
        if query:
            options['query'] = query

    if export_type in EXTERNAL_EXPORT_TYPES and \
            (token is not None) or (meta is not None):
        export_type = Export.EXTERNAL_EXPORT

    if export_type == Export.GOOGLE_SHEETS_EXPORT:
        credential = _get_google_credential(request)

        if isinstance(credential, HttpResponseRedirect):
            return credential
        options['google_credentials'] = credential.to_json()

    if should_create_new_export(xform, export_type, options, request=request)\
            or export_type == Export.EXTERNAL_EXPORT:
        resp = {
            u'job_uuid':
            _create_export_async(xform,
                                 export_type,
                                 query,
                                 False,
                                 options=options)
        }
    else:
        print('Do not create a new export.')
        export = newest_export_for(xform, export_type, options)

        if not export.filename:
            # tends to happen when using newest_export_for.
            resp = {
                u'job_uuid':
                _create_export_async(xform,
                                     export_type,
                                     query,
                                     False,
                                     options=options)
            }
        else:
            resp = export_async_export_response(request, export)

    return resp
Exemple #3
0
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
Exemple #4
0
def data_export(request, username, id_string, export_type):
    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,
        "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
    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 process_async_export(request, xform, export_type, options=None):
    """
    Check if should generate export or just return the latest export.
    Rules for regenerating an export are:
        1. Filter included on the exports.
        2. New submission done.
        3. Always regenerate external exports.
            (External exports uses templates and the template might have
             changed)
    :param request:
    :param xform:
    :param export_type:
    :param options: additional export params that may include
        query: export filter
        token: template url for xls external reports
        meta: metadataid that contains the external xls report template url
        remove_group_name: Flag to determine if group names should appear
    :return: response dictionary
    """
    # maintain the order of keys while processing the export

    export_type = _get_export_type(export_type)
    token = options.get("token")
    meta = options.get("meta")
    query = options.get("query")

    if export_type in external_export_types and \
            (token is not None) or (meta is not None):
        export_type = Export.EXTERNAL_EXPORT

    dataview_pk = options.get('dataview_pk')
    if export_type == Export.GOOGLE_SHEETS_EXPORT:
        credential = _get_google_credential(request)

        if isinstance(credential, HttpResponseRedirect):
            return credential
        options['google_credentials'] = credential

    if should_create_new_export(xform, export_type, options, request=request)\
            or export_type == Export.EXTERNAL_EXPORT:
        resp = {
            u'job_uuid':
            _create_export_async(xform,
                                 export_type,
                                 query,
                                 False,
                                 options=options)
        }
    else:
        export = newest_export_for(xform, export_type, options)

        if not export.filename:
            # tends to happen when using newest_export_for.
            resp = {
                u'job_uuid':
                _create_export_async(xform,
                                     export_type,
                                     query,
                                     False,
                                     options=options)
            }
        else:
            resp = _export_async_export_response(request,
                                                 xform,
                                                 export,
                                                 dataview_pk=dataview_pk)

    return resp