diff options
Diffstat (limited to '')
| -rw-r--r-- | webmentions_ssg/forms/__init__.py | 42 | ||||
| -rw-r--r-- | webmentions_ssg/forms/validators.py | 62 |
2 files changed, 104 insertions, 0 deletions
diff --git a/webmentions_ssg/forms/__init__.py b/webmentions_ssg/forms/__init__.py new file mode 100644 index 0000000..98962ad --- /dev/null +++ b/webmentions_ssg/forms/__init__.py @@ -0,0 +1,42 @@ +import re + +from flask_wtf import FlaskForm +from wtforms import PasswordField, StringField, SubmitField +from wtforms.validators import URL, InputRequired, Regexp + +from .validators import AllowedHostname, NotEqualTo + + +class LoginForm(FlaskForm): + username = StringField("Username", validators=[InputRequired()]) + password = PasswordField("Password", validators=[InputRequired()]) + submit = SubmitField("Sign In") + + +class EndpointForm(FlaskForm): + source = StringField( + "source", + validators=[ + InputRequired(), + URL(), + Regexp( + "^https?://.*", + flags=re.IGNORECASE, + message="source must begin with http or https", + ), + NotEqualTo("target"), + ], + ) + target = StringField( + "target", + validators=[ + InputRequired(), + URL(), + Regexp( + "^https?://.*", + flags=re.IGNORECASE, + message="target must begin with http or https", + ), + AllowedHostname(), + ], + ) diff --git a/webmentions_ssg/forms/validators.py b/webmentions_ssg/forms/validators.py new file mode 100644 index 0000000..20d9ebf --- /dev/null +++ b/webmentions_ssg/forms/validators.py @@ -0,0 +1,62 @@ +from urllib.parse import urlsplit + +from flask import current_app +from wtforms import ValidationError + + +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) |
