diff --git a/netbox/extras/urls.py b/netbox/extras/urls.py index d8619f6f9..14e74c5ca 100644 --- a/netbox/extras/urls.py +++ b/netbox/extras/urls.py @@ -120,15 +120,15 @@ urlpatterns = [ path('scripts/', views.ScriptListView.as_view(), name='script_list'), path('scripts/add/', views.ScriptModuleCreateView.as_view(), name='scriptmodule_add'), path('scripts/results//', views.ScriptResultView.as_view(), name='script_result'), - path('scripts//', include(get_model_urls('extras', 'scriptmodule'))), + path('scripts//', views.ScriptView.as_view(), name='script'), + path('scripts//source/', views.ScriptSourceView.as_view(), name='script_source'), + path('scripts//jobs/', views.ScriptJobsView.as_view(), name='script_jobs'), + path('script-modules//', include(get_model_urls('extras', 'scriptmodule'))), - path('scripts///', views.ScriptModuleView.as_view(), name='script_module'), - path('scripts///source/', views.ScriptModuleSourceView.as_view(), name='script_module_source'), - path('scripts///jobs/', views.ScriptModuleJobsView.as_view(), name='script_module_jobs'), - - path('script-modules//', views.ScriptView.as_view(), name='script'), - path('scripts-modules//source/', views.ScriptSourceView.as_view(), name='script_source'), - path('scripts-modules//jobs/', views.ScriptJobsView.as_view(), name='script_jobs'), + # Redirects for legacy script URLs + # TODO: Remove in NetBox v4.1 + path('scripts///', views.LegacyScriptRedirectView.as_view()), + path('scripts////', views.LegacyScriptRedirectView.as_view()), # Markdown path('render/markdown/', views.RenderMarkdownView.as_view(), name="render_markdown"), diff --git a/netbox/extras/views.py b/netbox/extras/views.py index 31b054dc8..7a177ef2e 100644 --- a/netbox/extras/views.py +++ b/netbox/extras/views.py @@ -1132,25 +1132,6 @@ class ScriptView(BaseScriptView): }) -class ScriptModuleView(ScriptView): - - def get(self, request, module, name): - if ret := self.get_script_by_module_name(request, module, name): - return ret - - form = None - if self.script_class: - form = self.script_class.as_form(initial=normalize_querydict(request.GET)) - - return render(request, 'extras/script.html', { - 'job_count': self.jobs.count(), - 'module': self.script.module, - 'script': self.script, - 'script_class': self.script_class, - 'form': form, - }) - - class ScriptSourceView(BaseScriptView): def get(self, request, pk): @@ -1166,21 +1147,6 @@ class ScriptSourceView(BaseScriptView): }) -class ScriptModuleSourceView(ScriptSourceView): - - def get(self, request, module, name): - if ret := self.get_script_by_module_name(request, module, name): - return ret - - return render(request, 'extras/script/source.html', { - 'job_count': self.jobs.count(), - 'module': self.script.module, - 'script': self.script, - 'script_class': self.script_class, - 'tab': 'source', - }) - - class ScriptJobsView(ContentTypePermissionRequiredMixin, View): script = None script_class = None @@ -1218,35 +1184,23 @@ class ScriptJobsView(ContentTypePermissionRequiredMixin, View): }) -class ScriptModuleJobsView(ScriptJobsView): - def get(self, request, module, name): - module = get_script_module(module, request) - self.script = get_object_or_404(Script.objects.all(), module=module, name=name) +class LegacyScriptRedirectView(ContentTypePermissionRequiredMixin, View): + """ + Redirect legacy (pre-v4.0) script URLs. Examples: + /extras/scripts/// --> /extras/scripts// + /extras/scripts///source/ --> /extras/scripts//source/ + /extras/scripts///jobs/ --> /extras/scripts//jobs/ + """ + def get_required_permission(self): + return 'extras.view_script' - if self.script.python_class: - self.script_class = self.script.python_class() - else: - self.script.delete_if_no_jobs() - if not self.script.id: - messages.error(request, _("Script class has been deleted from module: ") + str(self.script.module)) - return redirect('extras:script_list') + def get(self, request, module, name, path=''): + module = get_object_or_404(ScriptModule.objects.restrict(request.user), file_path__regex=f"^{module}\\.") + script = get_object_or_404(Script.objects.all(), module=module, name=name) - self.jobs = self.script.jobs.all() + url = reverse('extras:script', kwargs={'pk': script.pk}) - jobs_table = JobTable( - data=self.jobs, - orderable=False, - user=request.user - ) - jobs_table.configure(request) - - return render(request, 'extras/script/jobs.html', { - 'job_count': self.jobs.count(), - 'module': self.script.module, - 'script': self.script, - 'table': jobs_table, - 'tab': 'jobs', - }) + return redirect(f'{url}{path}') class ScriptResultView(BaseScriptView):