fix(audit): fermer les frontieres restantes
This commit is contained in:
+140
-1
@@ -23,7 +23,7 @@ from marshmallow import (
|
||||
validates_schema,
|
||||
)
|
||||
|
||||
from app.models import ESPORT_GAMES, USER_TYPES
|
||||
from app.models import ESPORT_GAMES, GAME_PLATFORMS, USER_TYPES
|
||||
|
||||
# =============================================================================
|
||||
# Custom Validators
|
||||
@@ -276,6 +276,36 @@ class RegisterSchema(StripMixin):
|
||||
raise ValidationError(_l('Passwords do not match.'), field_name='confirm_password')
|
||||
|
||||
|
||||
class GamertagSchema(StripMixin):
|
||||
"""One dynamic per-game identity submitted beside an account form."""
|
||||
|
||||
game = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(ESPORT_GAMES, error=_l('Unknown game.')),
|
||||
)
|
||||
gamertag = fields.String(
|
||||
required=True,
|
||||
validate=validate.Length(
|
||||
min=1,
|
||||
max=120,
|
||||
error=_l('Gamertag must be between 1 and 120 characters.'),
|
||||
),
|
||||
)
|
||||
platform = fields.String(
|
||||
allow_none=True,
|
||||
load_default=None,
|
||||
validate=validate.Length(max=30, error=_l('Platform must be 30 characters or less.')),
|
||||
)
|
||||
|
||||
@validates_schema
|
||||
def validate_platform_for_game(self, data, **kwargs):
|
||||
"""A forged platform must belong to the selected game's list."""
|
||||
platform = data.get('platform')
|
||||
allowed = GAME_PLATFORMS.get(data.get('game'), ())
|
||||
if platform and platform not in allowed:
|
||||
raise ValidationError(_l('Unknown platform for this game.'), field_name='platform')
|
||||
|
||||
|
||||
class CreateUserSchema(StripMixin):
|
||||
"""Validate president-created user form input.
|
||||
|
||||
@@ -517,6 +547,115 @@ class TeamPlayerSchema(PlayerSelectionSchema):
|
||||
)
|
||||
|
||||
|
||||
TRYOUT_STATUSES = ('upcoming', 'in_progress', 'completed')
|
||||
TRYOUT_REGISTRATION_STATUSES = ('registered', 'attended', 'no_show')
|
||||
|
||||
|
||||
class TryoutStatusSchema(StripMixin):
|
||||
"""A state transition requested from the tryout detail page."""
|
||||
|
||||
status = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(TRYOUT_STATUSES, error=_l('Unknown tryout status.')),
|
||||
)
|
||||
|
||||
|
||||
class TryoutRegistrationStatusSchema(StripMixin):
|
||||
"""Attendance state for one tryout registration."""
|
||||
|
||||
status = fields.String(
|
||||
required=True,
|
||||
validate=validate.OneOf(
|
||||
TRYOUT_REGISTRATION_STATUSES,
|
||||
error=_l('Unknown registration status.'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TryoutTeamSchema(StripMixin):
|
||||
"""A tryout-local team created from its compact inline form."""
|
||||
|
||||
team_name = fields.String(
|
||||
required=True,
|
||||
validate=validate.Length(
|
||||
min=1,
|
||||
max=100,
|
||||
error=_l('Team name must be between 1 and 100 characters.'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class TryoutTeamMemberSchema(StripMixin):
|
||||
"""A registered player and their optional position on a tryout team."""
|
||||
|
||||
player_id = fields.Integer(
|
||||
required=True,
|
||||
validate=validate.Range(min=1),
|
||||
error_messages={
|
||||
'invalid': _l('Invalid player selection.'),
|
||||
'required': _l('Player must be selected.'),
|
||||
},
|
||||
)
|
||||
position = fields.String(
|
||||
load_default='',
|
||||
validate=validate.Length(
|
||||
max=50,
|
||||
error=_l('Position must be 50 characters or less.'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class NoteContentSchema(StripMixin):
|
||||
"""Bounded text stored as a team or personal coaching note."""
|
||||
|
||||
content = fields.String(
|
||||
required=True,
|
||||
validate=validate.Length(
|
||||
min=1,
|
||||
max=5000,
|
||||
error=_l('Note content must be between 1 and 5000 characters.'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class PersonalNoteSchema(NoteContentSchema):
|
||||
"""A personal note with at most one optional, typed context."""
|
||||
|
||||
player_id = fields.Integer(
|
||||
required=True,
|
||||
validate=validate.Range(min=1),
|
||||
error_messages={
|
||||
'invalid': _l('Invalid player selection.'),
|
||||
'required': _l('Player must be selected.'),
|
||||
},
|
||||
)
|
||||
match_id = fields.Integer(allow_none=True, load_default=None, validate=validate.Range(min=1))
|
||||
tryout_id = fields.Integer(allow_none=True, load_default=None, validate=validate.Range(min=1))
|
||||
team_id = fields.Integer(allow_none=True, load_default=None, validate=validate.Range(min=1))
|
||||
|
||||
@validates_schema
|
||||
def validate_one_context(self, data, **kwargs):
|
||||
"""A note cannot claim several unrelated contexts at once."""
|
||||
contexts = [data.get(name) for name in ('match_id', 'tryout_id', 'team_id')]
|
||||
if sum(value is not None for value in contexts) > 1:
|
||||
raise ValidationError(
|
||||
_l('Select at most one note context.'),
|
||||
field_name='context',
|
||||
)
|
||||
|
||||
|
||||
class OneOnOneRejectionSchema(StripMixin):
|
||||
"""Optional explanation sent to a player when a request is rejected."""
|
||||
|
||||
rejection_reason = fields.String(
|
||||
load_default='',
|
||||
validate=validate.Length(
|
||||
max=2000,
|
||||
error=_l('Rejection reason must be 2000 characters or less.'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class OneOnOneRequestSchema(StripMixin):
|
||||
"""A player asking their coach for a session (MNT-12).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user