示例#1
0
def table_data_view(request, database, schema, table):
    logger.info(
        "table_data_view attempt: %s %s %s %s",
        request.user.email,
        database,
        schema,
        table,
    )

    log_event(
        request.user,
        EventLog.TYPE_DATASET_TABLE_DATA_DOWNLOAD,
        extra={
            "path": request.get_full_path(),
            "database": database,
            "schema": schema,
            "table": table,
        },
    )

    if request.method != "GET":
        return HttpResponseNotAllowed(["GET"])
    elif not can_access_schema_table(request.user, database, schema, table):
        return HttpResponseForbidden()
    elif not (view_exists(database, schema, table)
              or table_exists(database, schema, table)):
        return HttpResponseNotFound()
    else:
        return table_data(request.user.email, database, schema, table)
示例#2
0
    def get(self, request, *args, **kwargs):
        dataset = find_dataset(self.kwargs.get('dataset_uuid'), request.user)

        if not dataset.user_has_access(self.request.user):
            return HttpResponseForbidden()

        query = get_object_or_404(self.model,
                                  id=self.kwargs.get('query_id'),
                                  dataset=dataset)

        if not query.reviewed and not request.user.is_superuser:
            return HttpResponseForbidden()

        log_event(
            request.user,
            EventLog.TYPE_DATASET_CUSTOM_QUERY_DOWNLOAD,
            query.dataset,
            extra={
                'path': request.get_full_path(),
                **serializers.serialize('python', [query])[0],
            },
        )
        dataset.number_of_downloads = F('number_of_downloads') + 1
        dataset.save(update_fields=['number_of_downloads'])

        return streaming_query_response(
            request.user.email,
            query.database.memorable_name,
            sql.SQL(query.query),
            query.get_filename(),
        )
示例#3
0
def table_data_view(request, database, schema, table):
    logger.info(
        'table_data_view attempt: %s %s %s %s',
        request.user.email,
        database,
        schema,
        table,
    )

    log_event(
        request.user,
        EventLog.TYPE_DATASET_TABLE_DATA_DOWNLOAD,
        extra={
            'path': request.get_full_path(),
            'database': database,
            'schema': schema,
            'table': table,
        },
    )

    if request.method != 'GET':
        return HttpResponseNotAllowed(['GET'])
    elif not can_access_schema_table(request.user, database, schema, table):
        return HttpResponseForbidden()
    elif not (view_exists(database, schema, table)
              or table_exists(database, schema, table)):
        return HttpResponseNotFound()
    else:
        return table_data(request.user.email, database, schema, table)
示例#4
0
    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):
        if self._initial_approved is False and self.approved is True:
            raise ValueError(
                "A new record must be created for a new approval - you cannot flip a rescinded approval."
            )
        elif self._initial_approved is self.approved and self.modified_date is not None:
            raise ValueError(
                "The only change that can be made to an approval is to unapprove it."
            )

        super().save(force_insert, force_update, using, update_fields)

        if self.approved:
            log_event(self.approver,
                      EventLog.TYPE_VISUALISATION_APPROVED,
                      related_object=self)
        else:
            log_event(
                self.approver,
                EventLog.TYPE_VISUALISATION_UNAPPROVED,
                related_object=self,
            )
        self._initial_approved = self.approved
示例#5
0
    def post(self, request, *args, **kwargs):
        action = request.POST.get('action', '')
        play_sql = get_playground_sql_from_request(request)

        if action == 'edit':
            if not play_sql:
                play_sql = PlaygroundSQL(sql=request.POST.get("sql", ""),
                                         created_by_user=request.user)
                play_sql.save()

            redirect_url = reverse('explorer:index')

            return redirect(redirect_url + f"?play_id={play_sql.id}")

        if action == 'save':
            ret = super().post(request)
            if self.get_form().is_valid():
                query, form = QueryView.get_instance_and_form(
                    request, self.object.id, play_sql=play_sql)

                if form.is_valid():
                    form.save()

                vm = query_viewmodel(
                    request,
                    query,
                    form=form,
                    run_query=False,
                    rows=url_get_rows(request),
                    page=url_get_page(request),
                    message=None,
                )

                if vm['form'].errors:
                    self.object.delete()
                    del vm['query']
                    vm['form_action'] = request.get_full_path()

                    return render(request, self.template_name, vm)

                messages.success(request, "Your query has been saved.")
                log_event(
                    request.user,
                    EventLog.TYPE_DATA_EXPLORER_SAVED_QUERY,
                    related_object=query,
                    extra={"sql": query.sql},
                )
                return HttpResponseRedirect(
                    reverse_lazy('explorer:query_detail',
                                 kwargs={'query_id': self.object.id}))

            return ret

        elif action == 'edit':
            query_params = (('sql', request.POST.get('sql')), )
            return HttpResponseRedirect(
                reverse('explorer:index') + f"?{urlencode(query_params)}")

        else:
            return HttpResponse(f"Unknown form action: {action}", 400)
