aboutsummaryrefslogtreecommitdiff
path: root/webmentions_ssg/forms/validators.py
blob: c4b5eda533f4280468f07145600e40a974098526 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
from urllib.parse import urlsplit

from flask import current_app
from wtforms import ValidationError

from ..url_security import AddressResolutionError, is_public_url


class NotEqualTo:
    """
    Compares the values of two fields.

    :param fieldname:
        The name of the other field to compare to.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated with `%(other_label)s` and `%(other_name)s` to provide a
        more helpful error.
    """

    def __init__(self, fieldname, message=None):
        self.fieldname = fieldname
        self.message = message

    def __call__(self, form, field):
        try:
            other = form[self.fieldname]
        except KeyError as exc:
            raise ValidationError(
                field.gettext("Invalid field name '%s'.") % self.fieldname
            ) from exc

        if field.data != other.data:
            return

        d = {
            "other_label": hasattr(other, "label")
            and other.label.text
            or self.fieldname,
            "other_name": self.fieldname,
        }
        message = self.message
        if message is None:
            message = field.gettext("Field must not be equal to %(other_name)s.")

        raise ValidationError(message % d)


class AllowedHostname:
    def __init__(self, message=None):
        self.message = message

    def __call__(self, form, field):
        if (
            urlsplit(field.data).hostname
            in current_app.config["WEBMENTIONS_SSG_ALLOWED_HOSTNAMES"]
        ):
            return

        message = self.message
        if self.message is None:
            message = field.gettext("Invalid input.")

        raise ValidationError(message)


class PublicURL:
    def __init__(self, message=None):
        self.message = message

    def __call__(self, form, field):
        message = self.message

        if message is None:
            message = field.gettext("URL must resolve to a public address.")

        try:
            if not is_public_url(field.data):
                raise ValidationError(message)
        except (AddressResolutionError, ValueError) as exc:
            raise ValidationError(message) from exc