diff --git a/.env.demo b/.env.demo index a2ad6189..144b4ee4 100644 --- a/.env.demo +++ b/.env.demo @@ -47,7 +47,7 @@ IMAP2_DELETE_AFTER_PROCESS=false GOTENBERG_URL=http://gotenberg:3000 # ** needed for Authentik ** - +AUTH_ENABLED=true SESSION_SECRET= AUTHENTIK_CLIENT_ID= AUTHENTIK_CLIENT_SECRET= diff --git a/app/auth.py b/app/auth.py index ba938ba9..db3df500 100644 --- a/app/auth.py +++ b/app/auth.py @@ -1,4 +1,5 @@ # app/auth.py +# app/auth.py import os from functools import wraps @@ -10,60 +11,57 @@ from starlette.responses import RedirectResponse config = Config(".env") oauth = OAuth(config) -oauth.register( - name="authentik", - client_id=config("AUTHENTIK_CLIENT_ID"), - client_secret=config("AUTHENTIK_CLIENT_SECRET"), - server_metadata_url=config("AUTHENTIK_CONFIG_URL"), - client_kwargs={ - "scope": "openid profile email", - }, -) +AUTH_ENABLED = config("AUTH_ENABLED", cast=bool, default=True) + +if AUTH_ENABLED: + oauth.register( + name="authentik", + client_id=config("AUTHENTIK_CLIENT_ID"), + client_secret=config("AUTHENTIK_CLIENT_SECRET"), + server_metadata_url=config("AUTHENTIK_CONFIG_URL"), + client_kwargs={"scope": "openid profile email"}, + ) router = APIRouter() + def get_current_user(request: Request): return request.session.get("user") + def require_login(func): + if not AUTH_ENABLED: + return func # no-op + @wraps(func) async def wrapper(request: Request, *args, **kwargs): if not request.session.get("user"): - # Save original URL in session before redirecting to login request.session["redirect_after_login"] = str(request.url) return RedirectResponse(url="/login", status_code=status.HTTP_302_FOUND) return await func(request, *args, **kwargs) + return wrapper -@router.get("/login") -async def login(request: Request): - """ - Initiate Authentik login flow. - This calls oauth.authentik.authorize_redirect(...) - The resulting redirect_uri must match what's in Authentik's application config. - """ - redirect_uri = request.url_for("auth") - return await oauth.authentik.authorize_redirect(request, redirect_uri) -@router.get("/auth") -async def auth(request: Request): - """ - Authentik callback endpoint. Exchanges code for token, - puts user info in session, and redirects to /ui or wherever you want. - """ - token = await oauth.authentik.authorize_access_token(request) - userinfo = token.get("userinfo") - request.session["user"] = dict(userinfo) +if AUTH_ENABLED: + @router.get("/login") + async def login(request: Request): + redirect_uri = request.url_for("auth") + return await oauth.authentik.authorize_redirect(request, redirect_uri) - # Get original destination or fallback - redirect_url = request.session.pop("redirect_after_login", "/ui") - return RedirectResponse(url=redirect_url) + @router.get("/auth") + async def auth(request: Request): + token = await oauth.authentik.authorize_access_token(request) + userinfo = token.get("userinfo") + request.session["user"] = dict(userinfo) + redirect_url = request.session.pop("redirect_after_login", "/upload") + return RedirectResponse(url=redirect_url) + + @router.get("/logout") + async def logout(request: Request): + request.session.pop("user", None) + return RedirectResponse(url="/") -@router.get("/logout") -async def logout(request: Request): - """Clears session and redirects home.""" - request.session.pop("user", None) - return RedirectResponse(url="/") @router.get("/private") @require_login diff --git a/app/frontend.py b/app/frontend.py index 9cec1c42..f278fb4f 100644 --- a/app/frontend.py +++ b/app/frontend.py @@ -2,6 +2,7 @@ from fastapi import APIRouter from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles +from app.auth import require_login import os router = APIRouter() @@ -14,7 +15,9 @@ frontend_folder = os.path.join(os.path.dirname(__file__), "..", "frontend") router.mount("/static", StaticFiles(directory=frontend_folder), name="static") # 2) For the root route ("/"), return the index.html -@router.get("/ui", response_class=FileResponse) + +@router.get("/upload", response_class=FileResponse) +@require_login def serve_ui(): return os.path.join(frontend_folder, "index.html")