Skip to content
Snippets Groups Projects
Commit 9cdff1b5 authored by HeJ's avatar HeJ
Browse files

extend core.utils.resolve_internal_url() to allow any HTTP url

This is done to allow internal URLs in RoomLinks without having to
handle non-internal URLs in a different way.
parent f468fb0a
Branches
Tags
No related merge requests found
......@@ -134,7 +134,7 @@ class MyHtmlRenderer(HTMLRenderer):
from .utils import resolve_internal_url
# attempt resolving an internal URL
if resolved_internal_url := resolve_internal_url(url, fallback_as_is=False):
if resolved_internal_url := resolve_internal_url(url, accept_http_https=False, fallback_as_is=False):
url = resolved_internal_url
# derive external link (i.e. apply dereferer), if its not an internal or trusted location
......
......@@ -8,7 +8,6 @@ from django.conf import settings
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.postgres.fields import DateTimeRangeField
from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.db import models
from django.db.models import Q, QuerySet
from django.utils.text import slugify
......@@ -21,7 +20,7 @@ from core.models.base_managers import ConferenceManagerMixin
from core.models.conference import Conference, ConferenceMember
from core.models.shared import BackendMixin
from core.models.tags import TagItem
from core.utils import str2bool
from core.utils import resolve_internal_url, str2bool
from core.validators import FileSizeValidator, ImageDimensionValidator
......@@ -483,10 +482,7 @@ class RoomLink(models.Model):
def clean(self):
if self.link_type in RoomLink.URL_LINKTYPES:
validator = URLValidator()
try:
validator(self.link)
except ValidationError:
if not resolve_internal_url(self.link, fallback_as_is=False):
raise ValidationError({'link': _('RoomLink__link__must_be_url')})
def __str__(self):
......
......@@ -90,6 +90,18 @@ class InternalUrlTests(TestCase):
for check in checks:
self.assertEqual(check[1], resolve_internal_url(check[0]))
# combinations of accept_http_https and fallback_as_is with a https URL
self.assertEqual('https://ccc.de/', resolve_internal_url('https://ccc.de/', accept_http_https=True, fallback_as_is=True))
self.assertEqual('https://ccc.de/', resolve_internal_url('https://ccc.de/', accept_http_https=True, fallback_as_is=False))
self.assertEqual('https://ccc.de/', resolve_internal_url('https://ccc.de/', accept_http_https=False, fallback_as_is=True))
self.assertIsNone(resolve_internal_url('https://ccc.de/', accept_http_https=False, fallback_as_is=False))
# combinations of accept_http_https and fallback_as_is with an invalid URL
self.assertEqual('foo', resolve_internal_url('foo', accept_http_https=True, fallback_as_is=True))
self.assertIsNone(resolve_internal_url('foo', accept_http_https=True, fallback_as_is=False))
self.assertEqual('foo', resolve_internal_url('foo', accept_http_https=False, fallback_as_is=True))
self.assertIsNone(resolve_internal_url('foo', accept_http_https=False, fallback_as_is=False))
@override_settings(ADDITIONAL_LINK_PROTOCOLS={'c3nav': 'https://test.c3nav.de/l/VALUE', 'ccc': 'https://ccc.de/?goto=VALUE'})
def test_additional_link_protocols(self):
checks = [
......
......@@ -156,7 +156,7 @@ def mask_url(url):
return urlunparse(masked)
def resolve_internal_url(url: str, fallback_as_is: bool = True) -> str | None:
def resolve_internal_url(url: str, accept_http_https: bool = True, fallback_as_is: bool = True) -> str | None:
"""
Resolves special URLs like
- conference://url_resolver_name
......@@ -164,7 +164,8 @@ def resolve_internal_url(url: str, fallback_as_is: bool = True) -> str | None:
- event://slug
- wiki://slug
Regular URLs (i.e. https://...) are returned as-is by default but may be resolved as None (i.e. no match).
Regular URLs (i.e. https://...) are accepted by default, too.
Everything else (unparseable, unknown protocl) are returned as-is by default but may be resolved as None (i.e. no match).
"""
try:
protocol, rhs = url.split('://', maxsplit=1)
......@@ -175,6 +176,9 @@ def resolve_internal_url(url: str, fallback_as_is: bool = True) -> str | None:
remainder = rhs_splitted[0]
query_string = '' if len(rhs_splitted) == 1 else rhs_splitted[1]
if accept_http_https and protocol in ['http', 'https']:
return url
try:
from core.templatetags.hub_absolute import hub_absolute # pylint: disable=import-outside-toplevel
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment