125890 fix objectpermission form

This commit is contained in:
Arthur 2023-06-09 13:00:23 -07:00
parent 2fdd834a66
commit f1eadc6a5c
3 changed files with 83 additions and 9 deletions

View File

@ -3,6 +3,7 @@ from django.conf import settings
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.forms import SimpleArrayField from django.contrib.postgres.forms import SimpleArrayField
from django.utils.html import mark_safe from django.utils.html import mark_safe
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
@ -11,9 +12,10 @@ from ipam.formfields import IPNetworkFormField
from ipam.validators import prefix_validator from ipam.validators import prefix_validator
from netbox.preferences import PREFERENCES from netbox.preferences import PREFERENCES
from utilities.forms import BootstrapMixin from utilities.forms import BootstrapMixin
from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField from utilities.forms.fields import ContentTypeMultipleChoiceField, DynamicModelChoiceField, DynamicModelMultipleChoiceField
from utilities.forms.widgets import DateTimePicker from utilities.forms.widgets import DateTimePicker
from utilities.utils import flatten_dict from utilities.utils import flatten_dict
from users.constants import *
from users.models import * from users.models import *
@ -183,7 +185,7 @@ class GroupForm(BootstrapMixin, forms.ModelForm):
) )
fieldsets = ( fieldsets = (
('', ('name', )), (None, ('name', )),
('Users', ('users', )), ('Users', ('users', )),
('Permissions', ('object_permissions', )), ('Permissions', ('object_permissions', )),
) )
@ -196,14 +198,86 @@ class GroupForm(BootstrapMixin, forms.ModelForm):
class ObjectPermissionForm(BootstrapMixin, forms.ModelForm): class ObjectPermissionForm(BootstrapMixin, forms.ModelForm):
users = DynamicModelMultipleChoiceField(
required=False,
queryset=get_user_model().objects.all()
)
groups = DynamicModelMultipleChoiceField(
required=False,
queryset=Group.objects.all()
)
object_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=OBJECTPERMISSION_OBJECT_TYPES
)
can_view = forms.BooleanField(required=False)
can_add = forms.BooleanField(required=False)
can_change = forms.BooleanField(required=False)
can_delete = forms.BooleanField(required=False)
fieldsets = ( fieldsets = (
('name', 'description', 'enabled'), (None, ('name', 'description', 'enabled',)),
('User', ('username', 'first_name', 'last_name', 'email', )), ('Actions', ('can_view', 'can_add', 'can_change', 'can_delete', 'actions')),
('Objects', ('object_types')),
('Assignment', ('groups', 'users')),
('Constraints', ('constraints',))
) )
class Meta: class Meta:
model = ObjectPermission model = ObjectPermission
fields = [ fields = [
'name', 'description', 'enabled', 'name', 'description', 'enabled', 'object_types', 'users', 'groups', 'constraints', 'actions',
] ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Make the actions field optional since the admin form uses it only for non-CRUD actions
self.fields['actions'].required = False
# Order group and user fields
self.fields['groups'].queryset = self.fields['groups'].queryset.order_by('name')
self.fields['users'].queryset = self.fields['users'].queryset.order_by('username')
# Check the appropriate checkboxes when editing an existing ObjectPermission
if self.instance.pk:
for action in ['view', 'add', 'change', 'delete']:
if action in self.instance.actions:
self.fields[f'can_{action}'].initial = True
self.instance.actions.remove(action)
def clean(self):
super().clean()
object_types = self.cleaned_data.get('object_types')
constraints = self.cleaned_data.get('constraints')
# Append any of the selected CRUD checkboxes to the actions list
if not self.cleaned_data.get('actions'):
self.cleaned_data['actions'] = list()
for action in ['view', 'add', 'change', 'delete']:
if self.cleaned_data[f'can_{action}'] and action not in self.cleaned_data['actions']:
self.cleaned_data['actions'].append(action)
# At least one action must be specified
if not self.cleaned_data['actions']:
raise ValidationError("At least one action must be selected.")
# Validate the specified model constraints by attempting to execute a query. We don't care whether the query
# returns anything; we just want to make sure the specified constraints are valid.
if object_types and constraints:
# Normalize the constraints to a list of dicts
if type(constraints) is not list:
constraints = [constraints]
for ct in object_types:
model = ct.model_class()
try:
tokens = {
CONSTRAINT_TOKEN_USER: 0, # Replace token with a null user ID
}
model.objects.filter(qs_filter_from_constraints(constraints, tokens)).exists()
except FieldError as e:
raise ValidationError({
'constraints': f'Invalid filter for {model}: {e}'
})

View File

@ -2,7 +2,7 @@ import django_tables2 as tables
from django_tables2.utils import A from django_tables2.utils import A
from .models import Token from .models import Token
from netbox.tables import NetBoxTable, columns from netbox.tables import NetBoxTable, columns
from users.models import NetBoxGroup, NetBoxUser from users.models import NetBoxGroup, NetBoxUser, ObjectPermission
__all__ = ( __all__ = (
'GroupTable', 'GroupTable',
@ -93,7 +93,7 @@ class ObjectPermissionTable(NetBoxTable):
) )
class Meta(NetBoxTable.Meta): class Meta(NetBoxTable.Meta):
model = NetBoxUser model = ObjectPermission
fields = ( fields = (
'pk', 'id', 'name', 'enabled', 'actions', 'constraints', 'pk', 'id', 'name', 'enabled', 'actions', 'constraints',
) )

View File

@ -450,7 +450,7 @@ class NetBoxGroupBulkDeleteView(generic.BulkDeleteView):
class ObjectPermissionListView(generic.ObjectListView): class ObjectPermissionListView(generic.ObjectListView):
queryset = NetBoxGroup.objects.all() queryset = ObjectPermission.objects.all()
filterset = filtersets.ObjectPermissionFilterSet filterset = filtersets.ObjectPermissionFilterSet
filterset_form = forms.ObjectPermissionFilterForm filterset_form = forms.ObjectPermissionFilterForm
table = tables.ObjectPermissionTable table = tables.ObjectPermissionTable
@ -458,7 +458,7 @@ class ObjectPermissionListView(generic.ObjectListView):
@register_model_view(ObjectPermission) @register_model_view(ObjectPermission)
class ObjectPermissionView(generic.ObjectView): class ObjectPermissionView(generic.ObjectView):
queryset = NetBoxGroup.objects.all() queryset = ObjectPermission.objects.all()
template_name = 'users/objectpermission.html' template_name = 'users/objectpermission.html'
def get_extra_context(self, request, instance): def get_extra_context(self, request, instance):