Coverage for or_dependencies.py: 82%
60 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:56 +0000
1import json
2import logging
3from typing import Callable
5from fastapi import Depends, Security
6from fastapi.exceptions import RequestValidationError
7from fastapi.routing import APIRoute
8from fastapi.security import SecurityScopes
9from starlette import status
10from starlette.exceptions import HTTPException
11from starlette.requests import Request
12from starlette.responses import Response, JSONResponse
14import schemas
15from chalicelib.utils import helper
16from chalicelib.utils.log import sanitize
18logger = logging.getLogger(__name__)
21async def OR_context(request: Request) -> schemas.CurrentContext:
22 if hasattr(request.state, "currentContext"): 22 ↛ 25line 22 didn't jump to line 25 because the condition on line 22 was always true
23 return request.state.currentContext
24 else:
25 raise Exception("currentContext not found")
28class ORRoute(APIRoute):
29 def get_route_handler(self) -> Callable:
30 original_route_handler = super().get_route_handler()
32 async def custom_route_handler(request: Request) -> Response:
33 try:
34 response: Response = await original_route_handler(request)
35 except RequestValidationError as exc:
36 # 422 validation exception
37 logger.warning(
38 f"!!! 422 exception when calling: {sanitize(request.method, max_length=16)} {sanitize(str(request.url))}")
39 logger.warning(exc.errors())
40 for e in exc.errors():
41 if e.get("msg", "").endswith("must be alphanumeric"):
42 return JSONResponse(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
43 content={"errors": [e["msg"][18:]], "detail": str(exc)})
44 raise exc
45 except HTTPException as e:
46 if e.status_code // 100 == 4: 46 ↛ 49line 46 didn't jump to line 49 because the condition on line 46 was always true
47 return JSONResponse(content={"errors": e.detail if isinstance(e.detail, list) else [e.detail]},
48 status_code=e.status_code)
49 elif e.status_code // 100 == 5:
50 logger.error(f"!!! status code:{e.status_code}")
51 logger.exception(e)
52 return JSONResponse(content={"errors": ["Internal server error."]},
53 status_code=e.status_code)
54 else:
55 raise e
56 except Exception as e:
57 logger.exception(e)
58 return JSONResponse(content={"errors": ["Internal server error."]},
59 status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
61 if isinstance(response, JSONResponse): 61 ↛ 74line 61 didn't jump to line 74 because the condition on line 61 was always true
62 response: JSONResponse = response
63 body = json.loads(response.body.decode('utf8'))
64 response.body = response.render(helper.cast_session_id_to_string(body))
65 response.headers["Content-Length"] = str(len(response.body))
66 if response.status_code == 200 \
67 and body is not None and isinstance(body, dict) \
68 and body.get("errors") is not None:
69 if "not found" in body["errors"][0]:
70 response.status_code = status.HTTP_404_NOT_FOUND
71 else:
72 response.status_code = status.HTTP_400_BAD_REQUEST
74 return response
76 return custom_route_handler
79def __check_role(required_roles: SecurityScopes, context: schemas.CurrentContext = Depends(OR_context)):
80 if len(required_roles.scopes) > 0: 80 ↛ exitline 80 didn't return from function '__check_role' because the condition on line 80 was always true
81 if context.role not in required_roles.scopes: 81 ↛ 82line 81 didn't jump to line 82 because the condition on line 81 was never true
82 raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED,
83 detail="You need a different role to access this resource")
86def OR_role(*required_roles):
87 return Security(__check_role, scopes=list(required_roles))