示例#6
0
    def get(self, request, *args, **kwargs):
        dataset = find_dataset(
            self.kwargs.get('group_slug'), self.kwargs.get('set_slug')
        )

        if not dataset.user_has_access(self.request.user):
            return HttpResponseForbidden()

        query = get_object_or_404(
            self.model, id=self.kwargs.get('query_id'), dataset=dataset
        )

        log_event(
            request.user,
            EventLog.TYPE_DATASET_CUSTOM_QUERY_DOWNLOAD,
            query.dataset,
            extra={'path': request.get_full_path(), **model_to_dict(query)},
        )
        dataset.number_of_downloads = F('number_of_downloads') + 1
        dataset.save(update_fields=['number_of_downloads'])

        return streaming_query_response(
            request.user.email,
            query.database.memorable_name,
            sql.SQL(query.query),
            query.get_filename(),
        )
示例#7
0
def request_access_view(request, dataset_uuid):
    dataset = find_dataset_or_visualisation(dataset_uuid, request.user)

    if request.method == 'POST':
        form = RequestAccessForm(request.POST)
        if form.is_valid():
            goal = form.cleaned_data['goal']
            contact_email = form.cleaned_data['email']

            user_edit_relative = reverse('admin:auth_user_change',
                                         args=[request.user.id])
            user_url = request.build_absolute_uri(user_edit_relative)

            dataset_url = request.build_absolute_uri(
                dataset.get_absolute_url())

            if (isinstance(dataset, VisualisationCatalogueItem)
                    and dataset.visualisation_template):
                ticket_reference = _notify_visualisation_access_request(
                    request, dataset, dataset_url, contact_email, goal)
            else:
                ticket_reference = create_zendesk_ticket(
                    contact_email,
                    request.user,
                    goal,
                    user_url,
                    dataset.name,
                    dataset_url,
                    dataset.information_asset_owner,
                    dataset.information_asset_manager,
                )

            log_event(
                request.user,
                EventLog.TYPE_DATASET_ACCESS_REQUEST,
                dataset,
                extra={
                    'contact_email': contact_email,
                    'goal': goal,
                    'ticket_reference': ticket_reference,
                },
            )

            url = reverse('datasets:request_access_success',
                          args=[dataset_uuid])
            return HttpResponseRedirect(f'{url}?ticket={ticket_reference}')

    return render(
        request,
        'request_access.html',
        {
            'dataset': dataset,
            'authenticated_user': request.user,
            'is_visualisation': isinstance(dataset,
                                           VisualisationCatalogueItem),
        },
    )
示例#8
0
    def get(self, request, *args, **kwargs):
        dl_format = self.kwargs.get('format')
        if dl_format not in ['json', 'csv']:
            raise Http404
        ref_dataset = self.get_object()
        records = []
        for record in ref_dataset.get_records():
            record_data = {}
            for field in ref_dataset.fields.all():
                field_name = field.name
                value = getattr(record, field.column_name)
                # If this is a linked field display the display name and id of that linked record
                if field.data_type == ReferenceDatasetField.DATA_TYPE_FOREIGN_KEY:
                    record_data[get_linked_field_identifier_name(field)] = (
                        value.get_identifier() if value is not None else None
                    )
                    record_data[get_linked_field_display_name(field)] = (
                        value.get_display_name() if value is not None else None
                    )
                else:
                    record_data[field_name] = value
            records.append(record_data)

        response = HttpResponse()
        response['Content-Disposition'] = 'attachment; filename={}-{}.{}'.format(
            ref_dataset.slug, ref_dataset.published_version, dl_format
        )

        log_event(
            request.user,
            EventLog.TYPE_REFERENCE_DATASET_DOWNLOAD,
            ref_dataset,
            extra={
                'path': request.get_full_path(),
                'reference_dataset_version': ref_dataset.published_version,
                'download_format': dl_format,
            },
        )
        ref_dataset.number_of_downloads = F('number_of_downloads') + 1
        ref_dataset.save(update_fields=['number_of_downloads'])

        if dl_format == 'json':
            response['Content-Type'] = 'application/json'
            response.write(json.dumps(list(records), cls=DjangoJSONEncoder))
        else:
            response['Content-Type'] = 'text/csv'
            with closing(io.StringIO()) as outfile:
                writer = csv.DictWriter(
                    outfile,
                    fieldnames=ref_dataset.export_field_names,
                    quoting=csv.QUOTE_NONNUMERIC,
                )
                writer.writeheader()
                writer.writerows(records)
                response.write(outfile.getvalue())  # pylint: disable=no-member
        return response
