
* 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>
131 lines
3.9 KiB
Python
131 lines
3.9 KiB
Python
import logging
|
|
|
|
from fastapi import Depends, FastAPI, Request, status
|
|
from starlette.middleware.cors import CORSMiddleware
|
|
|
|
from .api import graphql_app
|
|
from .apl import AplEntity, apl_client
|
|
from .deps import (
|
|
ApiDependencies,
|
|
WebhookDependencies,
|
|
saleor_api_url_header,
|
|
verify_saleor_api_url,
|
|
)
|
|
from .integrations.datadog import DataDogClientError
|
|
from .logs import configure_logging
|
|
from .payload import OBSERVABILITY_EVENTS
|
|
from .saleor.client import GraphQLError, SaleorClient
|
|
from .saleor.common import InstallData, LazyUrl
|
|
from .settings import manifest, settings
|
|
from .utils import get_base_url
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
configure_logging(settings.debug)
|
|
|
|
apl_client.setup(settings.apl_url)
|
|
|
|
|
|
app = FastAPI(openapi_url="/api/openapi.json")
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_headers=["*"],
|
|
allow_methods=["OPTIONS", "GET", "POST", "DELETE"],
|
|
)
|
|
|
|
|
|
@app.get("/manifest", status_code=status.HTTP_200_OK, tags=["installation-handshake"])
|
|
async def show_manifest(request: Request):
|
|
manifest_copy = manifest.copy()
|
|
for name, field in manifest_copy:
|
|
if isinstance(field, LazyUrl):
|
|
setattr(manifest_copy, name, field(request))
|
|
for extension in manifest_copy.extensions:
|
|
if isinstance(extension.url, LazyUrl):
|
|
extension.url = extension.url(request)
|
|
for webhook in manifest_copy.webhooks:
|
|
if isinstance(webhook.target_url, LazyUrl):
|
|
webhook.target_url = webhook.target_url(request)
|
|
return manifest_copy
|
|
|
|
|
|
@app.post(
|
|
"/install",
|
|
status_code=status.HTTP_200_OK,
|
|
tags=["installation-handshake"],
|
|
name="install",
|
|
)
|
|
async def install(
|
|
data: InstallData,
|
|
request: Request,
|
|
api_url=Depends(saleor_api_url_header),
|
|
_valid=Depends(verify_saleor_api_url),
|
|
):
|
|
client = SaleorClient(api_url, "test", data.auth_token)
|
|
try:
|
|
app_info = await client.app_info()
|
|
target_url = get_base_url(request).replace(path="webhooks")
|
|
await client.create_webhook(
|
|
target_url=str(target_url),
|
|
events=["OBSERVABILITY"],
|
|
name="OBSERVABILITY",
|
|
)
|
|
jwks = await client.get_jwks()
|
|
entity = AplEntity(
|
|
saleor_api_url=api_url,
|
|
app_id=app_info.id,
|
|
app_token=data.auth_token,
|
|
jwks=jwks,
|
|
)
|
|
await apl_client.set(api_url, entity)
|
|
except GraphQLError:
|
|
return {"error": {"message": "Wrong app token"}}
|
|
return {}
|
|
|
|
|
|
@app.post(
|
|
"/webhooks",
|
|
status_code=status.HTTP_200_OK,
|
|
tags=["webhooks"],
|
|
name="webhooks",
|
|
)
|
|
async def handle_observability_events(
|
|
payloads: list[OBSERVABILITY_EVENTS],
|
|
commons: WebhookDependencies = Depends(),
|
|
):
|
|
metadata = await commons.manager.get_metadata()
|
|
if not metadata.datadog or not metadata.datadog.active:
|
|
logger.warning(
|
|
"DataDog integration inactive or not configured. Dropping %s events",
|
|
len(payloads),
|
|
)
|
|
return
|
|
credentials = metadata.datadog.credentials
|
|
try:
|
|
logger.info("Sending %s events to DataDog", len(payloads))
|
|
await commons.datadog_client.send_logs(
|
|
commons.saleor_data.saleor_api_url, credentials, payloads
|
|
)
|
|
except DataDogClientError:
|
|
logger.warning("Sending logs to DataDog failed. Deactivating integration")
|
|
metadata.datadog.active = False
|
|
metadata.datadog.error = "Wrong credentials. Integration deactivated"
|
|
await commons.manager.save_private_metadata(metadata)
|
|
|
|
|
|
@app.get("/health", status_code=status.HTTP_200_OK, tags=["health"], name="health")
|
|
async def health():
|
|
return {"status": "ok"}
|
|
|
|
|
|
@app.get("/graphql")
|
|
async def graphiql(request: Request):
|
|
return await graphql_app.render_playground(request)
|
|
|
|
|
|
@app.post("/graphql")
|
|
async def graphql(request: Request, commons: ApiDependencies = Depends()):
|
|
request.state.api_context = commons
|
|
return await graphql_app.graphql_http_server(request)
|