diff --git a/netbox/users/filtersets.py b/netbox/users/filtersets.py index 2bc6b012c..a4e9a9fbc 100644 --- a/netbox/users/filtersets.py +++ b/netbox/users/filtersets.py @@ -1,12 +1,11 @@ import django_filters -from django.conf import settings from django.contrib.auth import get_user_model -from django.contrib.auth.models import Group, User +from django.contrib.auth.models import Group from django.db.models import Q from django.utils.translation import gettext as _ from netbox.filtersets import BaseFilterSet -from users.models import ObjectPermission, Token, NetBoxUser +from users.models import ObjectPermission, Token __all__ = ( 'GroupFilterSet', @@ -116,6 +115,18 @@ class ObjectPermissionFilterSet(BaseFilterSet): method='search', label=_('Search'), ) + can_view = django_filters.BooleanFilter( + method='_check_action' + ) + can_add = django_filters.BooleanFilter( + method='_check_action' + ) + can_change = django_filters.BooleanFilter( + method='_check_action' + ) + can_delete = django_filters.BooleanFilter( + method='_check_action' + ) user_id = django_filters.ModelMultipleChoiceFilter( field_name='users', queryset=get_user_model().objects.all(), @@ -150,3 +161,10 @@ class ObjectPermissionFilterSet(BaseFilterSet): Q(name__icontains=value) | Q(description__icontains=value) ) + + def _check_action(self, queryset, name, value): + action = name.split('_')[1] + if value: + return queryset.filter(actions__contains=[action]) + else: + return queryset.exclude(actions__contains=[action]) diff --git a/netbox/users/forms/filtersets.py b/netbox/users/forms/filtersets.py index 90fb5c745..eca76dea4 100644 --- a/netbox/users/forms/filtersets.py +++ b/netbox/users/forms/filtersets.py @@ -1,9 +1,12 @@ from django import forms +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group from django.utils.translation import gettext_lazy as _ -from users.models import NetBoxGroup, NetBoxUser, ObjectPermission -from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES, FilterForm, add_blank_choice from netbox.forms import NetBoxModelFilterSetForm +from users.models import NetBoxGroup, NetBoxUser, ObjectPermission +from utilities.forms import BOOLEAN_WITH_BLANK_CHOICES +from utilities.forms.fields import DynamicModelMultipleChoiceField __all__ = ( 'GroupFilterForm', @@ -12,35 +15,6 @@ __all__ = ( ) -class UserFilterForm(NetBoxModelFilterSetForm): - model = NetBoxUser - fieldsets = ( - (None, ('q', 'filter_id',)), - (_('Security'), ('is_superuser', 'is_staff', 'is_active')), - ) - is_superuser = forms.NullBooleanField( - required=False, - widget=forms.Select( - choices=BOOLEAN_WITH_BLANK_CHOICES - ), - label=_('Is Superuser'), - ) - is_staff = forms.NullBooleanField( - required=False, - widget=forms.Select( - choices=BOOLEAN_WITH_BLANK_CHOICES - ), - label=_('Is Staff'), - ) - is_active = forms.NullBooleanField( - required=False, - widget=forms.Select( - choices=BOOLEAN_WITH_BLANK_CHOICES - ), - label=_('Is Active'), - ) - - class GroupFilterForm(NetBoxModelFilterSetForm): model = NetBoxGroup fieldsets = ( @@ -48,11 +22,47 @@ class GroupFilterForm(NetBoxModelFilterSetForm): ) +class UserFilterForm(NetBoxModelFilterSetForm): + model = NetBoxUser + fieldsets = ( + (None, ('q', 'filter_id',)), + (_('Group'), ('group_id',)), + (_('Status'), ('is_active', 'is_staff', 'is_superuser')), + ) + group_id = DynamicModelMultipleChoiceField( + queryset=Group.objects.all(), + required=False, + label=_('Group') + ) + is_active = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Is Active'), + ) + is_staff = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Is Staff'), + ) + is_superuser = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Is Superuser'), + ) + + class ObjectPermissionFilterForm(NetBoxModelFilterSetForm): model = ObjectPermission fieldsets = ( (None, ('q', 'filter_id',)), - (None, ('enabled',)), + (_('Permission'), ('enabled', 'group_id', 'user_id')), + (_('Actions'), ('can_view', 'can_add', 'can_change', 'can_delete')), ) enabled = forms.NullBooleanField( label=_('Enabled'), @@ -61,3 +71,41 @@ class ObjectPermissionFilterForm(NetBoxModelFilterSetForm): choices=BOOLEAN_WITH_BLANK_CHOICES ) ) + group_id = DynamicModelMultipleChoiceField( + queryset=Group.objects.all(), + required=False, + label=_('Group') + ) + user_id = DynamicModelMultipleChoiceField( + queryset=get_user_model().objects.all(), + required=False, + label=_('User') + ) + can_view = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Can View'), + ) + can_add = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Can Add'), + ) + can_change = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Can Change'), + ) + can_delete = forms.NullBooleanField( + required=False, + widget=forms.Select( + choices=BOOLEAN_WITH_BLANK_CHOICES + ), + label=_('Can Delete'), + ) diff --git a/netbox/users/tables.py b/netbox/users/tables.py index 1fa237309..304f2c8a3 100644 --- a/netbox/users/tables.py +++ b/netbox/users/tables.py @@ -58,6 +58,7 @@ class TokenTable(NetBoxTable): class UserTable(NetBoxTable): username = tables.Column(linkify=True) + groups = tables.ManyToManyColumn() is_active = columns.BooleanColumn() is_staff = columns.BooleanColumn() is_superuser = columns.BooleanColumn() @@ -68,7 +69,8 @@ class UserTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = NetBoxUser fields = ( - 'pk', 'id', 'username', 'first_name', 'last_name', 'email', 'is_active', 'is_staff', 'is_superuser', + 'pk', 'id', 'username', 'first_name', 'last_name', 'email', 'groups', 'is_active', 'is_staff', + 'is_superuser', ) default_columns = ('pk', 'username', 'first_name', 'last_name', 'email', 'is_active') diff --git a/netbox/users/tests/test_filtersets.py b/netbox/users/tests/test_filtersets.py index d632687ef..542b40b83 100644 --- a/netbox/users/tests/test_filtersets.py +++ b/netbox/users/tests/test_filtersets.py @@ -10,7 +10,6 @@ from users import filtersets from users.models import ObjectPermission, Token from utilities.testing import BaseFilterSetTests - User = get_user_model() @@ -34,7 +33,8 @@ class UserTestCase(TestCase, BaseFilterSetTests): first_name='Hank', last_name='Hill', email='hank@stricklandpropane.com', - is_staff=True + is_staff=True, + is_superuser=True ), User( username='User2', @@ -83,13 +83,17 @@ class UserTestCase(TestCase, BaseFilterSetTests): params = {'email': ['hank@stricklandpropane.com', 'dale@dalesdeadbug.com']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_is_active(self): + params = {'is_active': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + def test_is_staff(self): params = {'is_staff': True} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - def test_is_active(self): - params = {'is_active': True} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + def test_is_superuser(self): + params = {'is_superuser': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_group(self): groups = Group.objects.all()[:2] @@ -191,6 +195,22 @@ class ObjectPermissionTestCase(TestCase, BaseFilterSetTests): params = {'description': ['foobar1', 'foobar2']} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + def test_can_view(self): + params = {'can_view': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_can_add(self): + params = {'can_add': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_can_change(self): + params = {'can_change': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + + def test_can_delete(self): + params = {'can_delete': True} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) + class TokenTestCase(TestCase, BaseFilterSetTests): queryset = Token.objects.all()