core: add validator which allows for URLs with formatting (#4890)
This commit is contained in:
parent
9b8c0e3924
commit
86bb2afd02
|
@ -182,7 +182,9 @@ class Migration(migrations.Migration):
|
||||||
model_name="application",
|
model_name="application",
|
||||||
name="meta_launch_url",
|
name="meta_launch_url",
|
||||||
field=models.TextField(
|
field=models.TextField(
|
||||||
blank=True, default="", validators=[authentik.lib.models.DomainlessURLValidator()]
|
blank=True,
|
||||||
|
default="",
|
||||||
|
validators=[authentik.lib.models.DomainlessFormattedURLValidator()],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
migrations.RunPython(
|
migrations.RunPython(
|
||||||
|
|
|
@ -26,7 +26,11 @@ from authentik.core.types import UILoginButton, UserSettingSerializer
|
||||||
from authentik.lib.avatars import get_avatar
|
from authentik.lib.avatars import get_avatar
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
from authentik.lib.models import CreatedUpdatedModel, DomainlessURLValidator, SerializerModel
|
from authentik.lib.models import (
|
||||||
|
CreatedUpdatedModel,
|
||||||
|
DomainlessFormattedURLValidator,
|
||||||
|
SerializerModel,
|
||||||
|
)
|
||||||
from authentik.lib.utils.http import get_client_ip
|
from authentik.lib.utils.http import get_client_ip
|
||||||
from authentik.policies.models import PolicyBindingModel
|
from authentik.policies.models import PolicyBindingModel
|
||||||
|
|
||||||
|
@ -291,7 +295,7 @@ class Application(SerializerModel, PolicyBindingModel):
|
||||||
)
|
)
|
||||||
|
|
||||||
meta_launch_url = models.TextField(
|
meta_launch_url = models.TextField(
|
||||||
default="", blank=True, validators=[DomainlessURLValidator()]
|
default="", blank=True, validators=[DomainlessFormattedURLValidator()]
|
||||||
)
|
)
|
||||||
|
|
||||||
open_in_new_tab = models.BooleanField(
|
open_in_new_tab = models.BooleanField(
|
||||||
|
|
|
@ -37,6 +37,22 @@ class TestApplicationsAPI(APITestCase):
|
||||||
order=0,
|
order=0,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_formatted_launch_url(self):
|
||||||
|
"""Test formatted launch URL"""
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
self.assertEqual(
|
||||||
|
self.client.patch(
|
||||||
|
reverse("authentik_api:application-detail", kwargs={"slug": self.allowed.slug}),
|
||||||
|
{"meta_launch_url": "https://%(username)s.test.goauthentik.io/%(username)s"},
|
||||||
|
).status_code,
|
||||||
|
200,
|
||||||
|
)
|
||||||
|
self.allowed.refresh_from_db()
|
||||||
|
self.assertEqual(
|
||||||
|
self.allowed.get_launch_url(self.user),
|
||||||
|
f"https://{self.user.username}.test.goauthentik.io/{self.user.username}",
|
||||||
|
)
|
||||||
|
|
||||||
def test_set_icon(self):
|
def test_set_icon(self):
|
||||||
"""Test set_icon"""
|
"""Test set_icon"""
|
||||||
file = ContentFile(b"text", "name")
|
file = ContentFile(b"text", "name")
|
||||||
|
|
|
@ -74,3 +74,21 @@ class DomainlessURLValidator(URLValidator):
|
||||||
if scheme not in self.schemes:
|
if scheme not in self.schemes:
|
||||||
value = "default" + value
|
value = "default" + value
|
||||||
super().__call__(value)
|
super().__call__(value)
|
||||||
|
|
||||||
|
|
||||||
|
class DomainlessFormattedURLValidator(DomainlessURLValidator):
|
||||||
|
"""URL validator which allows for python format strings"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_re = r"([%\(\)a-zA-Z])+" + self.domain_re + self.domain_re
|
||||||
|
self.regex = _lazy_re_compile(
|
||||||
|
r"^(?:[a-z0-9.+-]*)://" # scheme is validated separately
|
||||||
|
r"(?:[^\s:@/]+(?::[^\s:@/]*)?@)?" # user:pass authentication
|
||||||
|
r"(?:" + self.ipv4_re + "|" + self.ipv6_re + "|" + self.host_re + ")"
|
||||||
|
r"(?::\d{2,5})?" # port
|
||||||
|
r"(?:[/?#][^\s]*)?" # resource path
|
||||||
|
r"\Z",
|
||||||
|
re.IGNORECASE,
|
||||||
|
)
|
||||||
|
self.schemes = ["http", "https", "blank"] + list(self.schemes)
|
||||||
|
|
Reference in New Issue