From 4f5daa9e6533d86cafecb04fad3a105d778ac9b2 Mon Sep 17 00:00:00 2001 From: Damir Date: Wed, 8 Apr 2026 00:14:00 +0300 Subject: [PATCH] update --- backend/main.py | 78 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/backend/main.py b/backend/main.py index 6cbc811..67417cf 100644 --- a/backend/main.py +++ b/backend/main.py @@ -8,6 +8,7 @@ from fastapi import Depends, FastAPI, HTTPException from pydantic import BaseModel from sqlalchemy import select from sqlalchemy.orm import Session +from sqlalchemy.exc import SQLAlchemyError app = FastAPI(title="AI CI/CD Assistant") @@ -42,12 +43,26 @@ def validate_config(config_text: str): @app.get("/health") async def health(): - return {"status": "ok"} + # lightweight DB probe to surface connection issues early + db_ok = True + db_error = None + try: + with engine.connect() as conn: + conn.exec_driver_sql("SELECT 1") + except Exception as e: + db_ok = False + db_error = str(e) + return {"status": "ok", "db_ok": db_ok, "db_error": db_error} @app.on_event("startup") def _startup(): - Base.metadata.create_all(bind=engine) + # Ensure tables exist; if DB is unreachable, endpoints will surface the error. + try: + Base.metadata.create_all(bind=engine) + except Exception: + # Avoid crashing the service hard; /health will show db_error. + pass class RegisterRequest(BaseModel): @@ -67,35 +82,50 @@ def register(req: RegisterRequest, db: Session = Depends(get_db)): if not email or not req.password: raise HTTPException(status_code=400, detail="Email and password are required") - exists = db.execute(select(User).where(User.email == email)).scalar_one_or_none() - if exists: - raise HTTPException(status_code=409, detail="Email already registered") + try: + exists = db.execute(select(User).where(User.email == email)).scalar_one_or_none() + if exists: + raise HTTPException(status_code=409, detail="Email already registered") - user = User( - email=email, - full_name=req.full_name.strip() if req.full_name else None, - password_hash=hash_password(req.password), - is_active=True, - is_admin=False, - ) - db.add(user) - db.commit() - db.refresh(user) - - return {"id": str(user.id), "email": user.email, "full_name": user.full_name, "is_admin": user.is_admin} + user = User( + email=email, + full_name=req.full_name.strip() if req.full_name else None, + password_hash=hash_password(req.password), + is_active=True, + is_admin=False, + ) + db.add(user) + db.commit() + db.refresh(user) + return {"id": str(user.id), "email": user.email, "full_name": user.full_name, "is_admin": user.is_admin} + except HTTPException: + raise + except SQLAlchemyError as e: + db.rollback() + raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") + except Exception as e: + db.rollback() + raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}") @app.post("/auth/login") def login(req: LoginRequest, db: Session = Depends(get_db)): email = req.email.strip().lower() - user = db.execute(select(User).where(User.email == email)).scalar_one_or_none() - if not user or not verify_password(req.password, user.password_hash): - raise HTTPException(status_code=401, detail="Invalid credentials") - if not user.is_active: - raise HTTPException(status_code=403, detail="User is inactive") + try: + user = db.execute(select(User).where(User.email == email)).scalar_one_or_none() + if not user or not verify_password(req.password, user.password_hash): + raise HTTPException(status_code=401, detail="Invalid credentials") + if not user.is_active: + raise HTTPException(status_code=403, detail="User is inactive") - token = create_access_token(user_id=str(user.id)) - return {"access_token": token, "token_type": "bearer"} + token = create_access_token(user_id=str(user.id)) + return {"access_token": token, "token_type": "bearer"} + except HTTPException: + raise + except SQLAlchemyError as e: + raise HTTPException(status_code=500, detail=f"Database error: {str(e)}") + except Exception as e: + raise HTTPException(status_code=500, detail=f"Internal error: {str(e)}") @app.get("/auth/me")