Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions server/mergin/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from flask_mail import Mail
from connexion.apps.flask_app import FlaskJSONEncoder
from flask_wtf import FlaskForm
from wtforms import StringField
from pathlib import Path
import sys
import time
Expand Down Expand Up @@ -433,3 +434,14 @@ class ResponseError:

def to_dict(self) -> Dict:
return dict(code=self.code, detail=self.detail + f" ({self.code})")

def whitespace_filter(obj):
return obj.strip() if isinstance(obj, str) else obj

class CustomStringField(StringField):
""" Custom class for string form fields """
def __init__(self, *args, **kwargs):
filters = kwargs.get("filters")
# add whitespace filter
kwargs["filters"] = (*filters, whitespace_filter) if filters else (whitespace_filter, )
super().__init__(*args, **kwargs)
24 changes: 9 additions & 15 deletions server/mergin/auth/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,7 @@
)

from .models import User
from ..app import UpdateForm


def whitespace_filter(obj):
return obj.strip() if isinstance(obj, str) else obj
from ..app import UpdateForm, CustomStringField


def username_validation(form, field):
Expand Down Expand Up @@ -51,20 +47,18 @@ def __call__(self, form, field):
class LoginForm(FlaskForm):
"""Form with username and password fields for user to sign in."""

login = StringField(validators=[DataRequired(), Length(max=80)])
login = CustomStringField(validators=[DataRequired(), Length(max=80)])
password = PasswordField(validators=[DataRequired()])


class RegisterUserForm(FlaskForm):
username = StringField(
username = CustomStringField(
"Username",
validators=[validators.Length(min=4, max=25), username_validation],
filters=(whitespace_filter,),
)
email = StringField(
email = CustomStringField(
"Email Address",
validators=[DataRequired(), Email()],
filters=(whitespace_filter,),
)

def validate(self):
Expand All @@ -85,8 +79,8 @@ def validate(self):


class ResetPasswordForm(FlaskForm):
email = StringField(
"Email Address", [DataRequired(), Email()], filters=(whitespace_filter,)
email = CustomStringField(
"Email Address", [DataRequired(), Email()],
)


Expand Down Expand Up @@ -119,9 +113,9 @@ class UserProfileDataForm(UpdateForm):
"""This form is for user profile update"""

receive_notifications = BooleanField("Receive notifications", [Optional()])
first_name = StringField("First Name", [Optional()], filters=(whitespace_filter,))
last_name = StringField("Last Name", [Optional()], filters=(whitespace_filter,))
email = StringField("Email", [Optional(), Email()], filters=(whitespace_filter,))
first_name = CustomStringField("First Name", [Optional()])
last_name = CustomStringField("Last Name", [Optional()])
email = CustomStringField("Email", [Optional(), Email()])


class ApiLoginForm(LoginForm):
Expand Down
3 changes: 2 additions & 1 deletion server/mergin/tests/test_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ def client(app):
return client


# login tests: success, success with email login, invalid password, missing password, wrong headers
# login tests: success, success with trailing space, success with email login, invalid password, missing password, wrong headers
test_login_data = [
({"login": "mergin", "password": "ilovemergin"}, json_headers, 200),
({"login": "mergin ", "password": "ilovemergin"}, json_headers, 200),
({"login": "mergin@mergin.com", "password": "ilovemergin"}, json_headers, 200),
({"login": "mergin", "password": "ilovemergi"}, json_headers, 401),
({"login": "mergin"}, json_headers, 401),
Expand Down