import logging import os import traceback from importlib.resources import files from fastapi import FastAPI, Request from fastapi.responses import HTMLResponse, JSONResponse from fastapi.staticfiles import StaticFiles from fastapi.templating import Jinja2Templates from fastapi.encoders import jsonable_encoder import mc_openapi.assets as ASSETS from mc_openapi.doml_mc import (init_model, verify_csp_compatibility, verify_model) from mc_openapi.doml_mc.exceptions import * from mc_openapi.doml_mc.intermediate_model.metamodel import DOMLVersion from mc_openapi.doml_mc.mc import ModelChecker assets = files(ASSETS) static_path = assets / "static" templates_path = assets / "templates" app = FastAPI() app.mount("/static", StaticFiles(directory=static_path), name="static") templates = Jinja2Templates(directory=templates_path) @app.get("/", response_class=HTMLResponse) async def root(request: Request): return templates.TemplateResponse("home.html", {"request": request}) def handleDOMLX(doml_xmi: bytes, callback) -> dict: doml_version_str: str = None doml_version: DOMLVersion = None try: # First try to infer DOML version from ENV, then query params doml_version_str = os.environ.get("DOML_VERSION") if doml_version_str: doml_version = DOMLVersion.get(doml_version_str) logging.info(f"Forcing DOML {doml_version.value}") dmc = init_model(doml_xmi, doml_version) return callback(dmc) except ( BadDOMLException, UnsupportedDOMLVersionException, MissingInfrastructureLayerException, NoActiveConcreteLayerException ) as e: return JSONResponse( status_code=400, content=jsonable_encoder({ "message": e.errors, "debug_message": traceback.format_exc() }) ) except (RuntimeError, Exception) as e: logging.error(traceback.format_exc()) return JSONResponse( status_code=400, content=jsonable_encoder({ "message": "An error has occurred. It could be an error within your DOML file. If it persist, try specifying DOML version manually.", "debug_message": traceback.format_exc() }) ) @app.post("/modelcheck") async def mc(request: Request): doml_xmi = await request.body() return handleDOMLX(doml_xmi, verify_model) @app.post("/csp") async def csp(request: Request): doml_xmi = await request.body() return handleDOMLX(doml_xmi, verify_csp_compatibility) @app.post("/modelcheck_html") async def mc_html(request: Request): doml_xmi = await request.body() res = handleDOMLX(doml_xmi, verify_model) return templates.TemplateResponse("mc.html", {"request": request, **res}) @app.post("/csp_html") async def csp_html(request: Request): doml_xmi = await request.body() res = handleDOMLX(doml_xmi, verify_csp_compatibility) return templates.TemplateResponse("csp.html", {"request": request, **res})