Fixed web auth

parent ca38e0be
......@@ -471,68 +471,96 @@ class AuthManager:
"""Hash token for secure storage"""
return hashlib.sha256(token.encode()).hexdigest()
def require_auth(self, f):
def require_auth(self, f=None):
"""Decorator for routes requiring authentication"""
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ', 1)[1]
# Try JWT token first
payload = self.verify_jwt_token(token)
if payload:
request.current_user = payload
return f(*args, **kwargs)
# Try API token
api_data = self.verify_api_token(token)
if api_data:
request.current_user = api_data
return f(*args, **kwargs)
return {'error': 'Authentication required'}, 401
return decorated_function
def decorator(func):
@wraps(func)
def decorated_function(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ', 1)[1]
# Try JWT token first
payload = self.verify_jwt_token(token)
if payload:
request.current_user = payload
return func(*args, **kwargs)
# Try API token
api_data = self.verify_api_token(token)
if api_data:
request.current_user = api_data
return func(*args, **kwargs)
return {'error': 'Authentication required'}, 401
return decorated_function
# If called without arguments, return the decorator
if f is None:
return decorator
# If called with a function, apply the decorator immediately
else:
return decorator(f)
def require_admin(self, f):
def require_admin(self, f=None):
"""Decorator for routes requiring admin access"""
from functools import wraps
@wraps(f)
def decorated_function(*args, **kwargs):
if not hasattr(request, 'current_user'):
return {'error': 'Authentication required'}, 401
user_role = request.current_user.get('role', 'normal')
is_admin = request.current_user.get('is_admin', False)
if user_role != 'admin' and not is_admin:
return {'error': 'Admin access required'}, 403
return f(*args, **kwargs)
return decorated_function
def decorator(func):
@wraps(func)
def decorated_function(*args, **kwargs):
if not hasattr(request, 'current_user'):
return {'error': 'Authentication required'}, 401
user_role = request.current_user.get('role', 'normal')
is_admin = request.current_user.get('is_admin', False)
if user_role != 'admin' and not is_admin:
return {'error': 'Admin access required'}, 403
return func(*args, **kwargs)
return decorated_function
# If called without arguments, return the decorator
if f is None:
return decorator
# If called with a function, apply the decorator immediately
else:
return decorator(f)
def require_role(self, allowed_roles: List[str]):
"""Decorator for routes requiring specific roles"""
from functools import wraps
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not hasattr(request, 'current_user'):
return {'error': 'Authentication required'}, 401
user_role = request.current_user.get('role', 'normal')
if user_role not in allowed_roles:
return {'error': f'Access denied. Required roles: {", ".join(allowed_roles)}'}, 403
return f(*args, **kwargs)
return decorated_function
return decorator
\ No newline at end of file
return decorator
def get_auth_decorator(self, require_admin=False):
"""Get the appropriate auth decorator based on availability"""
if hasattr(self, '_app') and self._app:
if require_admin:
return self.require_admin()
else:
return self.require_auth()
else:
# Fallback to Flask-Login's login_required
from flask_login import login_required
return login_required
\ No newline at end of file
......@@ -15,6 +15,16 @@ from werkzeug.utils import secure_filename
from .auth import AuthenticatedUser
from ..core.message_bus import Message, MessageType
def conditional_auth_decorator(condition, auth_decorator, fallback_decorator=login_required):
"""Helper function for conditional auth decorators"""
def decorator(func):
if condition:
return auth_decorator(func)
else:
return fallback_decorator(func)
return decorator
logger = logging.getLogger(__name__)
# Blueprint definitions
......@@ -2059,8 +2069,25 @@ def get_cashier_pending_matches():
# Allow access from localhost without authentication
if request.remote_addr == '127.0.0.1':
pass # Skip authentication
# Check if user is authenticated via Flask-Login (web interface)
elif current_user.is_authenticated:
pass # User is logged in via web interface
elif hasattr(api_bp, 'auth_manager') and api_bp.auth_manager:
api_bp.auth_manager.require_auth()
# Apply API token authentication manually
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ', 1)[1]
payload = api_bp.auth_manager.verify_jwt_token(token)
if payload:
request.current_user = payload
else:
api_data = api_bp.auth_manager.verify_api_token(token)
if api_data:
request.current_user = api_data
else:
return {'error': 'Authentication required'}, 401
else:
return {'error': 'Authentication required'}, 401
from ..database.models import MatchModel
from datetime import datetime, date, timedelta
......@@ -2213,8 +2240,25 @@ def get_fixture_details(fixture_id):
# Allow access from localhost without authentication
if request.remote_addr == '127.0.0.1':
pass # Skip authentication
# Check if user is authenticated via Flask-Login (web interface)
elif current_user.is_authenticated:
pass # User is logged in via web interface
elif hasattr(api_bp, 'auth_manager') and api_bp.auth_manager:
api_bp.auth_manager.require_auth()
# Apply auth check manually for conditional auth
auth_header = request.headers.get('Authorization')
if auth_header and auth_header.startswith('Bearer '):
token = auth_header.split(' ', 1)[1]
payload = api_bp.auth_manager.verify_jwt_token(token)
if payload:
request.current_user = payload
else:
api_data = api_bp.auth_manager.verify_api_token(token)
if api_data:
request.current_user = api_data
else:
return {'error': 'Authentication required'}, 401
else:
return {'error': 'Authentication required'}, 401
from ..database.models import MatchModel, MatchOutcomeModel
from datetime import datetime, date
......
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