Przeglądaj źródła

Work on #6221 - Make templatetags safe for consumption when using plugins and update ButtonColumn to use viewname helper.

Daniel Sheppard 4 lat temu
rodzic
commit
88ac0f5d34

+ 4 - 3
netbox/utilities/tables.py

@@ -216,18 +216,19 @@ class ButtonsColumn(tables.TemplateColumn):
     attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
     attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
     # Note that braces are escaped to allow for string formatting prior to template rendering
     # Note that braces are escaped to allow for string formatting prior to template rendering
     template_code = """
     template_code = """
+    {{% load helpers %}}
     {{% if "changelog" in buttons %}}
     {{% if "changelog" in buttons %}}
-        <a href="{{% url '{app_label}:{model_name}_changelog' pk=record.pk %}}" class="btn btn-outline-dark btn-sm" title="Change log">
+        <a href="{{% url record|viewname:'changelog' pk=record.pk %}}" class="btn btn-outline-dark btn-sm" title="Change log">
             <i class="mdi mdi-history"></i>
             <i class="mdi mdi-history"></i>
         </a>
         </a>
     {{% endif %}}
     {{% endif %}}
     {{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
     {{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
-        <a href="{{% url '{app_label}:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-warning" title="Edit">
+        <a href="{{% url record|viewname:'edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-warning" title="Edit">
             <i class="mdi mdi-pencil"></i>
             <i class="mdi mdi-pencil"></i>
         </a>
         </a>
     {{% endif %}}
     {{% endif %}}
     {{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}}
     {{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}}
-        <a href="{{% url '{app_label}:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-danger" title="Delete">
+        <a href="{{% url record|viewname:'delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-danger" title="Delete">
             <i class="mdi mdi-trash-can-outline"></i>
             <i class="mdi mdi-trash-can-outline"></i>
         </a>
         </a>
     {{% endif %}}
     {{% endif %}}

+ 6 - 3
netbox/utilities/templatetags/helpers.py

@@ -16,9 +16,10 @@ from django.utils.safestring import mark_safe
 from markdown import markdown
 from markdown import markdown
 
 
 from netbox.config import get_config
 from netbox.config import get_config
+from netbox.settings import PLUGINS
 from utilities.forms import get_selected_values, TableConfigForm
 from utilities.forms import get_selected_values, TableConfigForm
 from utilities.markdown import StrikethroughExtension
 from utilities.markdown import StrikethroughExtension
-from utilities.utils import foreground_color
+from utilities.utils import foreground_color, resolve_namespace
 
 
 register = template.Library()
 register = template.Library()
 
 
@@ -115,7 +116,8 @@ def viewname(model, action):
     """
     """
     Return the view name for the given model and action. Does not perform any validation.
     Return the view name for the given model and action. Does not perform any validation.
     """
     """
-    return f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+    namespace = resolve_namespace(model)
+    return f'{namespace}:{model._meta.model_name}_{action}'
 
 
 
 
 @register.filter()
 @register.filter()
@@ -123,7 +125,8 @@ def validated_viewname(model, action):
     """
     """
     Return the view name for the given model and action if valid, or None if invalid.
     Return the view name for the given model and action if valid, or None if invalid.
     """
     """
-    viewname = f'{model._meta.app_label}:{model._meta.model_name}_{action}'
+    namespace = resolve_namespace(model)
+    viewname = f'{namespace}:{model._meta.model_name}_{action}'
     try:
     try:
         # Validate and return the view name. We don't return the actual URL yet because many of the templates
         # Validate and return the view name. We don't return the actual URL yet because many of the templates
         # are written to pass a name to {% url %}.
         # are written to pass a name to {% url %}.

+ 10 - 0
netbox/utilities/utils.py

@@ -13,10 +13,20 @@ from jinja2.sandbox import SandboxedEnvironment
 from mptt.models import MPTTModel
 from mptt.models import MPTTModel
 
 
 from dcim.choices import CableLengthUnitChoices
 from dcim.choices import CableLengthUnitChoices
+from extras.plugins import PluginConfig
 from extras.utils import is_taggable
 from extras.utils import is_taggable
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 from utilities.constants import HTTP_REQUEST_META_SAFE_COPY
 
 
 
 
+def resolve_namespace(instance):
+    """
+    Get the appropriate namepsace for the app based on whether it is a Plugin or base application
+    """
+    if isinstance(instance._meta.app_config, PluginConfig):
+        return f'plugins:{instance._meta.app_label}'
+    return f'{instance._meta.app_label}'
+
+
 def csv_format(data):
 def csv_format(data):
     """
     """
     Encapsulate any data which contains a comma within double quotes.
     Encapsulate any data which contains a comma within double quotes.