import os from fastapi import FastAPI from fastapi.responses import RedirectResponse from fastapi.staticfiles import StaticFiles from app.config import settings from app.database import init_db, SessionLocal from app.models import AdminUser, Profile from app.routers import auth, public, admin, chat from app.routers.auth import hash_password BASE = settings.BASE_PATH # "" for root deployment, or "/careerbot" for subpath app = FastAPI(title="CareerBot", description="Personal Career Showcase with AI Assistant") # Mount static files and uploads under BASE_PATH app.mount(f"{BASE}/static", StaticFiles(directory="app/static"), name="static") os.makedirs(settings.UPLOAD_DIR, exist_ok=True) app.mount(f"{BASE}/uploads", StaticFiles(directory=settings.UPLOAD_DIR), name="uploads") # When BASE="" and DB is shared with a /careerbot deployment, photo_url values # stored by the sibling deployment begin with "/careerbot/uploads/...". # Add a secondary mount so those URLs keep resolving here. if BASE == "": app.mount("/careerbot/uploads", StaticFiles(directory=settings.UPLOAD_DIR), name="uploads_legacy") # Include routers with BASE_PATH prefix app.include_router(auth.router, prefix=BASE) app.include_router(public.router, prefix=BASE) app.include_router(admin.router, prefix=BASE) app.include_router(chat.router, prefix=BASE) # Set Jinja2 template globals for BASE_PATH admin.templates.env.globals["base"] = BASE public.templates.env.globals["base"] = BASE # Root redirect only needed when deployed under a subpath (otherwise "/" is already the app root) if BASE: @app.get("/") def root_redirect(): return RedirectResponse(url=f"{BASE}/", status_code=302) @app.on_event("startup") def startup(): init_db() db = SessionLocal() try: # Ensure admin user exists admin_user = db.query(AdminUser).filter(AdminUser.email == "ln0422@gmail.com").first() if not admin_user: admin_user = AdminUser( email="ln0422@gmail.com", password_hash=hash_password("qshs123456"), ) db.add(admin_user) db.commit() # Ensure profile exists profile = db.query(Profile).first() if not profile: db.add(Profile()) db.commit() finally: db.close()