From b206e367f3628661d8af7f64e3bd91d038174016 Mon Sep 17 00:00:00 2001 From: Ramez Ashraf Date: Sun, 15 Oct 2023 09:24:01 +0300 Subject: [PATCH] - Add `REPORT_VIEW_ACCESS_FUNCTION` to control default access to the report view --- CHANGELOG.md | 8 ++-- slick_reporting/app_settings.py | 6 +++ slick_reporting/helpers.py | 12 ++++++ .../slick_reporting.report_loader.js | 42 +++++++++---------- slick_reporting/views.py | 12 +++--- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a4f6d4..cc201f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file. ## [] - Implement Slick reporting media override feature + docs - Add `Integrating reports into your Admin site` section to the docs +- Group by and crosstab reports do not need date_field set anymore. Only time series do. +- Fix in FirstBalance Computation field if no date is supplied +- Add `REPORT_VIEW_ACCESS_FUNCTION` to control access to the report view + ## [1.2.0] - 2023-10-10 - Add ``get_slick_reporting_media`` and ``get_charts_media`` templatetags @@ -79,9 +83,7 @@ All notable changes to this project will be documented in this file. - Breaking: [Only if you use Crosstab reports] renamed crosstab_compute_reminder to crosstab_compute_remainder - Breaking : [Only if you set the templates statics by hand] renamed slick_reporting to ra.hightchart.js and ra.chartjs.js to erp_framework.highchart.js and erp_framework.chartjs.js respectively -- Fix an issue with Crosstab when there crosstab_compute_remainder = False -- Group by and crosstab reports do not need date_field set anymore. Only time series do. -- Fix in FirstBalance Computation field if no date is supplied +- Fix an issue with Crosstab when there crosstab_compute_remainder = False ## [0.7.0] diff --git a/slick_reporting/app_settings.py b/slick_reporting/app_settings.py index 7bab3b2..38137bd 100644 --- a/slick_reporting/app_settings.py +++ b/slick_reporting/app_settings.py @@ -1,4 +1,5 @@ from django.conf import settings +from django.urls import get_callable from django.utils.functional import lazy from django.utils.translation import gettext_lazy as _ @@ -84,6 +85,7 @@ def get_end_date(): "total": _("Total"), "export_to_csv": _("Export to CSV"), }, + "REPORT_VIEW_ACCESS_FUNCTION": "slick_reporting.helpers.user_test_function", } @@ -125,3 +127,7 @@ def get_slick_reporting_settings(): def get_media(): return SLICK_REPORTING_SETTINGS["MEDIA"] + + +def get_access_function(): + return get_callable(SLICK_REPORTING_SETTINGS["REPORT_VIEW_ACCESS_FUNCTION"]) diff --git a/slick_reporting/helpers.py b/slick_reporting/helpers.py index 0cd49cc..ac15b78 100644 --- a/slick_reporting/helpers.py +++ b/slick_reporting/helpers.py @@ -1,5 +1,6 @@ from collections import OrderedDict +from django.conf import settings from django.contrib.contenttypes.fields import GenericForeignKey @@ -53,3 +54,14 @@ def get_field_from_query_text(path, model): return field _rel = field.related_model return field + + +def user_test_function(report_view): + """ + A default test function return True on DEBUG, otherwise return the user.is_superuser + :param report_view: + :return: + """ + if not settings.DEBUG: + return report_view.request.user.is_superuser + return True diff --git a/slick_reporting/static/slick_reporting/slick_reporting.report_loader.js b/slick_reporting/static/slick_reporting/slick_reporting.report_loader.js index f36f28b..44778a9 100644 --- a/slick_reporting/static/slick_reporting/slick_reporting.report_loader.js +++ b/slick_reporting/static/slick_reporting/slick_reporting.report_loader.js @@ -132,31 +132,31 @@ return $container } - $('body').on('click', 'a[data-chart-id]', function (e) { - e.preventDefault(); - let $this = $(this); - let data = $.slick_reporting.cache[$this.attr('data-report-slug')] - let chart_id = $this.attr('data-chart-id') - $.slick_reporting.report_loader.displayChart(data, $this.parents('[data-report-widget]').find('[data-report-chart]'), chart_id) - - }); - - $('[data-export-btn]').on('click', function (e) { - let $elem = $(this); - e.preventDefault() - let form = $($elem.attr('data-form-selector')); - window.location = '?' + form.serialize() + '&_export=' + $elem.attr('data-export-parameter'); - }); - $('[data-get-results-button]').not(".vanilla-btn-flag").on('click', function (event) { - event.preventDefault(); - let $elem = $('[data-report-widget]') - $.slick_reporting.report_loader.refreshReportWidget($elem) - }); jQuery(document).ready(function () { $.slick_reporting.report_loader.initialize(); - }); + $('body').on('click', 'a[data-chart-id]', function (e) { + e.preventDefault(); + let $this = $(this); + let data = $.slick_reporting.cache[$this.attr('data-report-slug')] + let chart_id = $this.attr('data-chart-id') + $.slick_reporting.report_loader.displayChart(data, $this.parents('[data-report-widget]').find('[data-report-chart]'), chart_id) + }); + + $('[data-export-btn]').on('click', function (e) { + let $elem = $(this); + e.preventDefault() + let form = $($elem.attr('data-form-selector')); + window.location = '?' + form.serialize() + '&_export=' + $elem.attr('data-export-parameter'); + }); + $('[data-get-results-button]').not(".vanilla-btn-flag").on('click', function (event) { + event.preventDefault(); + let $elem = $('[data-report-widget]') + $.slick_reporting.report_loader.refreshReportWidget($elem) + }); + + }); $.slick_reporting.report_loader = { diff --git a/slick_reporting/views.py b/slick_reporting/views.py index f61f359..ee6ab5b 100644 --- a/slick_reporting/views.py +++ b/slick_reporting/views.py @@ -5,6 +5,7 @@ import simplejson as json from django import forms from django.conf import settings +from django.contrib.auth.mixins import UserPassesTestMixin from django.db.models import Q from django.forms import modelform_factory from django.http import HttpResponse, StreamingHttpResponse, JsonResponse @@ -12,7 +13,7 @@ from django.utils.functional import Promise from django.views.generic import FormView -from .app_settings import SLICK_REPORTING_SETTINGS +from .app_settings import SLICK_REPORTING_SETTINGS, get_access_function from .forms import ( report_form_factory, get_crispy_helper, @@ -83,7 +84,7 @@ def write(self, value): ) -class ReportViewBase(ReportGeneratorAPI, FormView): +class ReportViewBase(ReportGeneratorAPI, UserPassesTestMixin, FormView): report_slug = None report_title = "" @@ -118,10 +119,9 @@ class ReportViewBase(ReportGeneratorAPI, FormView): export_actions = None - # @staticmethod - # def form_filter_func(fkeys_dict): - # # todo revise - # return fkeys_dict + def test_func(self): + access_function = get_access_function() + return access_function(self) @classmethod def get_report_title(cls):