diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 90f31ac97..ab111b0ec 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -109,21 +109,6 @@ class SavedFilterViewSet(NetBoxModelViewSet): serializer_class = serializers.SavedFilterSerializer filterset_class = filtersets.SavedFilterFilterSet - def get_queryset(self): - """ - Return only shared SavedFilters, or those owned by the current user, unless - this is a superuser. - """ - queryset = super().get_queryset() - user = self.request.user - if user.is_superuser: - return queryset - if user.is_anonymous: - return queryset.filter(shared=True) - return queryset.filter( - Q(shared=True) | Q(user=user) - ) - # # Tags diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py index 263692557..6010c733a 100644 --- a/netbox/extras/filtersets.py +++ b/netbox/extras/filtersets.py @@ -158,6 +158,9 @@ class SavedFilterFilterSet(BaseFilterSet): to_field_name='username', label='User (name)', ) + usable = django_filters.BooleanFilter( + method='_usable' + ) class Meta: model = SavedFilter @@ -171,6 +174,19 @@ class SavedFilterFilterSet(BaseFilterSet): Q(description__icontains=value) ) + def _usable(self, queryset, name, value): + """ + Return only SavedFilters that are both enabled and are shared (or belong to the current user). + """ + user = self.request.user if self.request else None + if not user or user.is_anonymous: + if value: + return queryset.filter(enabled=True, shared=True) + return queryset.filter(Q(enabled=False) | Q(shared=False)) + if value: + return queryset.filter(enabled=True).filter(Q(shared=True) | Q(user=user)) + return queryset.filter(Q(enabled=False) | Q(Q(shared=False) & ~Q(user=user))) + class ImageAttachmentFilterSet(BaseFilterSet): q = django_filters.CharFilter( diff --git a/netbox/extras/forms/mixins.py b/netbox/extras/forms/mixins.py index ce91f2507..2b64d1a74 100644 --- a/netbox/extras/forms/mixins.py +++ b/netbox/extras/forms/mixins.py @@ -66,7 +66,8 @@ class SavedFiltersMixin(forms.Form): filter = DynamicModelMultipleChoiceField( queryset=SavedFilter.objects.all(), required=False, + label='Saved Filter', query_params={ - 'enabled': True, + 'usable': True, } ) diff --git a/netbox/extras/tests/test_filtersets.py b/netbox/extras/tests/test_filtersets.py index 9209cb3a1..140f05906 100644 --- a/netbox/extras/tests/test_filtersets.py +++ b/netbox/extras/tests/test_filtersets.py @@ -300,6 +300,13 @@ class SavedFilterTestCase(TestCase, BaseFilterSetTests): params = {'enabled': False} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + def test_usable(self): + # Filtering for an anonymous user + params = {'usable': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'usable': False} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + class ExportTemplateTestCase(TestCase, BaseFilterSetTests): queryset = ExportTemplate.objects.all() diff --git a/netbox/templates/extras/savedfilter.html b/netbox/templates/extras/savedfilter.html index 6e56125d7..4372481aa 100644 --- a/netbox/templates/extras/savedfilter.html +++ b/netbox/templates/extras/savedfilter.html @@ -27,7 +27,7 @@