diff --git a/mo/web/acct.py b/mo/web/acct.py index a07888d3dd7b1682c5e3bbf0102374e26097384a..22865e22870e5cb5eacb7a48d1209f4e575a0d83 100644 --- a/mo/web/acct.py +++ b/mo/web/acct.py @@ -13,7 +13,6 @@ from typing import Optional, Dict import werkzeug.exceptions import wtforms from wtforms import validators, ValidationError -from wtforms.fields.html5 import EmailField import mo.config as config import mo.db as db @@ -28,7 +27,7 @@ import mo.web.fields as mo_fields class LoginForm(FlaskForm): next = wtforms.HiddenField() email = mo_fields.Email(validators=[validators.DataRequired()]) - passwd = wtforms.PasswordField('Heslo') + passwd = mo_fields.Password('Heslo') submit = wtforms.SubmitField('Přihlásit se') reset = wtforms.SubmitField('Zapomenuté heslo') @@ -127,7 +126,7 @@ def user_settings(): class SettingsForm(FlaskForm): email = mo_fields.Email(validators=[validators.DataRequired()]) - current_passwd = wtforms.PasswordField('Aktuální heslo', validators=[validators.DataRequired()]) + current_passwd = mo_fields.Password('Aktuální heslo', validators=[validators.DataRequired()]) new_passwd = mo_fields.NewPassword( description=mo.users.password_help + ' Pokud nechcete heslo měnit, ponechte toto políčko prázdné.', ) @@ -354,7 +353,7 @@ class Reg1: class Reg1Form(FlaskForm): email = mo_fields.Email(validators=[validators.DataRequired()]) token = wtforms.HiddenField() - captcha = wtforms.StringField('Kontrolní odpověď', validators=[validators.DataRequired()]) + captcha = mo_fields.String('Kontrolní odpověď', validators=[validators.DataRequired()]) submit = wtforms.SubmitField('Vytvořit účet') diff --git a/mo/web/fields.py b/mo/web/fields.py index 85eeb71fb6655b2f6f2b047968c7d92ee0c949ad..5fcbb6b0c63b460973b63dae11bf2d8fa5224a11 100644 --- a/mo/web/fields.py +++ b/mo/web/fields.py @@ -9,6 +9,19 @@ import mo.users import mo.db as db +class Stripped: + """Zkombinuje se s třídou z WTForms a přidá automatické ořezávání mezer.""" + + def process_formdata(self, valuelist): + if valuelist: + valuelist = [x.strip() for x in valuelist] + super().process_formdata(valuelist) + + +class String(Stripped, wtforms.StringField): + pass + + class OptionalInt(wtforms.IntegerField): widget = NumberInput() @@ -40,7 +53,7 @@ class Decimal(wtforms.DecimalField): return super(Decimal, self)._value() -class IntList(wtforms.StringField): +class IntList(String): list = None def __init__(self, label="", validators=None, **kwargs): @@ -54,13 +67,13 @@ class IntList(wtforms.StringField): except mo.CheckError as e: raise wtforms.ValidationError(str(e)) + class Points(Decimal): def __init__(self, label="Body", validators=None, **kwargs): super().__init__(label, validators, **kwargs) - -class Email(EmailField): +class Email(Stripped, EmailField): def __init__(self, label="E-mail", validators=None, **kwargs): super().__init__(label, validators, **kwargs) @@ -72,7 +85,7 @@ class Email(EmailField): raise wtforms.ValidationError(str(e)) -class Grade(wtforms.StringField): +class Grade(String): """Pro validaci hledá ve formuláři form.school a podle ní rozlišuje SŠ a ZŠ """ default_description = "Pro základní školy je to číslo od 1 do 9, pro <var>k</var>-tý ročník <var>r</var>-leté střední školy má formát <var>k</var>/<var>r</var>." validate_grade = True @@ -104,7 +117,7 @@ class BirthYear(OptionalInt): raise wtforms.ValidationError(str(e)) -class Name(wtforms.StringField): +class Name(String): def pre_validate(field, form): # XXX: Tato kontrola úmyslně není striktní, aby prošla i jména jako 'de Beer' if field.data: @@ -124,7 +137,7 @@ class LastName(Name): super().__init__(label, validators, **kwargs) -class Place(wtforms.StringField): +class Place(String): def __init__(self, label="Místo", validators=None, **kwargs): super().__init__(label, validators, **kwargs) self.render_kw = {"placeholder": "Kód"} @@ -142,7 +155,7 @@ class Place(wtforms.StringField): field.place_error = "Zadané místo nenalezeno." def get_place(field) -> Optional[db.Place]: - """ Kešuje výsledek v field.place""" + """Kešuje výsledek v field.place""" if not field.place_loaded: field.place_loaded = True field.load_place() @@ -182,7 +195,11 @@ class School(Place): field.place_error = str(e) -class NewPassword(wtforms.PasswordField): +class Password(Stripped, wtforms.PasswordField): + pass + + +class NewPassword(Password): def __init__(self, label="Nové heslo", validators=None, **kwargs): super().__init__(label, validators, **kwargs) @@ -192,7 +209,7 @@ class NewPassword(wtforms.PasswordField): raise wtforms.ValidationError(mo.users.password_help) -class RepeatPassword(wtforms.PasswordField): +class RepeatPassword(Password): """Pro validaci hledá ve formuláři form.new_passwd a s ním porovnává.""" def __init__(self, label="Zopakujte heslo", validators=None, **kwargs): diff --git a/mo/web/org_contest.py b/mo/web/org_contest.py index 5459ba280cd6eab754599ae8c6087cce92a9d576..d9269c633c23fef9d13fa38fbb9324df2732d8ad 100644 --- a/mo/web/org_contest.py +++ b/mo/web/org_contest.py @@ -670,7 +670,7 @@ class SubmitForm(FlaskForm): class SetFinalForm(FlaskForm): - type = wtforms.StringField() + type = mo_fields.String() paper_id = wtforms.IntegerField() submit_final = wtforms.SubmitField("Prohlásit za finální") diff --git a/mo/web/org_place.py b/mo/web/org_place.py index 1d6b0c1e47db58b29db540656893524f024df4c6..7ffbc4a3a6d8a2d1dde7af974d80bf0f3def8e44 100644 --- a/mo/web/org_place.py +++ b/mo/web/org_place.py @@ -50,30 +50,30 @@ def org_place(id: int): class PlaceEditForm(FlaskForm): - name = wtforms.StringField( + name = mo_fields.String( 'Název', render_kw={'autofocus': True}, validators=[validators.DataRequired()] ) - code = wtforms.StringField( + code = mo_fields.String( 'Kód', filters=[lambda x: x or None], # may be NULL in db description="Na místo se lze odkazovat kódem z písmen a číslic." ) type = wtforms.SelectField( 'Typ', choices=db.PlaceType.choices(), coerce=db.PlaceType.coerce ) - nuts = wtforms.StringField( + nuts = mo_fields.String( 'NUTS', filters=[lambda x: x or None], # may be NULL in db description="Pro okresy a výše" ) - note = wtforms.StringField('Poznámka') + note = mo_fields.String('Poznámka') submit = wtforms.SubmitField('Uložit') class PlaceSchoolEditForm(PlaceEditForm): - red_izo = wtforms.StringField('RED_IZO') - ico = wtforms.StringField('IČO') - official_name = wtforms.StringField('Oficiální název') - address = wtforms.StringField('Adresa') + red_izo = mo_fields.String('RED_IZO') + ico = mo_fields.String('IČO') + official_name = mo_fields.String('Oficiální název') + address = mo_fields.String('Adresa') is_zs = wtforms.BooleanField('ZŠ') is_ss = wtforms.BooleanField('SŠ') submit = wtforms.SubmitField('Uložit') diff --git a/mo/web/org_round.py b/mo/web/org_round.py index 26b1abcbe06744dc751d659405da991b8aa4835e..3aa42c34ec730a2f5356f9725cb3c6dd3babea80 100644 --- a/mo/web/org_round.py +++ b/mo/web/org_round.py @@ -279,11 +279,11 @@ def org_round(round_id: int, hier_id: Optional[int] = None): class TaskEditForm(FlaskForm): - code = wtforms.StringField('Kód úlohy', validators=[ + code = mo_fields.String('Kód úlohy', validators=[ validators.Required(), validators.Regexp(r'^[A-Za-z0-9-]+$', message="Kód úlohy smí obsahovat jen nediakritická písmena, čísla a znak -"), ], render_kw={'autofocus': True}) - name = wtforms.StringField('Název úlohy') + name = mo_fields.String('Název úlohy') type = wtforms.SelectField('Typ úlohy', choices=db.TaskType.choices(), coerce=db.TaskType.coerce) max_points = mo_fields.Points( 'Maximum bodů', validators=[validators.Optional(), validators.NumberRange(min=0)], @@ -368,8 +368,8 @@ def org_round_task_edit(round_id: int, task_id: int): class RoundEditForm(FlaskForm): _for_round: Optional[db.Round] = None - name = wtforms.StringField("Název", render_kw={'autofocus': True}) - code = wtforms.StringField("Kód", + name = mo_fields.String("Název", render_kw={'autofocus': True}) + code = mo_fields.String("Kód", description="Kód kola používaný v kódech úloh ('1', 'S' apod.). Není-li vyplněn, použije se pořadí kola v kategorii.", ) state = wtforms.SelectField( @@ -396,7 +396,7 @@ class RoundEditForm(FlaskForm): description="Ovlivňuje možnost zadávání nových bodů, již uložené body nezmění" ) enroll_mode = wtforms.SelectField("Režim přihlašování", choices=db.RoundEnrollMode.choices(), coerce=db.RoundEnrollMode.coerce) - enroll_advert = wtforms.StringField("Popis v přihlášce") + enroll_advert = mo_fields.String("Popis v přihlášce") has_messages = wtforms.BooleanField("Zprávičky pro účastníky (aktivuje možnost vytvářet novinky zobrazované účastníkům)") submit = wtforms.SubmitField('Uložit') @@ -546,7 +546,7 @@ def org_edit_statement(round_id: int): class MessageAddForm(FlaskForm): - title = wtforms.StringField('Nadpis', validators=[validators.Required()]) + title = mo_fields.String('Nadpis', validators=[validators.Required()]) markdown = wtforms.TextAreaField( 'Text zprávičky', description='Zprávičky lze formátovat pomocí Markdownu', validators=[validators.Required()], diff --git a/mo/web/org_users.py b/mo/web/org_users.py index 6d276fa9fd5e89ab836c94c63a792a6c4bf97994..956362a84b98dfcba3d77a18eb6b213a10973325 100644 --- a/mo/web/org_users.py +++ b/mo/web/org_users.py @@ -27,8 +27,8 @@ from mo.web.util import PagerForm class UsersFilterForm(PagerForm): # user - search_name = wtforms.TextField("Jméno/příjmení", render_kw={'autofocus': True}) - search_email = wtforms.TextField("E-mail") + search_name = mo_fields.String("Jméno/příjmení", render_kw={'autofocus': True}) + search_email = mo_fields.String("E-mail") # participants year = mo_fields.OptionalInt("Ročník") @@ -132,15 +132,15 @@ def org_users(): class OrgsFilterForm(PagerForm): # user - search_name = wtforms.TextField("Jméno/příjmení", render_kw={'autofocus': True}) - search_email = wtforms.TextField("E-mail") + search_name = mo_fields.String("Jméno/příjmení", render_kw={'autofocus': True}) + search_email = mo_fields.String("E-mail") search_role = wtforms.SelectMultipleField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, validators=[validators.Optional()]) search_right_for_place = mo_fields.Place('Právo pro oblast', validators=[validators.Optional()]) search_in_place = mo_fields.Place('V oblasti', validators=[validators.Optional()]) search_place_level = wtforms.SelectMultipleField("Úroveň oblasti", choices=[(i.level, i.name) for i in db.place_levels], validators=[validators.Optional()], coerce=int) search_year = mo_fields.IntList('Ročník', validators=[validators.Optional()]) - search_category = wtforms.StringField("Kategorie", validators=[validators.Optional()]) + search_category = mo_fields.String("Kategorie", validators=[validators.Optional()]) search_seq = mo_fields.IntList("Kolo", validators=[validators.Optional()]) submit = wtforms.SubmitField("Filtrovat") @@ -238,7 +238,7 @@ class FormAddRole(FlaskForm): role = wtforms.SelectField('Role', choices=db.RoleType.choices(), coerce=db.RoleType.coerce, render_kw={'autofocus': True}) place = mo_fields.Place() year = wtforms.IntegerField('Ročník', validators=[validators.Optional()]) - category = wtforms.StringField("Kategorie", validators=[validators.Length(max=2)], filters=[lambda x: x or None]) + category = mo_fields.String("Kategorie", validators=[validators.Length(max=2)], filters=[lambda x: x or None]) seq = wtforms.IntegerField("Kolo", render_kw={"placeholder": "Pořadí kola v kategorii"}, validators=[validators.Optional()]) submit = wtforms.SubmitField('Přidat roli') @@ -612,8 +612,8 @@ def org_user_participant_edit(user_id: int, year: int): class GlobalOrgsImportForm(ImportForm): allow_change_user_to_org = wtforms.BooleanField("Povolit převádění účastníků na organizátory") default_place = mo_fields.Place("Výchozí oblast (není-li v souboru uvedena)") - default_cat = wtforms.StringField("Výchozí kategorie (není-li v souboru uvedena)") - default_code = wtforms.StringField("Výchozí kód kola (není-li v souboru uveden)") + default_cat = mo_fields.String("Výchozí kategorie (není-li v souboru uvedena)") + default_code = mo_fields.String("Výchozí kód kola (není-li v souboru uveden)") only_this_year = wtforms.BooleanField("Omezit práva na aktuální ročník", default=True)