from functools import wraps from flask import current_app, g, jsonify from flask_httpauth import HTTPTokenAuth from inventory_provider.config import ServiceName from typing import Callable, List, Optional auth = HTTPTokenAuth(scheme="ApiKey") @auth.verify_token def verify_api_key(api_key: Optional[str]) -> Optional[ServiceName]: config = current_app.config["INVENTORY_PROVIDER_CONFIG"] # This is to enable anonymous access for testing. if not api_key: g.auth_client = ServiceName.ANONYMOUS return ServiceName.ANONYMOUS for client, details in config['api-keys'].items(): if details.get('api-key') == api_key: g.auth_client = client return client return None def authorize(*, allowed_clients: List[ServiceName]) -> Callable: """Decorator to restrict route access to specific clients.""" if not isinstance(allowed_clients, list): raise TypeError("allowed_clients must be a list of allowed service names") def decorator(f: Callable) -> Callable: @wraps(f) def wrapped(*args, **kwargs): client = g.get("auth_client") if client not in allowed_clients: # Anonymous clients are allowed to access any resource without providing an API key # TODO: Only for testing, should be removed in Production if client != ServiceName.ANONYMOUS: return jsonify({"error": "Forbidden"}), 403 return f(*args, **kwargs) return wrapped return decorator