"""Application.""" import sentry_sdk from audience_common.context.asgi.middleware import ( CorrelationIdMiddleware, RequestContextMiddleware, ) from audience_common.logger.asgi.middleware import RequestLoggerMiddleware from fastapi import FastAPI, HTTPException from fastapi.datastructures import Default from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import JSONResponse from monday_com_orca_backend import config from monday_com_orca_backend.api import auth, error_handlers, routers from monday_com_orca_backend.enums import HttpHeader, HttpMethod app = FastAPI( debug=config.APP_DEBUG, title=config.SERVICE_NAME, version=config.SERVICE_VERSION, default_response_class=Default(JSONResponse), description="Backend of the Monday.com ORCA project custom extension.", ) app.add_middleware( CORSMiddleware, allow_origins=[ # Development tunnel. The subdomain remains the same # for each new version deployment. "https://b5279b6533af.apps-tunnel.monday.app", # Frontend hosted in AWS and embedded in the Monday.com as iframe. "https://qa-monday-com-orca-frontend-cdn.qa-business-solutions.theorchard.io", "https://prod-monday-com-orca-frontend-cdn.prod-business-solutions.theorchard.io", ], allow_credentials=True, allow_methods=[HttpMethod.GET, HttpMethod.POST, HttpMethod.OPTIONS], allow_headers=[ HttpHeader.CONTENT_TYPE, HttpHeader.AUTHORIZATION, # For running backend behind Orchard VPN: HttpHeader.ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK, ], # Live app CDN. Must use REGEX with wildcard to allow all subdomains, # as each version deployment has its own random subdomain # (e.g. https://2f5da2e19899ad71.cdn2.monday.app) # As of the current moment of implementing this, 'allow_origin_regex' # has precedence over 'allow_origins'. See CORSMiddleware implementation # for more details. allow_origin_regex=r"https?://[a-zA-Z0-9]+\.cdn2\.monday\.app", ) app.add_middleware(CorrelationIdMiddleware) app.add_middleware(RequestContextMiddleware) app.add_middleware( RequestLoggerMiddleware, exclude_paths=["/hello", "/redoc", "/docs", "/openapi.json"], ) app.add_middleware( auth.JWTMiddleware, excluded_paths=["/hello"], custom_error_handler=error_handlers.unauthorized_exception_handler, # type: ignore[arg-type] # Ignore trailing slashes in paths, e.g. "/hello/" and "/hello" # are treated as the same path ignore_trailing_slash=True, ) app.include_router(routers.infra.router, tags=["Infra"]) app.include_router(routers.data.router, prefix="/api/data", tags=["Data"]) app.include_router(routers.users.router, prefix="/api/users", tags=["Users"]) # Register exception handlers app.add_exception_handler(Exception, error_handlers.default_error_handler) app.add_exception_handler( HTTPException, error_handlers.http_error_handler, # type: ignore[arg-type] ) if not config.SENTRY_DSN: if config.ENVIRONMENT in {config.PROD_ENVIRONMENT, config.QA_ENVIRONMENT}: raise Exception(f"Sentry is not configured in {config.ENVIRONMENT}") sentry_sdk.init(dsn=config.SENTRY_DSN)