mirror of
https://github.com/netbox-community/netbox.git
synced 2026-03-21 20:18:38 -06:00
Add RESERVED_ACTIONS constant and fix dedup in registered actions
- Define RESERVED_ACTIONS in users/constants.py for the four built-in permission actions (view, add, change, delete) - Replace hardcoded action lists in ObjectPermissionForm with the constant - Fix duplicate action names in clean() when the same action is registered across multiple models (e.g. render_config for Device and VirtualMachine) - Fix template substring matching bug in objectpermission.html detail view by passing RESERVED_ACTIONS through view context for proper list membership
This commit is contained in:
@@ -47,7 +47,7 @@
|
||||
<td>{% checkmark object.can_delete %}</td>
|
||||
</tr>
|
||||
{% for action in object.actions %}
|
||||
{% if action not in 'view,add,change,delete' %}
|
||||
{% if action not in reserved_actions %}
|
||||
<tr>
|
||||
<th scope="row">{{ action }}</th>
|
||||
<td>{% checkmark True %}</td>
|
||||
|
||||
@@ -10,6 +10,10 @@ OBJECTPERMISSION_OBJECT_TYPES = (
|
||||
|
||||
CONSTRAINT_TOKEN_USER = '$user'
|
||||
|
||||
# Built-in actions that receive special handling (dedicated checkboxes, model properties)
|
||||
# and should not be registered as custom model actions.
|
||||
RESERVED_ACTIONS = ('view', 'add', 'change', 'delete')
|
||||
|
||||
# API tokens
|
||||
TOKEN_PREFIX = 'nbt_' # Used for v2 tokens only
|
||||
TOKEN_KEY_LENGTH = 12
|
||||
|
||||
@@ -423,7 +423,7 @@ class ObjectPermissionForm(forms.ModelForm):
|
||||
remaining_actions = list(self.instance.actions)
|
||||
|
||||
# Check the appropriate CRUD checkboxes
|
||||
for action in ['view', 'add', 'change', 'delete']:
|
||||
for action in RESERVED_ACTIONS:
|
||||
if action in remaining_actions:
|
||||
self.fields[f'can_{action}'].initial = True
|
||||
remaining_actions.remove(action)
|
||||
@@ -450,7 +450,7 @@ class ObjectPermissionForm(forms.ModelForm):
|
||||
if isinstance(self.initial['actions'], str):
|
||||
self.initial['actions'] = [self.initial['actions']]
|
||||
if cloned_actions := self.initial['actions']:
|
||||
for action in ['view', 'add', 'change', 'delete']:
|
||||
for action in RESERVED_ACTIONS:
|
||||
if action in cloned_actions:
|
||||
self.fields[f'can_{action}'].initial = True
|
||||
self.initial['actions'].remove(action)
|
||||
@@ -479,10 +479,11 @@ class ObjectPermissionForm(forms.ModelForm):
|
||||
'Action "{action}" is for {model} which is not selected.'
|
||||
).format(action=action_name, model=model_key)
|
||||
})
|
||||
final_actions.append(action_name)
|
||||
if action_name not in final_actions:
|
||||
final_actions.append(action_name)
|
||||
|
||||
# Append any of the selected CRUD checkboxes to the actions list
|
||||
for action in ['view', 'add', 'change', 'delete']:
|
||||
for action in RESERVED_ACTIONS:
|
||||
if self.cleaned_data.get(f'can_{action}') and action not in final_actions:
|
||||
final_actions.append(action)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from utilities.query import count_related
|
||||
from utilities.views import GetRelatedModelsMixin, register_model_view
|
||||
|
||||
from . import filtersets, forms, tables
|
||||
from .constants import RESERVED_ACTIONS
|
||||
from .models import Group, ObjectPermission, Owner, OwnerGroup, Token, User
|
||||
|
||||
#
|
||||
@@ -214,6 +215,11 @@ class ObjectPermissionView(generic.ObjectView):
|
||||
queryset = ObjectPermission.objects.all()
|
||||
template_name = 'users/objectpermission.html'
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
'reserved_actions': RESERVED_ACTIONS,
|
||||
}
|
||||
|
||||
|
||||
@register_model_view(ObjectPermission, 'add', detail=False)
|
||||
@register_model_view(ObjectPermission, 'edit')
|
||||
|
||||
Reference in New Issue
Block a user