CoolFace
Apppublic

SRNI-2005/ctf

sourceHugging Faceupdated 6mo agoView on Hugging Face
0likes
users.py236 linesDownload Raw Back to forms
1from flask_babel import lazy_gettext as _l2from wtforms import BooleanField, PasswordField, SelectField, StringField3from wtforms.fields.html5 import EmailField4from wtforms.validators import InputRequired5 6from CTFd.constants.config import Configs7from CTFd.constants.languages import SELECT_LANGUAGE_LIST8from CTFd.forms import BaseForm9from CTFd.forms.fields import SubmitField10from CTFd.models import Brackets, UserFieldEntries, UserFields11from CTFd.utils.countries import SELECT_COUNTRIES_LIST12 13 14def build_custom_user_fields(15    form_cls,16    include_entries=False,17    fields_kwargs=None,18    field_entries_kwargs=None,19    blacklisted_items=(),20):21    """22    Function used to reinject values back into forms for accessing by themes23    """24    if fields_kwargs is None:25        fields_kwargs = {}26    if field_entries_kwargs is None:27        field_entries_kwargs = {}28 29    fields = []30    new_fields = UserFields.query.filter_by(**fields_kwargs).all()31    user_fields = {}32 33    # Only include preexisting values if asked34    if include_entries is True:35        for f in UserFieldEntries.query.filter_by(**field_entries_kwargs).all():36            user_fields[f.field_id] = f.value37 38    for field in new_fields:39        if field.name.lower() in blacklisted_items:40            continue41 42        form_field = getattr(form_cls, f"fields[{field.id}]")43 44        # Add the field_type to the field so we know how to render it45        form_field.field_type = field.field_type46 47        # Only include preexisting values if asked48        if include_entries is True:49            initial = user_fields.get(field.id, "")50            form_field.data = initial51            if form_field.render_kw:52                form_field.render_kw["data-initial"] = initial53            else:54                form_field.render_kw = {"data-initial": initial}55 56        fields.append(form_field)57    return fields58 59 60def attach_custom_user_fields(form_cls, **kwargs):61    """62    Function used to attach form fields to wtforms.63    Not really a great solution but is approved by wtforms.64 65    https://wtforms.readthedocs.io/en/2.3.x/specific_problems/#dynamic-form-composition66    """67    new_fields = UserFields.query.filter_by(**kwargs).all()68    for field in new_fields:69        validators = []70        if field.required:71            validators.append(InputRequired())72 73        if field.field_type == "text":74            input_field = StringField(75                field.name, description=field.description, validators=validators76            )77        elif field.field_type == "boolean":78            input_field = BooleanField(79                field.name, description=field.description, validators=validators80            )81 82        setattr(form_cls, f"fields[{field.id}]", input_field)83 84 85def build_registration_code_field(form_cls):86    """87    Build the appropriate field so we can render it via the extra property.88    Add field_type so Jinja knows how to render it.89    """90    if Configs.registration_code:91        field = getattr(form_cls, "registration_code", None)  # noqa B00992        field.field_type = "text"93        return [field]94    else:95        return []96 97 98def attach_registration_code_field(form_cls):99    """100    If we have a registration code required, we attach it to the form similar101    to attach_custom_user_fields102    """103    if Configs.registration_code:104        setattr(  # noqa B010105            form_cls,106            "registration_code",107            StringField(108                "Registration Code",109                description="Registration code required to create account",110                validators=[InputRequired()],111            ),112        )113 114 115def build_user_bracket_field(form_cls, value=None):116    field = getattr(form_cls, "bracket_id", None)  # noqa B009117    if field:118        field.field_type = "select"119        field.process_data(value)120        return [field]121    else:122        return []123 124 125def attach_user_bracket_field(form_cls):126    brackets = Brackets.query.filter_by(type="users").all()127    if brackets:128        choices = [("", "")] + [129            (bracket.id, f"{bracket.name} - {bracket.description}")130            for bracket in brackets131        ]132        select_field = SelectField(133            _l("Bracket"),134            description=_l("Competition bracket for your user"),135            choices=choices,136            validators=[InputRequired()],137        )138        setattr(form_cls, "bracket_id", select_field)  # noqa B010139 140 141class UserSearchForm(BaseForm):142    field = SelectField(143        "Search Field",144        choices=[145            ("name", "Name"),146            ("id", "ID"),147            ("email", "Email"),148            ("affiliation", "Affiliation"),149            ("website", "Website"),150            ("ip", "IP Address"),151        ],152        default="name",153        validators=[InputRequired()],154    )155    q = StringField("Parameter", validators=[InputRequired()])156    submit = SubmitField("Search")157 158 159class PublicUserSearchForm(BaseForm):160    field = SelectField(161        _l("Search Field"),162        choices=[163            ("name", _l("Name")),164            ("affiliation", _l("Affiliation")),165            ("website", _l("Website")),166        ],167        default="name",168        validators=[InputRequired()],169    )170    q = StringField(171        _l("Parameter"),172        description=_l("Search for matching users"),173        validators=[InputRequired()],174    )175    submit = SubmitField(_l("Search"))176 177 178class UserBaseForm(BaseForm):179    name = StringField("User Name", validators=[InputRequired()])180    email = EmailField("Email", validators=[InputRequired()])181    language = SelectField(_l("Language"), choices=SELECT_LANGUAGE_LIST)182    password = PasswordField("Password")183    website = StringField("Website")184    affiliation = StringField("Affiliation")185    country = SelectField("Country", choices=SELECT_COUNTRIES_LIST)186    type = SelectField("Type", choices=[("user", "User"), ("admin", "Admin")])187    verified = BooleanField("Verified")188    hidden = BooleanField("Hidden")189    banned = BooleanField("Banned")190    change_password = BooleanField("Require password change on next login")191    submit = SubmitField("Submit")192 193 194def UserEditForm(*args, **kwargs):195    class _UserEditForm(UserBaseForm):196        pass197 198        @property199        def extra(self):200            return build_custom_user_fields(201                self,202                include_entries=True,203                fields_kwargs=None,204                field_entries_kwargs={"user_id": self.obj.id},205            ) + build_user_bracket_field(self, value=self.obj.bracket_id)206 207        def __init__(self, *args, **kwargs):208            """209            Custom init to persist the obj parameter to the rest of the form210            """211            super().__init__(*args, **kwargs)212            obj = kwargs.get("obj")213            if obj:214                self.obj = obj215 216    attach_custom_user_fields(_UserEditForm)217    attach_user_bracket_field(_UserEditForm)218 219    return _UserEditForm(*args, **kwargs)220 221 222def UserCreateForm(*args, **kwargs):223    class _UserCreateForm(UserBaseForm):224        notify = BooleanField("Email account credentials to user", default=True)225 226        @property227        def extra(self):228            return build_custom_user_fields(229                self, include_entries=False230            ) + build_user_bracket_field(self)231 232    attach_custom_user_fields(_UserCreateForm)233    attach_user_bracket_field(_UserCreateForm)234 235    return _UserCreateForm(*args, **kwargs)236