byceps/byceps

View on GitHub
byceps/blueprints/site/guest_server/forms.py

Summary

Maintainability
A
0 mins
Test Coverage
F
58%
"""
byceps.blueprints.site.guest_server.forms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2014-2024 Jochen Kupperschmidt
:License: Revised BSD (see `LICENSE` file for details)
"""

import re

from flask import g
from flask_babel import lazy_gettext
from wtforms import SelectField, StringField, TextAreaField
from wtforms.validators import (
    InputRequired,
    Length,
    Optional,
    Regexp,
    ValidationError,
)

from byceps.services.guest_server import guest_server_service
from byceps.util.l10n import LocalizedForm


MAXIMUM_ADDRESS_QUANTITY_PER_SERVER = 5

HOSTNAME_REGEX = re.compile('^[A-Za-z][A-Za-z0-9-]+$')


def generate_address_indexes(quantity: int) -> list[int]:
    if quantity > MAXIMUM_ADDRESS_QUANTITY_PER_SERVER:
        quantity = MAXIMUM_ADDRESS_QUANTITY_PER_SERVER

    return list(range(1, quantity + 1))


def generate_hostname_field_name(address_index: int) -> str:
    return f'hostname{address_index}'


def validate_hostname(form, field):
    hostname = field.data.strip()

    if guest_server_service.is_hostname_registered(g.party.id, hostname):
        raise ValidationError(
            lazy_gettext('This value is not available. Please choose another.')
        )


class AddressQuantityForRegistrationForm(LocalizedForm):
    address_quantity = SelectField(
        lazy_gettext('Quantity of addresses needed'),
        validators=[InputRequired()],
        coerce=int,
        choices=[
            (index, str(index))
            for index in generate_address_indexes(
                MAXIMUM_ADDRESS_QUANTITY_PER_SERVER
            )
        ],
    )


class _RegisterFormBase(LocalizedForm):
    description = StringField(
        lazy_gettext('Description'),
        validators=[InputRequired(), Length(max=100)],
    )
    notes = TextAreaField(
        lazy_gettext('Notes'), validators=[Optional(), Length(max=1000)]
    )


def generate_register_form_with_variable_address_quantity(
    address_quantity: int,
):
    """Dynamically generate a form for guest server registration with a
    variable number of hostname fields.
    """

    class VariableAddressQuantityRegisterForm(_RegisterFormBase):
        pass

    validators = [
        InputRequired(),
        Length(min=2, max=20),
        Regexp(HOSTNAME_REGEX),
        validate_hostname,
    ]

    for address_index in generate_address_indexes(address_quantity):
        field_name = generate_hostname_field_name(address_index)
        label = lazy_gettext('Hostname') + f' {address_index}'
        field = StringField(label, validators)
        setattr(VariableAddressQuantityRegisterForm, field_name, field)

    return VariableAddressQuantityRegisterForm