示例#9
0
    def get(self, request, *args, **kwargs):
        dataset = find_dataset(self.kwargs.get('dataset_uuid'), request.user)

        if not dataset.user_has_access(self.request.user):
            return HttpResponseForbidden()

        source_link = get_object_or_404(SourceLink,
                                        id=self.kwargs.get('source_link_id'),
                                        dataset=dataset)

        log_event(
            request.user,
            EventLog.TYPE_DATASET_SOURCE_LINK_DOWNLOAD,
            source_link.dataset,
            extra={
                'path': request.get_full_path(),
                **serializers.serialize('python', [source_link])[0],
            },
        )
        dataset.number_of_downloads = F('number_of_downloads') + 1
        dataset.save(update_fields=['number_of_downloads'])

        if source_link.link_type == source_link.TYPE_EXTERNAL:
            return HttpResponseRedirect(source_link.url)

        client = boto3.client('s3')
        try:
            file_object = client.get_object(Bucket=settings.AWS_UPLOADS_BUCKET,
                                            Key=source_link.url)
        except ClientError as ex:
            try:
                return HttpResponse(
                    status=ex.response['ResponseMetadata']['HTTPStatusCode'])
            except KeyError:
                return HttpResponseServerError()

        response = StreamingHttpResponseWithoutDjangoDbConnection(
            file_object['Body'].iter_chunks(chunk_size=65536),
            content_type=file_object['ContentType'],
        )
        response[
            'Content-Disposition'] = f'attachment; filename="{source_link.get_filename()}"'
        response['Content-Length'] = file_object['ContentLength']

        return response
示例#10
0
    def get(self, request, *args, **kwargs):
        dataset = find_dataset(
            self.kwargs.get('group_slug'), self.kwargs.get('set_slug')
        )

        if not dataset.user_has_access(self.request.user):
            return HttpResponseForbidden()

        source_link = get_object_or_404(
            SourceLink, id=self.kwargs.get('source_link_id'), dataset=dataset
        )

        log_event(
            request.user,
            EventLog.TYPE_DATASET_SOURCE_LINK_DOWNLOAD,
            source_link.dataset,
            extra={'path': request.get_full_path(), **model_to_dict(source_link)},
        )
        dataset.number_of_downloads = F('number_of_downloads') + 1
        dataset.save(update_fields=['number_of_downloads'])

        if source_link.link_type == source_link.TYPE_EXTERNAL:
            return HttpResponseRedirect(source_link.url)

        client = boto3.client('s3')
        try:
            file_object = client.get_object(
                Bucket=settings.AWS_UPLOADS_BUCKET, Key=source_link.url
            )
        except ClientError as ex:
            try:
                return HttpResponse(
                    status=ex.response['ResponseMetadata']['HTTPStatusCode']
                )
            except KeyError:
                return HttpResponseServerError()

        response = StreamingHttpResponse(
            file_object['Body'].iter_chunks(), content_type=file_object['ContentType']
        )
        response['Content-Disposition'] = 'attachment; filename="{}"'.format(
            os.path.split(source_link.url)[-1]
        )

        return response
