Add csrf extempts

parent 855f0860
...@@ -5,13 +5,14 @@ from flask_login import login_user, logout_user, login_required, current_user ...@@ -5,13 +5,14 @@ from flask_login import login_user, logout_user, login_required, current_user
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity, get_jwt from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity, get_jwt
from werkzeug.security import check_password_hash from werkzeug.security import check_password_hash
from app.auth import bp from app.auth import bp
from app import db from app import db, csrf
from app.auth.forms import LoginForm, RegistrationForm from app.auth.forms import LoginForm, RegistrationForm
from app.utils.security import validate_password_strength, generate_secure_token, rate_limit_check from app.utils.security import validate_password_strength, generate_secure_token, rate_limit_check
from app.utils.logging import log_security_event from app.utils.logging import log_security_event
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@csrf.exempt
@bp.route('/login', methods=['GET', 'POST']) @bp.route('/login', methods=['GET', 'POST'])
def login(): def login():
"""User login endpoint""" """User login endpoint"""
...@@ -67,6 +68,7 @@ def login(): ...@@ -67,6 +68,7 @@ def login():
return render_template('auth/login.html', form=form) return render_template('auth/login.html', form=form)
@csrf.exempt
@bp.route('/logout') @bp.route('/logout')
@login_required @login_required
def logout(): def logout():
...@@ -87,6 +89,7 @@ def logout(): ...@@ -87,6 +89,7 @@ def logout():
flash('You have been logged out successfully.', 'info') flash('You have been logged out successfully.', 'info')
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))
@csrf.exempt
@bp.route('/register', methods=['GET', 'POST']) @bp.route('/register', methods=['GET', 'POST'])
def register(): def register():
"""User registration endpoint (disabled by default, configurable by admin)""" """User registration endpoint (disabled by default, configurable by admin)"""
...@@ -143,6 +146,7 @@ def register(): ...@@ -143,6 +146,7 @@ def register():
return render_template('auth/register.html', form=form) return render_template('auth/register.html', form=form)
@csrf.exempt
@bp.route('/api/login', methods=['POST']) @bp.route('/api/login', methods=['POST'])
def api_login(): def api_login():
"""API login endpoint for JWT authentication""" """API login endpoint for JWT authentication"""
...@@ -199,6 +203,7 @@ def api_login(): ...@@ -199,6 +203,7 @@ def api_login():
logger.error(f"API login error: {str(e)}") logger.error(f"API login error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/logout', methods=['POST']) @bp.route('/api/logout', methods=['POST'])
@jwt_required() @jwt_required()
def api_logout(): def api_logout():
...@@ -228,6 +233,7 @@ def api_logout(): ...@@ -228,6 +233,7 @@ def api_logout():
logger.error(f"API logout error: {str(e)}") logger.error(f"API logout error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/refresh', methods=['POST']) @bp.route('/api/refresh', methods=['POST'])
@jwt_required() @jwt_required()
def api_refresh(): def api_refresh():
...@@ -255,6 +261,7 @@ def api_refresh(): ...@@ -255,6 +261,7 @@ def api_refresh():
logger.error(f"Token refresh error: {str(e)}") logger.error(f"Token refresh error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/profile', methods=['GET']) @bp.route('/api/profile', methods=['GET'])
@jwt_required() @jwt_required()
def api_profile(): def api_profile():
...@@ -273,6 +280,7 @@ def api_profile(): ...@@ -273,6 +280,7 @@ def api_profile():
logger.error(f"Profile fetch error: {str(e)}") logger.error(f"Profile fetch error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/change-password', methods=['POST']) @bp.route('/api/change-password', methods=['POST'])
@jwt_required() @jwt_required()
def api_change_password(): def api_change_password():
...@@ -313,6 +321,7 @@ def api_change_password(): ...@@ -313,6 +321,7 @@ def api_change_password():
logger.error(f"Password change error: {str(e)}") logger.error(f"Password change error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/sessions', methods=['GET']) @bp.route('/api/sessions', methods=['GET'])
@jwt_required() @jwt_required()
def api_user_sessions(): def api_user_sessions():
...@@ -333,6 +342,7 @@ def api_user_sessions(): ...@@ -333,6 +342,7 @@ def api_user_sessions():
logger.error(f"Sessions fetch error: {str(e)}") logger.error(f"Sessions fetch error: {str(e)}")
return jsonify({'error': 'Internal server error'}), 500 return jsonify({'error': 'Internal server error'}), 500
@csrf.exempt
@bp.route('/api/sessions/<session_id>', methods=['DELETE']) @bp.route('/api/sessions/<session_id>', methods=['DELETE'])
@jwt_required() @jwt_required()
def api_terminate_session(session_id): def api_terminate_session(session_id):
......
...@@ -4,13 +4,14 @@ from datetime import datetime ...@@ -4,13 +4,14 @@ from datetime import datetime
from flask import render_template, request, jsonify, redirect, url_for, flash, current_app from flask import render_template, request, jsonify, redirect, url_for, flash, current_app
from flask_login import login_required, current_user from flask_login import login_required, current_user
from app.main import bp from app.main import bp
from app import db from app import db, csrf
from app.upload.file_handler import get_file_upload_handler from app.upload.file_handler import get_file_upload_handler
from app.upload.fixture_parser import get_fixture_parser from app.upload.fixture_parser import get_fixture_parser
from app.utils.security import require_admin, require_active_user from app.utils.security import require_admin, require_active_user
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@csrf.exempt
@bp.route('/') @bp.route('/')
def index(): def index():
"""Home page""" """Home page"""
...@@ -40,6 +41,7 @@ def index(): ...@@ -40,6 +41,7 @@ def index():
return redirect(url_for('main.dashboard')) return redirect(url_for('main.dashboard'))
return render_template('main/index.html') return render_template('main/index.html')
@csrf.exempt
@bp.route('/dashboard') @bp.route('/dashboard')
@login_required @login_required
@require_active_user @require_active_user
...@@ -94,6 +96,7 @@ def dashboard(): ...@@ -94,6 +96,7 @@ def dashboard():
flash('Error loading dashboard', 'error') flash('Error loading dashboard', 'error')
return render_template('main/dashboard.html') return render_template('main/dashboard.html')
@csrf.exempt
@bp.route('/fixtures') @bp.route('/fixtures')
@login_required @login_required
@require_active_user @require_active_user
...@@ -181,6 +184,7 @@ def fixtures(): ...@@ -181,6 +184,7 @@ def fixtures():
return render_template('main/matches.html', fixtures=[], pagination=None) return render_template('main/matches.html', fixtures=[], pagination=None)
# Keep the old /matches route for backward compatibility # Keep the old /matches route for backward compatibility
@csrf.exempt
@bp.route('/matches') @bp.route('/matches')
@login_required @login_required
@require_active_user @require_active_user
...@@ -188,6 +192,7 @@ def matches(): ...@@ -188,6 +192,7 @@ def matches():
"""Redirect to fixtures for backward compatibility""" """Redirect to fixtures for backward compatibility"""
return redirect(url_for('main.fixtures')) return redirect(url_for('main.fixtures'))
@csrf.exempt
@bp.route('/fixture/<fixture_id>') @bp.route('/fixture/<fixture_id>')
@login_required @login_required
@require_active_user @require_active_user
...@@ -230,6 +235,7 @@ def fixture_detail(fixture_id): ...@@ -230,6 +235,7 @@ def fixture_detail(fixture_id):
flash('Error loading fixture details', 'error') flash('Error loading fixture details', 'error')
return redirect(url_for('main.matches')) return redirect(url_for('main.matches'))
@csrf.exempt
@bp.route('/fixture/<fixture_id>/delete', methods=['POST']) @bp.route('/fixture/<fixture_id>/delete', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -290,6 +296,7 @@ def delete_fixture(fixture_id): ...@@ -290,6 +296,7 @@ def delete_fixture(fixture_id):
flash('Error deleting fixture', 'error') flash('Error deleting fixture', 'error')
return redirect(url_for('main.matches')) return redirect(url_for('main.matches'))
@csrf.exempt
@bp.route('/match/<int:id>') @bp.route('/match/<int:id>')
@login_required @login_required
@require_active_user @require_active_user
...@@ -318,6 +325,7 @@ def match_detail(id): ...@@ -318,6 +325,7 @@ def match_detail(id):
flash('Error loading match details', 'error') flash('Error loading match details', 'error')
return redirect(url_for('main.fixture_detail', fixture_id=request.args.get('fixture_id', ''))) return redirect(url_for('main.fixture_detail', fixture_id=request.args.get('fixture_id', '')))
@csrf.exempt
@bp.route('/match/<int:match_id>/outcomes', methods=['POST']) @bp.route('/match/<int:match_id>/outcomes', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -386,6 +394,7 @@ def update_match_outcomes(match_id): ...@@ -386,6 +394,7 @@ def update_match_outcomes(match_id):
logger.error(f"Update match outcomes error: {str(e)}") logger.error(f"Update match outcomes error: {str(e)}")
return jsonify({'error': 'Failed to update outcomes'}), 500 return jsonify({'error': 'Failed to update outcomes'}), 500
@csrf.exempt
@bp.route('/match/<int:match_id>/outcomes/<int:outcome_id>', methods=['DELETE']) @bp.route('/match/<int:match_id>/outcomes/<int:outcome_id>', methods=['DELETE'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -424,6 +433,7 @@ def delete_match_outcome(match_id, outcome_id): ...@@ -424,6 +433,7 @@ def delete_match_outcome(match_id, outcome_id):
logger.error(f"Delete match outcome error: {str(e)}") logger.error(f"Delete match outcome error: {str(e)}")
return jsonify({'error': 'Failed to delete outcome'}), 500 return jsonify({'error': 'Failed to delete outcome'}), 500
@csrf.exempt
@bp.route('/uploads') @bp.route('/uploads')
@login_required @login_required
@require_active_user @require_active_user
...@@ -467,6 +477,7 @@ def uploads(): ...@@ -467,6 +477,7 @@ def uploads():
flash('Error loading uploads', 'error') flash('Error loading uploads', 'error')
return render_template('main/uploads.html', uploads=[], pagination=None) return render_template('main/uploads.html', uploads=[], pagination=None)
@csrf.exempt
@bp.route('/statistics') @bp.route('/statistics')
@login_required @login_required
@require_active_user @require_active_user
...@@ -511,6 +522,7 @@ def statistics(): ...@@ -511,6 +522,7 @@ def statistics():
flash('Error loading statistics', 'error') flash('Error loading statistics', 'error')
return render_template('main/statistics.html') return render_template('main/statistics.html')
@csrf.exempt
@bp.route('/admin') @bp.route('/admin')
@login_required @login_required
@require_admin @require_admin
...@@ -553,6 +565,7 @@ def admin_panel(): ...@@ -553,6 +565,7 @@ def admin_panel():
flash('Error loading admin panel', 'error') flash('Error loading admin panel', 'error')
return render_template('main/admin.html') return render_template('main/admin.html')
@csrf.exempt
@bp.route('/admin/users') @bp.route('/admin/users')
@login_required @login_required
@require_admin @require_admin
...@@ -603,6 +616,7 @@ def admin_users(): ...@@ -603,6 +616,7 @@ def admin_users():
flash('Error loading users', 'error') flash('Error loading users', 'error')
return render_template('main/admin_users.html', users=[], pagination=None) return render_template('main/admin_users.html', users=[], pagination=None)
@csrf.exempt
@bp.route('/admin/logs') @bp.route('/admin/logs')
@login_required @login_required
@require_admin @require_admin
...@@ -647,6 +661,7 @@ def admin_logs(): ...@@ -647,6 +661,7 @@ def admin_logs():
flash('Error loading logs', 'error') flash('Error loading logs', 'error')
return render_template('main/admin_logs.html', logs=[], pagination=None) return render_template('main/admin_logs.html', logs=[], pagination=None)
@csrf.exempt
@bp.route('/admin/users/<int:user_id>/edit', methods=['POST']) @bp.route('/admin/users/<int:user_id>/edit', methods=['POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -695,6 +710,7 @@ def admin_edit_user(user_id): ...@@ -695,6 +710,7 @@ def admin_edit_user(user_id):
logger.error(f"Admin edit user error: {str(e)}") logger.error(f"Admin edit user error: {str(e)}")
return jsonify({'error': 'Failed to update user'}), 500 return jsonify({'error': 'Failed to update user'}), 500
@csrf.exempt
@bp.route('/admin/users/<int:user_id>/delete', methods=['DELETE']) @bp.route('/admin/users/<int:user_id>/delete', methods=['DELETE'])
@login_required @login_required
@require_admin @require_admin
...@@ -719,6 +735,7 @@ def admin_delete_user(user_id): ...@@ -719,6 +735,7 @@ def admin_delete_user(user_id):
logger.error(f"Admin delete user error: {str(e)}") logger.error(f"Admin delete user error: {str(e)}")
return jsonify({'error': 'Failed to delete user'}), 500 return jsonify({'error': 'Failed to delete user'}), 500
@csrf.exempt
@bp.route('/admin/users/create', methods=['POST']) @bp.route('/admin/users/create', methods=['POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -768,6 +785,7 @@ def admin_create_user(): ...@@ -768,6 +785,7 @@ def admin_create_user():
logger.error(f"Admin create user error: {str(e)}") logger.error(f"Admin create user error: {str(e)}")
return jsonify({'error': 'Failed to create user'}), 500 return jsonify({'error': 'Failed to create user'}), 500
@csrf.exempt
@bp.route('/admin/users/<int:user_id>/reset-password', methods=['POST']) @bp.route('/admin/users/<int:user_id>/reset-password', methods=['POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -797,6 +815,7 @@ def admin_reset_user_password(user_id): ...@@ -797,6 +815,7 @@ def admin_reset_user_password(user_id):
logger.error(f"Admin reset password error: {str(e)}") logger.error(f"Admin reset password error: {str(e)}")
return jsonify({'error': 'Failed to reset password'}), 500 return jsonify({'error': 'Failed to reset password'}), 500
@csrf.exempt
@bp.route('/admin/settings') @bp.route('/admin/settings')
@login_required @login_required
@require_admin @require_admin
...@@ -819,6 +838,7 @@ def admin_system_settings(): ...@@ -819,6 +838,7 @@ def admin_system_settings():
flash('Error loading system settings', 'error') flash('Error loading system settings', 'error')
return render_template('main/admin_settings.html', settings={}) return render_template('main/admin_settings.html', settings={})
@csrf.exempt
@bp.route('/admin/settings/registration', methods=['GET', 'POST']) @bp.route('/admin/settings/registration', methods=['GET', 'POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -853,6 +873,7 @@ def admin_registration_settings(): ...@@ -853,6 +873,7 @@ def admin_registration_settings():
logger.error(f"Admin registration settings error: {str(e)}") logger.error(f"Admin registration settings error: {str(e)}")
return jsonify({'error': 'Failed to update registration settings'}), 500 return jsonify({'error': 'Failed to update registration settings'}), 500
@csrf.exempt
@bp.route('/admin/settings/<setting_key>', methods=['GET', 'POST']) @bp.route('/admin/settings/<setting_key>', methods=['GET', 'POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -909,6 +930,7 @@ def admin_setting_detail(setting_key): ...@@ -909,6 +930,7 @@ def admin_setting_detail(setting_key):
logger.error(f"Admin setting detail error: {str(e)}") logger.error(f"Admin setting detail error: {str(e)}")
return jsonify({'error': 'Failed to update setting'}), 500 return jsonify({'error': 'Failed to update setting'}), 500
@csrf.exempt
@bp.route('/admin/database/migrations') @bp.route('/admin/database/migrations')
@login_required @login_required
@require_admin @require_admin
...@@ -926,6 +948,7 @@ def admin_database_migrations(): ...@@ -926,6 +948,7 @@ def admin_database_migrations():
flash('Error loading migration status', 'error') flash('Error loading migration status', 'error')
return render_template('main/admin_migrations.html', migration_status={}) return render_template('main/admin_migrations.html', migration_status={})
@csrf.exempt
@bp.route('/admin/database/migrations/run', methods=['POST']) @bp.route('/admin/database/migrations/run', methods=['POST'])
@login_required @login_required
@require_admin @require_admin
...@@ -965,6 +988,7 @@ def admin_run_migrations(): ...@@ -965,6 +988,7 @@ def admin_run_migrations():
'message': f'Failed to run migrations: {str(e)}' 'message': f'Failed to run migrations: {str(e)}'
}), 500 }), 500
@csrf.exempt
@bp.route('/admin/database/migrations/status') @bp.route('/admin/database/migrations/status')
@login_required @login_required
@require_admin @require_admin
...@@ -986,6 +1010,7 @@ def admin_migration_status(): ...@@ -986,6 +1010,7 @@ def admin_migration_status():
'message': f'Failed to get migration status: {str(e)}' 'message': f'Failed to get migration status: {str(e)}'
}), 500 }), 500
@csrf.exempt
@bp.route('/health') @bp.route('/health')
def health_check(): def health_check():
"""Health check endpoint""" """Health check endpoint"""
...@@ -1016,6 +1041,7 @@ def health_check(): ...@@ -1016,6 +1041,7 @@ def health_check():
'timestamp': db.func.now() 'timestamp': db.func.now()
}), 503 }), 503
@csrf.exempt
@bp.route('/api/dashboard-data') @bp.route('/api/dashboard-data')
@login_required @login_required
@require_active_user @require_active_user
...@@ -1054,6 +1080,7 @@ def api_dashboard_data(): ...@@ -1054,6 +1080,7 @@ def api_dashboard_data():
# API Token Management Routes # API Token Management Routes
@csrf.exempt
@bp.route('/profile/tokens') @bp.route('/profile/tokens')
@login_required @login_required
@require_active_user @require_active_user
...@@ -1073,6 +1100,7 @@ def user_tokens(): ...@@ -1073,6 +1100,7 @@ def user_tokens():
flash('Error loading API tokens', 'error') flash('Error loading API tokens', 'error')
return render_template('main/user_tokens.html', tokens=[]) return render_template('main/user_tokens.html', tokens=[])
@csrf.exempt
@bp.route('/profile/tokens/create', methods=['POST']) @bp.route('/profile/tokens/create', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -1111,6 +1139,7 @@ def create_api_token(): ...@@ -1111,6 +1139,7 @@ def create_api_token():
logger.error(f"Create API token error: {str(e)}") logger.error(f"Create API token error: {str(e)}")
return jsonify({'error': 'Failed to create API token'}), 500 return jsonify({'error': 'Failed to create API token'}), 500
@csrf.exempt
@bp.route('/profile/tokens/<int:token_id>/delete', methods=['DELETE']) @bp.route('/profile/tokens/<int:token_id>/delete', methods=['DELETE'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -1139,6 +1168,7 @@ def delete_api_token(token_id): ...@@ -1139,6 +1168,7 @@ def delete_api_token(token_id):
logger.error(f"Delete API token error: {str(e)}") logger.error(f"Delete API token error: {str(e)}")
return jsonify({'error': 'Failed to delete API token'}), 500 return jsonify({'error': 'Failed to delete API token'}), 500
@csrf.exempt
@bp.route('/profile/tokens/<int:token_id>/revoke', methods=['POST']) @bp.route('/profile/tokens/<int:token_id>/revoke', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -1169,6 +1199,7 @@ def revoke_api_token(token_id): ...@@ -1169,6 +1199,7 @@ def revoke_api_token(token_id):
logger.error(f"Revoke API token error: {str(e)}") logger.error(f"Revoke API token error: {str(e)}")
return jsonify({'error': 'Failed to revoke API token'}), 500 return jsonify({'error': 'Failed to revoke API token'}), 500
@csrf.exempt
@bp.route('/profile/tokens/<int:token_id>/extend', methods=['POST']) @bp.route('/profile/tokens/<int:token_id>/extend', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -1205,6 +1236,7 @@ def extend_api_token(token_id): ...@@ -1205,6 +1236,7 @@ def extend_api_token(token_id):
# API Routes with Token Authentication # API Routes with Token Authentication
@csrf.exempt
@bp.route('/api/matches') @bp.route('/api/matches')
def api_matches(): def api_matches():
"""API endpoint to list matches (requires API token)""" """API endpoint to list matches (requires API token)"""
...@@ -1260,6 +1292,7 @@ def api_matches(): ...@@ -1260,6 +1292,7 @@ def api_matches():
return _api_matches() return _api_matches()
@csrf.exempt
@bp.route('/api/fixtures') @bp.route('/api/fixtures')
def api_fixtures(): def api_fixtures():
"""API endpoint to list fixtures (requires API token)""" """API endpoint to list fixtures (requires API token)"""
...@@ -1313,6 +1346,7 @@ def api_fixtures(): ...@@ -1313,6 +1346,7 @@ def api_fixtures():
return _api_fixtures() return _api_fixtures()
@csrf.exempt
@bp.route('/api/match/<int:match_id>') @bp.route('/api/match/<int:match_id>')
def api_match_detail(match_id): def api_match_detail(match_id):
"""API endpoint to get match details (requires API token)""" """API endpoint to get match details (requires API token)"""
...@@ -1342,6 +1376,7 @@ def api_match_detail(match_id): ...@@ -1342,6 +1376,7 @@ def api_match_detail(match_id):
return _api_match_detail() return _api_match_detail()
@csrf.exempt
@bp.route('/download/zip/<int:match_id>') @bp.route('/download/zip/<int:match_id>')
@login_required @login_required
@require_active_user @require_active_user
......
...@@ -16,6 +16,7 @@ from app.upload.forms import FixtureUploadForm, ZipUploadForm ...@@ -16,6 +16,7 @@ from app.upload.forms import FixtureUploadForm, ZipUploadForm
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@csrf.exempt
@bp.route('/fixture', methods=['GET', 'POST']) @bp.route('/fixture', methods=['GET', 'POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -68,6 +69,7 @@ def upload_fixture(): ...@@ -68,6 +69,7 @@ def upload_fixture():
return render_template('upload/fixture.html', form=form) return render_template('upload/fixture.html', form=form)
@csrf.exempt
@bp.route('/zip', methods=['POST']) @bp.route('/zip', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -131,6 +133,7 @@ def upload_zip(): ...@@ -131,6 +133,7 @@ def upload_zip():
flash('Upload processing failed', 'error') flash('Upload processing failed', 'error')
return redirect(request.referrer or url_for('main.fixtures')) return redirect(request.referrer or url_for('main.fixtures'))
@csrf.exempt
@bp.route('/zip/<int:match_id>', methods=['GET', 'POST']) @bp.route('/zip/<int:match_id>', methods=['GET', 'POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -191,6 +194,7 @@ def upload_zip_page(match_id): ...@@ -191,6 +194,7 @@ def upload_zip_page(match_id):
return render_template('upload/zip.html', form=form, match=match) return render_template('upload/zip.html', form=form, match=match)
@csrf.exempt
@bp.route('/zip/<int:match_id>/delete', methods=['POST']) @bp.route('/zip/<int:match_id>/delete', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -842,6 +846,7 @@ def api_upload_info(upload_id): ...@@ -842,6 +846,7 @@ def api_upload_info(upload_id):
logger.error(f"Upload info error: {str(e)}") logger.error(f"Upload info error: {str(e)}")
return jsonify({'error': 'Failed to get upload info'}), 500 return jsonify({'error': 'Failed to get upload info'}), 500
@csrf.exempt
@bp.route('/fixture/<fixture_id>/zip', methods=['POST']) @bp.route('/fixture/<fixture_id>/zip', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
...@@ -915,8 +920,8 @@ def upload_fixture_zip(fixture_id): ...@@ -915,8 +920,8 @@ def upload_fixture_zip(fixture_id):
flash('Upload processing failed', 'error') flash('Upload processing failed', 'error')
return redirect(request.referrer or url_for('main.fixtures')) return redirect(request.referrer or url_for('main.fixtures'))
@bp.route('/chunk', methods=['POST'])
@csrf.exempt @csrf.exempt
@bp.route('/chunk', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
def upload_chunk(): def upload_chunk():
...@@ -956,8 +961,8 @@ def upload_chunk(): ...@@ -956,8 +961,8 @@ def upload_chunk():
logger.error(f"Chunk upload error: {str(e)}") logger.error(f"Chunk upload error: {str(e)}")
return jsonify({'success': False, 'error': str(e)}), 500 return jsonify({'success': False, 'error': str(e)}), 500
@bp.route('/finalize', methods=['POST'])
@csrf.exempt @csrf.exempt
@bp.route('/finalize', methods=['POST'])
@login_required @login_required
@require_active_user @require_active_user
def finalize_upload(): def finalize_upload():
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment