130 lines
4.8 KiB
Python
130 lines
4.8 KiB
Python
import os
|
|
import shutil
|
|
import uuid
|
|
from typing import Annotated
|
|
from fastapi import FastAPI, Request, UploadFile, Depends, Form, File, Cookie
|
|
from fastapi.templating import Jinja2Templates
|
|
from fastapi.security import OAuth2PasswordRequestForm
|
|
from fastapi.responses import HTMLResponse, JSONResponse, RedirectResponse, FileResponse
|
|
from fastapi.staticfiles import StaticFiles
|
|
from starlette.middleware.sessions import SessionMiddleware
|
|
from service import auth, reports
|
|
from service.db_requests import get_user
|
|
from service import structs
|
|
from service.models import User
|
|
|
|
app = FastAPI()
|
|
templates = Jinja2Templates(directory="client/templates")
|
|
app.mount("/static", StaticFiles(directory="client/static"), name="static")
|
|
|
|
app.add_middleware(
|
|
SessionMiddleware,
|
|
secret_key="CHANGEME",
|
|
session_cookie="session"
|
|
)
|
|
|
|
|
|
@app.get("/", response_class=RedirectResponse)
|
|
async def main_page(access_token: Annotated[str | None, Cookie()] = None):
|
|
if access_token:
|
|
try:
|
|
await auth.get_current_user(access_token)
|
|
except:
|
|
return RedirectResponse("/login")
|
|
return RedirectResponse("/upload-study")
|
|
else:
|
|
return RedirectResponse("/login")
|
|
|
|
|
|
@app.get("/login", response_class=HTMLResponse)
|
|
async def login_page(request: Request):
|
|
access_token = request.cookies.get("access_token")
|
|
if access_token:
|
|
try:
|
|
await auth.get_current_user(access_token)
|
|
return RedirectResponse("/upload-study", status_code=303)
|
|
except:
|
|
pass
|
|
response = templates.TemplateResponse("login.html", {"request": request})
|
|
response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, private"
|
|
response.headers["Pragma"] = "no-cache"
|
|
response.headers["Expires"] = "0"
|
|
return response
|
|
|
|
|
|
@app.post("/login")
|
|
async def login_submit(request: Request,
|
|
login_data: OAuth2PasswordRequestForm = Depends()):
|
|
user = get_user(login_data.username)
|
|
if user is None or not auth.verify_password(login_data.password,
|
|
user.hashed_password):
|
|
return templates.TemplateResponse("login.html",
|
|
{"request": request, "error": True})
|
|
response = RedirectResponse("/upload-study", status_code=303)
|
|
response.set_cookie(
|
|
key = "access_token",
|
|
value = auth.create_access_token(user.username),
|
|
httponly=True
|
|
)
|
|
return response
|
|
|
|
|
|
@app.get("/upload-study", dependencies=[Depends(auth.get_current_user)])
|
|
async def upload_page(request: Request):
|
|
return templates.TemplateResponse("upload.html", {"request": request})
|
|
|
|
|
|
@app.post("/upload-study")
|
|
async def study_submit(
|
|
request: Request,
|
|
user: User = Depends(auth.get_current_user),
|
|
file: UploadFile = File(None),
|
|
demo_filename: str = Form(None),
|
|
pathology: str = Form(...)
|
|
):
|
|
user_dir = os.path.join("data", user.username)
|
|
os.makedirs(user_dir, exist_ok=True)
|
|
fpath = os.path.join(user_dir, str(uuid.uuid4()) + ".dcm")
|
|
|
|
if file and file.filename:
|
|
with open(fpath, 'wb') as buffer:
|
|
buffer.write(await file.read())
|
|
else:
|
|
demo_source_path = os.path.join("data/demo", pathology, demo_filename)
|
|
shutil.copy2(demo_source_path, fpath)
|
|
|
|
try:
|
|
prediction = reports.make_reports(pathology, fpath, user.username)
|
|
except (structs.TagError, structs.ImagesError) as e:
|
|
error_msg = e.msg + ". Загрузите другой файл."
|
|
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
|
return JSONResponse({"error": error_msg}, status_code=400)
|
|
else:
|
|
return templates.TemplateResponse("upload.html", {"request": request, "error": error_msg})
|
|
except Exception as e:
|
|
error_msg = "Ошибка анализа. Загрузите другой файл."
|
|
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
|
return JSONResponse({"error": error_msg}, status_code=500)
|
|
else:
|
|
return templates.TemplateResponse("upload.html", {"request": request, "error": error_msg})
|
|
|
|
request.session["prediction"] = prediction._asdict()
|
|
if request.headers.get('X-Requested-With') == 'XMLHttpRequest':
|
|
return JSONResponse({"redirect": "/ai-result"})
|
|
else:
|
|
return RedirectResponse("/ai-result", status_code=303)
|
|
|
|
|
|
@app.get("/ai-result", dependencies=[Depends(auth.get_current_user)])
|
|
async def result_page(request: Request):
|
|
prediction = request.session["prediction"]
|
|
return templates.TemplateResponse("result.html", {
|
|
"request": request,
|
|
"prediction": prediction
|
|
})
|
|
|
|
|
|
@app.get("/download/{filename}")
|
|
async def download_report(filename: str,
|
|
user: User = Depends(auth.get_current_user)):
|
|
return FileResponse(f"data/{user.username}/reports/{filename}") |