added Authentik config

This commit is contained in:
Christian Krakau-Louis
2025-03-25 11:34:22 +01:00
parent 19c763e595
commit 6ca68126ed
2 changed files with 72 additions and 18 deletions
+56
View File
@@ -0,0 +1,56 @@
# app/auth.py
import os
from authlib.integrations.starlette_client import OAuth
from starlette.config import Config
from starlette.middleware.sessions import SessionMiddleware
from fastapi import APIRouter, Request
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",
},
)
router = APIRouter()
def get_current_user(request: Request):
return request.session.get("user")
def require_login(func):
"""Decorator to require login for particular endpoints."""
async def wrapper(request: Request, *args, **kwargs):
if not request.session.get("user"):
return RedirectResponse(url="/login")
return await func(request, *args, **kwargs)
return wrapper
@router.get("/login")
async def login(request: Request):
redirect_uri = request.url_for("auth")
return await oauth.authentik.authorize_redirect(request, redirect_uri)
@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)
return RedirectResponse(url="/ui")
@router.get("/logout")
async def logout(request: Request):
request.session.pop("user", None)
return RedirectResponse(url="/")
@router.get("/private")
@require_login
async def private_page(request: Request):
user = request.session.get("user")
return {"message": f"This is a protected page. Hello {user['email']}!"}
+15 -17
View File
@@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
from fastapi import FastAPI, HTTPException, UploadFile, File from fastapi import FastAPI, HTTPException, UploadFile, File
from app.config import settings from app.config import settings
@@ -9,9 +8,19 @@ from app.tasks.upload_to_paperless import upload_to_paperless
from app.tasks.upload_to_nextcloud import upload_to_nextcloud from app.tasks.upload_to_nextcloud import upload_to_nextcloud
from app.tasks.send_to_all import send_to_all_destinations from app.tasks.send_to_all import send_to_all_destinations
from app.frontend import router as frontend_router from app.frontend import router as frontend_router
from app.auth import router as auth_router
from starlette.middleware.sessions import SessionMiddleware
from starlette.config import Config
# Load configuration from .env for the session key
config = Config(".env")
SESSION_SECRET = config("SESSION_SECRET", default="YOUR_DEFAULT_SESSION_SECRET_MUST_BE_32_CHARS_OR_MORE")
app = FastAPI(title="Document Processing API") app = FastAPI(title="Document Processing API")
# Add session middleware (needed for storing user sessions)
app.add_middleware(SessionMiddleware, secret_key=SESSION_SECRET)
@app.get("/") @app.get("/")
def root(): def root():
return {"message": "Document Processing API"} return {"message": "Document Processing API"}
@@ -22,8 +31,6 @@ def process(file_path: str):
API Endpoint to start document processing. API Endpoint to start document processing.
This enqueues the first task (upload_to_s3), which handles the full pipeline. This enqueues the first task (upload_to_s3), which handles the full pipeline.
""" """
# If file_path is not absolute, treat it as relative to settings.workdir.
if not os.path.isabs(file_path): if not os.path.isabs(file_path):
file_path = os.path.join(settings.workdir, file_path) file_path = os.path.join(settings.workdir, file_path)
@@ -60,27 +67,20 @@ def send_to_nextcloud(file_path: str):
task = upload_to_nextcloud.delay(file_path) task = upload_to_nextcloud.delay(file_path)
return {"task_id": task.id, "status": "queued"} return {"task_id": task.id, "status": "queued"}
@app.post("/send_to_all_destinations/") @app.post("/send_to_all_destinations/")
def send_to_all_destinations_endpoint(file_path: str): def send_to_all_destinations_endpoint(file_path: str):
""" """
Call the aggregator task that sends this file to dropbox, nextcloud, and paperless. Call the aggregator task that sends this file to dropbox, nextcloud, and paperless.
""" """
if not os.path.isabs(file_path): if not os.path.isabs(file_path):
# If not absolute, assume it's in processed subdir
file_path = os.path.join(settings.workdir, 'processed', file_path) file_path = os.path.join(settings.workdir, 'processed', file_path)
if not os.path.exists(file_path): if not os.path.exists(file_path):
raise HTTPException( raise HTTPException(status_code=400, detail=f"File {file_path} not found.")
status_code=400,
detail=f"File {file_path} not found."
)
task = send_to_all_destinations.delay(file_path) task = send_to_all_destinations.delay(file_path)
return {"task_id": task.id, "status": "queued", "file_path": file_path} return {"task_id": task.id, "status": "queued", "file_path": file_path}
@app.post("/processall") @app.post("/processall")
def process_all_pdfs_in_workdir(): def process_all_pdfs_in_workdir():
""" """
@@ -102,7 +102,6 @@ def process_all_pdfs_in_workdir():
task_ids = [] task_ids = []
for pdf in pdf_files: for pdf in pdf_files:
file_path = os.path.join(target_dir, pdf) file_path = os.path.join(target_dir, pdf)
# Enqueue upload_to_s3
from app.tasks.upload_to_s3 import upload_to_s3 from app.tasks.upload_to_s3 import upload_to_s3
task = upload_to_s3.delay(file_path) task = upload_to_s3.delay(file_path)
task_ids.append(task.id) task_ids.append(task.id)
@@ -113,14 +112,10 @@ def process_all_pdfs_in_workdir():
"task_ids": task_ids "task_ids": task_ids
} }
app.include_router(frontend_router)
@app.post("/ui-upload") @app.post("/ui-upload")
async def ui_upload(file: UploadFile = File(...)): async def ui_upload(file: UploadFile = File(...)):
# You can store this file in your 'workdir' (like how /process does) or a tmp dir
workdir = "/workdir" workdir = "/workdir"
target_path = os.path.join(workdir, file.filename) target_path = os.path.join(workdir, file.filename)
try: try:
with open(target_path, "wb") as f: with open(target_path, "wb") as f:
content = await file.read() content = await file.read()
@@ -128,6 +123,9 @@ async def ui_upload(file: UploadFile = File(...)):
except Exception as e: except Exception as e:
raise HTTPException(status_code=500, detail=f"Failed to save file: {e}") raise HTTPException(status_code=500, detail=f"Failed to save file: {e}")
# Now you can call your existing Celery flow:
task = upload_to_s3.delay(target_path) task = upload_to_s3.delay(target_path)
return {"task_id": task.id, "status": "queued"} return {"task_id": task.id, "status": "queued"}
# Include the frontend and auth routers
app.include_router(frontend_router)
app.include_router(auth_router)