mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Update ObjectImportView to support ObjectPermissions
This commit is contained in:
@ -627,8 +627,8 @@ class DeviceTypeDeleteView(ObjectDeleteView):
|
|||||||
default_return_url = 'dcim:devicetype_list'
|
default_return_url = 'dcim:devicetype_list'
|
||||||
|
|
||||||
|
|
||||||
class DeviceTypeImportView(PermissionRequiredMixin, ObjectImportView):
|
class DeviceTypeImportView(ObjectImportView):
|
||||||
permission_required = [
|
additional_permissions = [
|
||||||
'dcim.add_devicetype',
|
'dcim.add_devicetype',
|
||||||
'dcim.add_consoleporttemplate',
|
'dcim.add_consoleporttemplate',
|
||||||
'dcim.add_consoleserverporttemplate',
|
'dcim.add_consoleserverporttemplate',
|
||||||
@ -639,7 +639,7 @@ class DeviceTypeImportView(PermissionRequiredMixin, ObjectImportView):
|
|||||||
'dcim.add_rearporttemplate',
|
'dcim.add_rearporttemplate',
|
||||||
'dcim.add_devicebaytemplate',
|
'dcim.add_devicebaytemplate',
|
||||||
]
|
]
|
||||||
model = DeviceType
|
queryset = DeviceType.objects.all()
|
||||||
model_form = forms.DeviceTypeImportForm
|
model_form = forms.DeviceTypeImportForm
|
||||||
related_object_forms = OrderedDict((
|
related_object_forms = OrderedDict((
|
||||||
('console-ports', forms.ConsolePortTemplateImportForm),
|
('console-ports', forms.ConsolePortTemplateImportForm),
|
||||||
|
@ -571,21 +571,29 @@ class BulkCreateView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class ObjectImportView(GetReturnURLMixin, View):
|
class ObjectImportView(GetReturnURLMixin, ObjectPermissionRequiredMixin, View):
|
||||||
"""
|
"""
|
||||||
Import a single object (YAML or JSON format).
|
Import a single object (YAML or JSON format).
|
||||||
|
|
||||||
|
queryset: Base queryset for the objects being created
|
||||||
|
model_form: The ModelForm used to create individual objects
|
||||||
|
related_object_forms: A dictionary mapping of forms to be used for the creation of related (child) objects
|
||||||
|
template_name: The name of the template
|
||||||
"""
|
"""
|
||||||
model = None
|
queryset = None
|
||||||
model_form = None
|
model_form = None
|
||||||
related_object_forms = dict()
|
related_object_forms = dict()
|
||||||
template_name = 'utilities/obj_import.html'
|
template_name = 'utilities/obj_import.html'
|
||||||
|
|
||||||
|
def get_required_permission(self):
|
||||||
|
return get_permission_for_model(self.queryset.model, 'add')
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
form = ImportForm()
|
form = ImportForm()
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'form': form,
|
'form': form,
|
||||||
'obj_type': self.model._meta.verbose_name,
|
'obj_type': self.queryset.model._meta.verbose_name,
|
||||||
'return_url': self.get_return_url(request),
|
'return_url': self.get_return_url(request),
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -615,12 +623,17 @@ class ObjectImportView(GetReturnURLMixin, View):
|
|||||||
|
|
||||||
# Save the primary object
|
# Save the primary object
|
||||||
obj = model_form.save()
|
obj = model_form.save()
|
||||||
|
|
||||||
|
# Enforce object-level permissions
|
||||||
|
self.queryset.get(pk=obj.pk)
|
||||||
|
|
||||||
logger.debug(f"Created {obj} (PK: {obj.pk})")
|
logger.debug(f"Created {obj} (PK: {obj.pk})")
|
||||||
|
|
||||||
# Iterate through the related object forms (if any), validating and saving each instance.
|
# Iterate through the related object forms (if any), validating and saving each instance.
|
||||||
for field_name, related_object_form in self.related_object_forms.items():
|
for field_name, related_object_form in self.related_object_forms.items():
|
||||||
logger.debug("Processing form for related objects: {related_object_form}")
|
logger.debug("Processing form for related objects: {related_object_form}")
|
||||||
|
|
||||||
|
related_obj_pks = []
|
||||||
for i, rel_obj_data in enumerate(data.get(field_name, list())):
|
for i, rel_obj_data in enumerate(data.get(field_name, list())):
|
||||||
|
|
||||||
f = related_object_form(obj, rel_obj_data)
|
f = related_object_form(obj, rel_obj_data)
|
||||||
@ -630,7 +643,8 @@ class ObjectImportView(GetReturnURLMixin, View):
|
|||||||
f.data[subfield_name] = field.initial
|
f.data[subfield_name] = field.initial
|
||||||
|
|
||||||
if f.is_valid():
|
if f.is_valid():
|
||||||
f.save()
|
related_obj = f.save()
|
||||||
|
related_obj_pks.append(related_obj.pk)
|
||||||
else:
|
else:
|
||||||
# Replicate errors on the related object form to the primary form for display
|
# Replicate errors on the related object form to the primary form for display
|
||||||
for subfield_name, errors in f.errors.items():
|
for subfield_name, errors in f.errors.items():
|
||||||
@ -639,9 +653,19 @@ class ObjectImportView(GetReturnURLMixin, View):
|
|||||||
model_form.add_error(None, err_msg)
|
model_form.add_error(None, err_msg)
|
||||||
raise AbortTransaction()
|
raise AbortTransaction()
|
||||||
|
|
||||||
|
# Enforce object-level permissions on related objects
|
||||||
|
model = related_object_form.Meta.model
|
||||||
|
if model.objects.filter(pk__in=related_obj_pks).count() != len(related_obj_pks):
|
||||||
|
raise ObjectDoesNotExist
|
||||||
|
|
||||||
except AbortTransaction:
|
except AbortTransaction:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
msg = "Object creation failed due to object-level permissions violation"
|
||||||
|
logger.debug(msg)
|
||||||
|
form.add_error(None, msg)
|
||||||
|
|
||||||
if not model_form.errors:
|
if not model_form.errors:
|
||||||
logger.info(f"Import object {obj} (PK: {obj.pk})")
|
logger.info(f"Import object {obj} (PK: {obj.pk})")
|
||||||
messages.success(request, mark_safe('Imported object: <a href="{}">{}</a>'.format(
|
messages.success(request, mark_safe('Imported object: <a href="{}">{}</a>'.format(
|
||||||
@ -673,7 +697,7 @@ class ObjectImportView(GetReturnURLMixin, View):
|
|||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'form': form,
|
'form': form,
|
||||||
'obj_type': self.model._meta.verbose_name,
|
'obj_type': self.queryset.model._meta.verbose_name,
|
||||||
'return_url': self.get_return_url(request),
|
'return_url': self.get_return_url(request),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user