Skip to content
Snippets Groups Projects
auth.py 1.52 KiB
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