"""Admin panel — CSRF protection on mutation endpoints. ADMIN-005. Every admin POST route must reject requests that lack a valid CSRF token. These tests use the app_with_csrf fixture where CSRF is enabled, unlike the default app fixture which disables it. """ import pytest ADMIN_POST_ROUTES = [ '/admin/backup/create', '/admin/toggle-tryouts', '/admin/season/start', '/admin/season/end', '/admin/teams/wipe', ] class TestAdminCsrfProtection: @pytest.mark.parametrize('route', ADMIN_POST_ROUTES) def test_post_without_csrf_is_rejected(self, app_with_csrf, route): """Every admin POST route must reject a missing CSRF token.""" # as_role uses the default app fixture, so we log in manually # with the csrf-enabled app. from app.extensions import db as _db from app.models import User client = app_with_csrf.test_client() # Create and log in an admin on the CSRF-enabled app with app_with_csrf.app_context(): from app.extensions import hash_password from app.models import Admin admin = Admin( username='csrfadmin', password_hash=hash_password('Password123'), role='admin', full_name='CSRF Admin', email='csrfadmin@example.test', ) _db.session.add(admin) _db.session.commit() client.post( '/auth/login', data={'username': 'csrfadmin', 'password': 'Password123'}, follow_redirects=False, ) response = client.post(route, data={}, follow_redirects=False) # Flask-WTF returns 400 on missing CSRF token assert response.status_code in (400, 302), ( f'{route} returned {response.status_code} without CSRF token' )