from functools import wraps import aiohttp from starlette.responses import JSONResponse from logger import root_logger as logger from settings import AUTH_URL async def request_data(gql, headers=None): if headers is None: headers = {"Content-Type": "application/json"} try: async with aiohttp.ClientSession() as session: async with session.post(AUTH_URL, json=gql, headers=headers) as response: if response.status == 200: data = await response.json() errors = data.get("errors") if errors: logger.error(f"HTTP Errors: {errors}") else: return data except Exception as e: # Handling and logging exceptions during authentication check import traceback logger.error(f"request_data error: {e}") logger.error(traceback.format_exc()) return None async def check_auth(req): logger.info('checking auth token') logger.debug(req.headers) token = req.headers.get("Authorization") user_id = "" if token: # Logging the authentication token logger.debug(f"{token}") query_name = "validate_jwt_token" operation = "ValidateToken" variables = {"params": {"token_type": "access_token", "token": token}} gql = { "query": f"query {operation}($params: ValidateJWTTokenInput!) {{" + f"{query_name}(params: $params) {{ is_valid claims }} " + "}", "variables": variables, "operationName": operation, } data = await request_data(gql) if data: logger.debug(data) user_data = data.get("data", {}).get(query_name, {}).get("claims", {}) user_id = user_data.get("sub", "") return user_id def login_required(f): """ A decorator that requires user authentication before accessing a route. """ @wraps(f) async def decorated_function(req, *args, **kwargs): user_id = await check_auth(req) if user_id: logger.info(f" got {user_id}") req.state.user_id = user_id.strip() return await f(req, *args, **kwargs) else: return JSONResponse({"detail": "Not authorized"}, status_code=401) return decorated_function