From 424b336536262592c499bad191c642759fbbad69 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 30 Mar 2023 10:03:41 -0400 Subject: [PATCH] Fixes #12061: Improve handling of insufficient permissions for widget content --- netbox/extras/dashboard/widgets.py | 21 ++++++++++++++----- .../dashboard/widgets/objectcounts.html | 15 +++++++++---- .../extras/dashboard/widgets/objectlist.html | 6 +++++- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/netbox/extras/dashboard/widgets.py b/netbox/extras/dashboard/widgets.py index 253208cbf..c745f1dff 100644 --- a/netbox/extras/dashboard/widgets.py +++ b/netbox/extras/dashboard/widgets.py @@ -11,6 +11,7 @@ from django.urls import NoReverseMatch, reverse from django.utils.translation import gettext as _ from utilities.forms import BootstrapMixin +from utilities.permissions import get_permission_for_model from utilities.templatetags.builtins.filters import render_markdown from utilities.utils import content_type_identifier, content_type_name, get_viewname from .utils import register_widget @@ -107,8 +108,12 @@ class ObjectCountsWidget(DashboardWidget): for content_type_id in self.config['models']: app_label, model_name = content_type_id.split('.') model = ContentType.objects.get_by_natural_key(app_label, model_name).model_class() - object_count = model.objects.restrict(request.user, 'view').count - counts.append((model, object_count)) + permission = get_permission_for_model(model, 'view') + if request.user.has_perm(permission): + object_count = model.objects.restrict(request.user, 'view').count + counts.append((model, object_count)) + else: + counts.append((model, None)) return render_to_string(self.template_name, { 'counts': counts, @@ -136,15 +141,21 @@ class ObjectListWidget(DashboardWidget): def render(self, request): app_label, model_name = self.config['model'].split('.') - content_type = ContentType.objects.get_by_natural_key(app_label, model_name) - viewname = get_viewname(content_type.model_class(), action='list') + model = ContentType.objects.get_by_natural_key(app_label, model_name).model_class() + viewname = get_viewname(model, action='list') + + # Evaluate user's permission. Note that this controls only whether the HTMX element is + # embedded on the page: The view itself will also evaluate permissions separately. + permission = get_permission_for_model(model, 'view') + has_permission = request.user.has_perm(permission) + try: htmx_url = reverse(viewname) except NoReverseMatch: htmx_url = None - return render_to_string(self.template_name, { 'viewname': viewname, + 'has_permission': has_permission, 'htmx_url': htmx_url, 'page_size': self.config.get('page_size'), }) diff --git a/netbox/templates/extras/dashboard/widgets/objectcounts.html b/netbox/templates/extras/dashboard/widgets/objectcounts.html index d75d88218..d0e604c9a 100644 --- a/netbox/templates/extras/dashboard/widgets/objectcounts.html +++ b/netbox/templates/extras/dashboard/widgets/objectcounts.html @@ -3,12 +3,19 @@ {% if counts %}
{% for model, count in counts %} - -
+ {% if count != None %} + +
+ {{ model|meta:"verbose_name_plural"|bettertitle }} +
{{ count }}
+
+
+ {% else %} +
{{ model|meta:"verbose_name_plural"|bettertitle }} -
{{ count }}
+
- + {% endif %} {% endfor %}
{% endif %} diff --git a/netbox/templates/extras/dashboard/widgets/objectlist.html b/netbox/templates/extras/dashboard/widgets/objectlist.html index 4e44acb46..76c4e658c 100644 --- a/netbox/templates/extras/dashboard/widgets/objectlist.html +++ b/netbox/templates/extras/dashboard/widgets/objectlist.html @@ -1,5 +1,9 @@ -{% if htmx_url %} +{% if htmx_url and has_permission %}
+{% elif htmx_url %} +
+ No permission to view this content. +
{% else %}
Unable to load content. Invalid view name: {{ viewname }}