providers/proxy: add domainless URL Validator
This commit is contained in:
parent
696aa7e5f6
commit
7fe9b8f0b4
|
@ -1,5 +1,9 @@
|
||||||
"""Generic models"""
|
"""Generic models"""
|
||||||
|
import re
|
||||||
|
|
||||||
|
from django.core.validators import URLValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.regex_helper import _lazy_re_compile
|
||||||
from model_utils.managers import InheritanceManager
|
from model_utils.managers import InheritanceManager
|
||||||
from rest_framework.serializers import BaseSerializer
|
from rest_framework.serializers import BaseSerializer
|
||||||
|
|
||||||
|
@ -48,3 +52,21 @@ class InheritanceForeignKey(models.ForeignKey):
|
||||||
"""Custom ForeignKey that uses InheritanceForwardManyToOneDescriptor"""
|
"""Custom ForeignKey that uses InheritanceForwardManyToOneDescriptor"""
|
||||||
|
|
||||||
forward_related_accessor_class = InheritanceForwardManyToOneDescriptor
|
forward_related_accessor_class = InheritanceForwardManyToOneDescriptor
|
||||||
|
|
||||||
|
|
||||||
|
class DomainlessURLValidator(URLValidator):
|
||||||
|
"""Subclass of URLValidator which doesn't check the domain
|
||||||
|
(to allow hostnames without domain)"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs) -> None:
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.host_re = "(" + self.hostname_re + self.domain_re + "|localhost)"
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Generated by Django 3.1.1 on 2020-09-13 19:47
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import passbook.lib.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("passbook_providers_proxy", "0003_proxyprovider_certificate"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="proxyprovider",
|
||||||
|
name="external_host",
|
||||||
|
field=models.TextField(
|
||||||
|
validators=[
|
||||||
|
passbook.lib.models.DomainlessURLValidator(
|
||||||
|
schemes=("http", "https")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="proxyprovider",
|
||||||
|
name="internal_host",
|
||||||
|
field=models.TextField(
|
||||||
|
validators=[
|
||||||
|
passbook.lib.models.DomainlessURLValidator(
|
||||||
|
schemes=("http", "https")
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -4,12 +4,12 @@ from random import SystemRandom
|
||||||
from typing import Iterable, Type
|
from typing import Iterable, Type
|
||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
from django.core.validators import URLValidator
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from passbook.crypto.models import CertificateKeyPair
|
from passbook.crypto.models import CertificateKeyPair
|
||||||
|
from passbook.lib.models import DomainlessURLValidator
|
||||||
from passbook.outposts.models import OutpostModel
|
from passbook.outposts.models import OutpostModel
|
||||||
from passbook.providers.oauth2.constants import (
|
from passbook.providers.oauth2.constants import (
|
||||||
SCOPE_OPENID,
|
SCOPE_OPENID,
|
||||||
|
@ -41,10 +41,10 @@ class ProxyProvider(OutpostModel, OAuth2Provider):
|
||||||
Protocols by using a Reverse-Proxy."""
|
Protocols by using a Reverse-Proxy."""
|
||||||
|
|
||||||
internal_host = models.TextField(
|
internal_host = models.TextField(
|
||||||
validators=[URLValidator(schemes=("http", "https"))]
|
validators=[DomainlessURLValidator(schemes=("http", "https"))]
|
||||||
)
|
)
|
||||||
external_host = models.TextField(
|
external_host = models.TextField(
|
||||||
validators=[URLValidator(schemes=("http", "https"))]
|
validators=[DomainlessURLValidator(schemes=("http", "https"))]
|
||||||
)
|
)
|
||||||
|
|
||||||
cookie_secret = models.TextField(default=get_cookie_secret)
|
cookie_secret = models.TextField(default=get_cookie_secret)
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Generated by Django 3.1.1 on 2020-09-13 19:47
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import passbook.lib.models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("passbook_sources_ldap", "0004_auto_20200524_1146"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="ldapsource",
|
||||||
|
name="server_uri",
|
||||||
|
field=models.TextField(
|
||||||
|
validators=[
|
||||||
|
passbook.lib.models.DomainlessURLValidator(
|
||||||
|
schemes=["ldap", "ldaps"]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
verbose_name="Server URI",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,20 +1,20 @@
|
||||||
"""passbook LDAP Models"""
|
"""passbook LDAP Models"""
|
||||||
from typing import Optional, Type
|
from typing import Optional, Type
|
||||||
|
|
||||||
from django.core.validators import URLValidator
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
from ldap3 import Connection, Server
|
from ldap3 import Connection, Server
|
||||||
|
|
||||||
from passbook.core.models import Group, PropertyMapping, Source
|
from passbook.core.models import Group, PropertyMapping, Source
|
||||||
|
from passbook.lib.models import DomainlessURLValidator
|
||||||
|
|
||||||
|
|
||||||
class LDAPSource(Source):
|
class LDAPSource(Source):
|
||||||
"""Federate LDAP Directory with passbook, or create new accounts in LDAP."""
|
"""Federate LDAP Directory with passbook, or create new accounts in LDAP."""
|
||||||
|
|
||||||
server_uri = models.TextField(
|
server_uri = models.TextField(
|
||||||
validators=[URLValidator(schemes=["ldap", "ldaps"])],
|
validators=[DomainlessURLValidator(schemes=["ldap", "ldaps"])],
|
||||||
verbose_name=_("Server URI"),
|
verbose_name=_("Server URI"),
|
||||||
)
|
)
|
||||||
bind_cn = models.TextField(verbose_name=_("Bind CN"))
|
bind_cn = models.TextField(verbose_name=_("Bind CN"))
|
||||||
|
|
Reference in New Issue