فهرست منبع

Merge pull request #4594 from netbox-community/develop

Release v2.8.3
Jeremy Stretch 5 سال پیش
والد
کامیت
c507ab30e9

+ 8 - 0
docs/release-notes/version-2.8.md

@@ -1,5 +1,13 @@
 # NetBox v2.8
 
+## v2.8.3 (2020-05-06)
+
+### Bug Fixes
+
+* [#4593](https://github.com/netbox-community/netbox/issues/4593) - Fix AttributeError exception when viewing object lists as a non-authenticated user
+
+---
+
 ## v2.8.2 (2020-05-06)
 
 ### Enhancements

+ 10 - 4
netbox/extras/views.py

@@ -124,9 +124,12 @@ class ConfigContextView(PermissionRequiredMixin, View):
         # Determine user's preferred output format
         if request.GET.get('format') in ['json', 'yaml']:
             format = request.GET.get('format')
-            request.user.config.set('extras.configcontext.format', format, commit=True)
-        else:
+            if request.user.is_authenticated:
+                request.user.config.set('extras.configcontext.format', format, commit=True)
+        elif request.user.is_authenticated:
             format = request.user.config.get('extras.configcontext.format', 'json')
+        else:
+            format = 'json'
 
         return render(request, 'extras/configcontext.html', {
             'configcontext': configcontext,
@@ -181,9 +184,12 @@ class ObjectConfigContextView(View):
         # Determine user's preferred output format
         if request.GET.get('format') in ['json', 'yaml']:
             format = request.GET.get('format')
-            request.user.config.set('extras.configcontext.format', format, commit=True)
-        else:
+            if request.user.is_authenticated:
+                request.user.config.set('extras.configcontext.format', format, commit=True)
+        elif request.user.is_authenticated:
             format = request.user.config.get('extras.configcontext.format', 'json')
+        else:
+            format = 'json'
 
         return render(request, 'extras/object_configcontext.html', {
             model_name: obj,

+ 1 - 1
netbox/netbox/settings.py

@@ -16,7 +16,7 @@ from django.core.validators import URLValidator
 # Environment setup
 #
 
-VERSION = '2.8.2'
+VERSION = '2.8.3'
 
 # Hostname
 HOSTNAME = platform.node()

+ 1 - 1
netbox/templates/utilities/obj_list.html

@@ -5,7 +5,7 @@
 {% block content %}
 <div class="pull-right noprint">
     {% block buttons %}{% endblock %}
-    {% if table_config_form %}
+    {% if request.user.is_authenticated and table_config_form %}
         <button type="button" class="btn btn-default" data-toggle="modal" data-target="#tableconfig" title="Configure table"><i class="fa fa-cog"></i> Configure</button>
     {% endif %}
     {% if permissions.add and 'add' in action_buttons %}

+ 5 - 2
netbox/utilities/paginator.py

@@ -50,9 +50,12 @@ def get_paginate_count(request):
     if 'per_page' in request.GET:
         try:
             per_page = int(request.GET.get('per_page'))
-            request.user.config.set('pagination.per_page', per_page, commit=True)
+            if request.user.is_authenticated:
+                request.user.config.set('pagination.per_page', per_page, commit=True)
             return per_page
         except ValueError:
             pass
 
-    return request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT)
+    if request.user.is_authenticated:
+        return request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT)
+    return settings.PAGINATE_COUNT

+ 14 - 0
netbox/utilities/testing/testcases.py

@@ -164,6 +164,13 @@ class ViewTestCases:
             response = self.client.get(instance.get_absolute_url())
             self.assertHttpStatus(response, 200)
 
+        @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
+        def test_list_objects_anonymous(self):
+            # Make the request as an unauthenticated user
+            self.client.logout()
+            response = self.client.get(self.model.objects.first().get_absolute_url())
+            self.assertHttpStatus(response, 200)
+
     class CreateObjectViewTestCase(ModelViewTestCase):
         """
         Create a single new instance.
@@ -287,6 +294,13 @@ class ViewTestCases:
                 self.assertHttpStatus(response, 200)
                 self.assertEqual(response.get('Content-Type'), 'text/csv')
 
+        @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
+        def test_list_objects_anonymous(self):
+            # Make the request as an unauthenticated user
+            self.client.logout()
+            response = self.client.get(self._get_url('list'))
+            self.assertHttpStatus(response, 200)
+
     class BulkCreateObjectsViewTestCase(ModelViewTestCase):
         """
         Create multiple instances using a single form. Expects the creation of three new instances by default.

+ 7 - 1
netbox/utilities/views.py

@@ -3,6 +3,7 @@ import sys
 from copy import deepcopy
 
 from django.contrib import messages
+from django.contrib.auth.decorators import login_required
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import FieldDoesNotExist, ValidationError
 from django.db import transaction, IntegrityError
@@ -13,6 +14,7 @@ from django.shortcuts import get_object_or_404, redirect, render
 from django.template import loader
 from django.template.exceptions import TemplateDoesNotExist
 from django.urls import reverse
+from django.utils.decorators import method_decorator
 from django.utils.html import escape
 from django.utils.http import is_safe_url
 from django.utils.safestring import mark_safe
@@ -164,7 +166,10 @@ class ObjectListView(View):
             permissions[action] = request.user.has_perm(perm_name)
 
         # Construct the table based on the user's permissions
-        columns = request.user.config.get(f"tables.{self.table.__name__}.columns")
+        if request.user.is_authenticated:
+            columns = request.user.config.get(f"tables.{self.table.__name__}.columns")
+        else:
+            columns = None
         table = self.table(self.queryset, columns=columns)
         if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
             table.columns.show('pk')
@@ -188,6 +193,7 @@ class ObjectListView(View):
 
         return render(request, self.template_name, context)
 
+    @method_decorator(login_required)
     def post(self, request):
 
         # Update the user's table configuration