"""Helpers used by more than one route module in this package. Nothing here touches the blueprint: these are plain functions, so a test can call them with a request context and nothing else. """ from flask import request from flask_babel import gettext as _ from app.extensions import db # Re-exported: these two moved to app/forms.py once the match and tryout # routes needed them as well (ARCH-005). Importing them from here still # works, so the thirty call sites in this package did not have to move. from app.forms import flash_validation_errors, form_payload # noqa: F401 from app.models import GAME_PLATFORMS, Admin, Coach, Manager, Player, Scout, UserGamertag ALLOWED_CONTRACT_EXTENSIONS = {'pdf'} ALLOWED_SIGNED_EXTENSIONS = {'pdf'} #: Every PDF starts with this. Checking the name alone accepted a file #: called anything.pdf holding anything at all. PDF_SIGNATURE = b'%PDF-' #: USER_TYPE → model class, for create_user. USER_CLASS_MAP = { 'admin': Admin, 'manager': Manager, 'coach': Coach, 'player': Player, 'scout': Scout, } def pdf_upload_error(file, allowed_extensions): """Why this upload is not an acceptable PDF, or None if it is. upload_signed_contract checked nothing beyond a non-empty filename — ALLOWED_SIGNED_EXTENSIONS was declared and never read — so a player could put an arbitrary file on the server under a name the application later hands back for download (SEC-021). Args: file: The uploaded FileStorage, or None. allowed_extensions: Extensions to accept, lowercase and without dot. Returns: str | None: A message to flash, or None when the file is acceptable. """ if file is None or not file.filename: return _('No file selected.') stem, dot, extension = file.filename.rpartition('.') if not (stem and dot) or extension.lower() not in allowed_extensions: return _('Only PDF files are allowed for contracts.') head = file.stream.read(len(PDF_SIGNATURE)) file.stream.seek(0) if head != PDF_SIGNATURE: return _('That file is not a PDF, whatever its name says.') return None def update_user_gamertags(user, selected_games): """Update gamertags for a user based on form input.""" existing_gamertags = {gt.game: gt for gt in user.gamertags} for game in selected_games: gamertag = request.form.get(f'gamertag_{game}', '').strip() platform = ( request.form.get(f'platform_{game}', '').strip() if GAME_PLATFORMS.get(game) else None ) existing = existing_gamertags.get(game) if gamertag: if existing: existing.gamertag = gamertag existing.platform = platform else: gt = UserGamertag(user_id=user.id, game=game, gamertag=gamertag, platform=platform) db.session.add(gt) elif existing: db.session.delete(existing) for game in existing_gamertags: if game not in selected_games: db.session.delete(existing_gamertags[game])