saleor-apps-redis_apl/apps/monitoring/backend/monitoring/deps.py
Przemysław Łada b33bfd35af
Add Saleor Monitoring app (#189)
* initial commit

* Remove pre-commit-config

* Update gitignore

* Update README

* Add better config for monitoring app (#190)

---------

Co-authored-by: Lukasz Ostrowski <lukasz.ostrowski@saleor.io>
2023-02-22 12:23:04 +01:00

143 lines
4.2 KiB
Python

import logging
from fastapi import Depends, Header, HTTPException, Request
from jwt.api_jwk import PyJWKSet
from .apl import AplEntity, AplError, AplKeyError, apl_client
from .integrations.datadog import DataDogApiClient, DataDogClient, TestDataDogClient
from .saleor import (
SALEOR_API_URL_HEADER,
SALEOR_SIGNATURE_HEADER,
SALEOR_TOKEN_HEADER,
SaleorToken,
)
from .saleor.crypto import decode_webhook_payload
from .saleor.manager import SaleorManager
from .schema import Metadata
from .settings import settings
logger = logging.getLogger(__name__)
async def saleor_api_url_header(
api_url: str | None = Header(None, alias=SALEOR_API_URL_HEADER)
) -> str:
if not api_url:
msg = f"Missing {SALEOR_API_URL_HEADER.upper()} header."
logger.warning(msg)
raise HTTPException(status_code=400, detail=msg)
return api_url
async def verify_saleor_api_url(api_url: str = Depends(saleor_api_url_header)):
# TODO implement
if api_url:
return True
raise HTTPException(
status_code=400,
detail=f"Provided url is invalid or environment {api_url} not allowed.",
)
async def saleor_token_header(
token: str | None = Header(None, alias=SALEOR_TOKEN_HEADER)
) -> str:
if not token:
msg = f"Missing {SALEOR_TOKEN_HEADER.upper()} header."
logger.warning(msg)
raise HTTPException(status_code=400, detail=msg)
return token
async def apl_entity(
api_url: str = Depends(saleor_api_url_header),
_verify=Depends(verify_saleor_api_url),
) -> AplEntity:
try:
return await apl_client.get(api_url)
except AplKeyError:
msg = f"App needs to be installed before use. First, install the app in Saleor at {api_url}."
logger.warning(msg)
raise HTTPException(status_code=400, detail=msg) # noqa: 904
except AplError as error:
logging.error("APL error %r", error)
raise HTTPException( # noqa: 904
status_code=500, detail="App error. Try again later."
)
async def saleor_token(
token_str: str = Depends(saleor_token_header),
saleor_data: AplEntity = Depends(apl_entity),
) -> SaleorToken:
token = SaleorToken(token_str, saleor_data.jwks)
# TODO handle jwks reload
return token
async def verify_is_stuff_user(token: SaleorToken = Depends(saleor_token)) -> bool:
if not token.is_staff_user():
HTTPException(
status_code=400, detail="Only staff user can perform this operation."
)
return True
async def get_saleor_signature(
saleor_signature: str | None = Header(None, alias=SALEOR_SIGNATURE_HEADER)
):
return saleor_signature
async def verify_webhook_signature(
request: Request,
jws: str = Depends(get_saleor_signature),
saleor_data: AplEntity = Depends(apl_entity),
):
saleor_jwks = PyJWKSet.from_dict(saleor_data.jwks)
return decode_webhook_payload(
jws=jws, jwks=saleor_jwks, webhook_payload=await request.body()
)
async def saleor_manager(saleor_data: AplEntity = Depends(apl_entity)):
return SaleorManager[Metadata](
saleor_data.saleor_api_url,
saleor_data.app_id,
saleor_data.app_token,
Metadata,
)
async def datadog_client() -> DataDogClient:
if settings.mock_datadog_client:
return TestDataDogClient()
return DataDogApiClient()
class ApiDependencies:
def __init__(
self,
token: SaleorToken = Depends(saleor_token),
saleor_data: AplEntity = Depends(apl_entity),
manager: SaleorManager[Metadata] = Depends(saleor_manager),
datadog_client: DataDogClient = Depends(datadog_client),
_verify_is_stuff_user=Depends(verify_is_stuff_user),
):
self.saleor_data = saleor_data
self.token = token
self.manager = manager
self.datadog_client = datadog_client
class WebhookDependencies:
def __init__(
self,
saleor_data: AplEntity = Depends(apl_entity),
manager: SaleorManager[Metadata] = Depends(saleor_manager),
datadog_client: DataDogClient = Depends(datadog_client),
_verify_webhook_signature=Depends(verify_webhook_signature),
):
self.saleor_data = saleor_data
self.manager = manager
self.datadog_client = datadog_client