From ecf768d544429b01754df2ab85d258d82818396b Mon Sep 17 00:00:00 2001 From: Robert Sparks Date: Mon, 14 Feb 2022 18:40:24 +0000 Subject: [PATCH] Merged in [19925] from jennifer@painless-security.com: Suppress origin template tag in production mode, show relative path only in other modes. - Legacy-Id: 19932 Note: SVN reference [19925] has been migrated to Git commit b4d07e11519d77523216bc8817058b0facd2bd41 --- ietf/utils/templatetags/origin.py | 30 ++++++++++++++++------ ietf/utils/templatetags/tests.py | 41 +++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 ietf/utils/templatetags/tests.py diff --git a/ietf/utils/templatetags/origin.py b/ietf/utils/templatetags/origin.py index 3ac3028d9..3a8adf1d5 100644 --- a/ietf/utils/templatetags/origin.py +++ b/ietf/utils/templatetags/origin.py @@ -1,5 +1,12 @@ +# Copyright The IETF Trust 2015-2022, All Rights Reserved +# -*- coding: utf-8 -*- +from pathlib import Path + from django import template +from django.conf import settings + import debug # pyflakes:ignore +from ietf.utils import log register = template.Library() @@ -9,19 +16,26 @@ class OriginNode(template.Node): # template file path if the template comes from a file: self.origin = origin + def relative_path(self): + origin_path = Path(str(self.origin)) + try: + return origin_path.relative_to(settings.BASE_DIR) + except ValueError: + log.log(f'Rendering a template from outside the project root: {self.origin}') + return '** path outside project root **' + def render(self, context): - if self.origin: - return "" % self.origin + if self.origin and settings.SERVER_MODE != 'production': + return f'' else: return "" -@register.tag -def origin(parser, token): - """ - Returns a node which renders the - """ + +@register.tag('origin') +def origin_tag(parser, token): + """Create a node indicating the path to the current template""" if hasattr(token, "source"): origin, source = token.source - return OriginNode(origin=origin) + return OriginNode(origin) else: return OriginNode() diff --git a/ietf/utils/templatetags/tests.py b/ietf/utils/templatetags/tests.py new file mode 100644 index 000000000..a93bf2d94 --- /dev/null +++ b/ietf/utils/templatetags/tests.py @@ -0,0 +1,41 @@ +# Copyright The IETF Trust 2022, All Rights Reserved +# -*- coding: utf-8 -*- +from django.template import Context, Origin, Template +from django.test import override_settings + +from ietf.utils.test_utils import TestCase +import debug # pyflakes: ignore + + +@override_settings(BASE_DIR='/fake/base/') +class OriginTests(TestCase): + def test_origin_not_shown_in_production(self): + template = Template( + '{% load origin %}{% origin %}', + origin=Origin('/fake/base/templates/my-template.html'), + ) + with override_settings(SERVER_MODE='production'): + self.assertEqual(template.render(Context()), '') + + def test_origin_shown_in_development_and_test(self): + template = Template( + '{% load origin %}{% origin %}', + origin=Origin('/fake/base/templates/my-template.html'), + ) + for mode in ['development', 'test']: + with override_settings(SERVER_MODE=mode): + output = template.render(Context()) + self.assertIn('templates/my-template.html', output) + for component in ['fake', 'base']: + self.assertNotIn(component, output, 'Reported path should be relative to BASE_DIR') + + def test_origin_outside_base_dir(self): + template = Template( + '{% load origin %}{% origin %}', + origin=Origin('/different/templates/my-template.html'), + ) + with override_settings(SERVER_MODE='development'): + for component in ['fake', 'base', 'different', 'templates']: + output = template.render(Context()) + self.assertNotIn(component, output, + 'Full path components should not be revealed in html')