示例#11
0
    def get(self, request, *args, **kwargs):
        access_request = self.get_object()
        if not access_request.zendesk_reference_number:
            catalogue_item = (find_dataset(access_request.catalogue_item_id,
                                           self.request.user)
                              if access_request.catalogue_item_id else None)

            if (isinstance(catalogue_item, VisualisationCatalogueItem)
                    and catalogue_item.visualisation_template is not None):
                access_request.zendesk_reference_number = (
                    zendesk.notify_visualisation_access_request(
                        request,
                        access_request,
                        catalogue_item,
                    ))
            else:
                access_request.zendesk_reference_number = zendesk.create_zendesk_ticket(
                    request,
                    access_request,
                    catalogue_item,
                )
            access_request.save()

            if catalogue_item:
                log_event(
                    request.user,
                    EventLog.TYPE_DATASET_ACCESS_REQUEST,
                    catalogue_item,
                    extra={
                        "ticket_reference":
                        access_request.zendesk_reference_number,
                    },
                )
            else:
                log_event(
                    request.user,
                    EventLog.TYPE_TOOLS_ACCESS_REQUEST,
                    extra={
                        "ticket_reference":
                        access_request.zendesk_reference_number,
                    },
                )
        return super().get(request, *args, **kwargs)
示例#12
0
    def post(self, request, query_id):
        action = request.POST.get("action", "")
        play_sql = get_playground_sql_from_request(request)

        if action == 'save':
            show = url_get_show(request)
            query, form = QueryView.get_instance_and_form(request,
                                                          query_id,
                                                          play_sql=play_sql)
            success = form.is_valid() and form.save()
            vm = query_viewmodel(
                request.user,
                query,
                form=form,
                run_query=show,
                rows=url_get_rows(request),
                page=url_get_page(request),
                message=None,
            )
            if success:
                messages.success(request, "Your query has been updated.")
                log_event(
                    request.user,
                    EventLog.TYPE_DATA_EXPLORER_SAVED_QUERY,
                    related_object=query,
                    extra={"sql": query.sql},
                )
                return redirect(
                    reverse('explorer:query_detail',
                            kwargs={"query_id": query.id}))

            vm['form_action'] = request.get_full_path()
            return render(self.request, 'explorer/query.html', vm)

        elif action == 'edit':
            query, _ = QueryView.get_instance_and_form(request,
                                                       query_id,
                                                       play_sql=play_sql)

            return HttpResponseRedirect(self.get_edit_sql_url(request, query))

        else:
            return HttpResponseBadRequest(f"Unknown form action: {action}")
示例#13
0
    def post(self, request, subscription_id):
        if subscription_id == "__all__":
            # Ignore the post values and just delete all subscriptions
            unsubscribed = unsubscribe_from_all(request.user)
        else:
            unsubscribed = [unsubscribe(subscription_id, request.user)]

        for subscription in unsubscribed:
            log_event(
                request.user,
                EventLog.TYPE_DATASET_NOTIFICATIONS_UNSUBSCRIBED,
                related_object=subscription,
            )

        return render(
            request,
            "datasets/subscriptions/unsubscribe_confirm.html",
            context={"subscriptions": unsubscribed},
        )
示例#14
0
 def form_valid(self, form):
     if form.cleaned_data["notification_type"] == NotificationType.COLUMNS:
         form.instance.notify_on_schema_change = True
         form.instance.notify_on_data_change = False
     elif form.cleaned_data[
             "notification_type"] == NotificationType.ALL_CHANGES:
         form.instance.notify_on_schema_change = True
         form.instance.notify_on_data_change = True
     log_event(
         self.request.user,
         EventLog.TYPE_DATASET_NOTIFICATIONS_SUBSCRIBED,
         related_object=form.instance,
         extra={
             "notify_on_schema_change":
             form.instance.notify_on_schema_change,
             "notify_on_data_change": form.instance.notify_on_data_change,
         },
     )
     return super().form_valid(form)
示例#15
0
    def get(self, request, *_, **__):
        dataset = find_dataset(
            self.kwargs.get('group_slug'), self.kwargs.get('set_slug')
        )
        db_object = get_object_or_404(
            self.model, id=self.kwargs.get('source_id'), dataset=dataset
        )

        if not db_object.dataset.user_has_access(self.request.user):
            return HttpResponseForbidden()

        if not self.db_object_exists(db_object):
            return HttpResponseNotFound()

        log_event(
            request.user,
            self.event_log_type,
            db_object.dataset,
            extra={'path': request.get_full_path(), **model_to_dict(db_object)},
        )
        dataset.number_of_downloads = F('number_of_downloads') + 1
        dataset.save(update_fields=['number_of_downloads'])
        return self.get_table_data(db_object)