diff --git a/app/routers/search.py b/app/routers/search.py index ddb9be3..28e3e3e 100644 --- a/app/routers/search.py +++ b/app/routers/search.py @@ -2,10 +2,19 @@ ``GET /api/search?q=`` backs the Ctrl+K command palette. Returns matching editor pages and databases scoped to the current user's accessible workspaces. + +Recherche partout (fusion-trois-apps #68) : la même route sert la page +unifiée (``GET /recherche``, coquille dont les résultats sont chargés +côté client) et accepte, en plus de la session native, le jeton SSO +``draco_session`` (validateur local ``app.services.draco``). Sans +session ni jeton valide, 401 — avant cette livraison, l'absence de +session donnait une recherche SANS périmètre (``user_id=None`` → ``1=1`` +dans ``_scope_where``) : corrigé ici. """ from __future__ import annotations -from fastapi import APIRouter, Query, Request +from fastapi import APIRouter, HTTPException, Query, Request +from fastapi.responses import HTMLResponse from app.auth.session import SessionManager from app.services.search import search as search_service @@ -17,6 +26,18 @@ router = APIRouter(tags=["search"]) def search(request: Request, q: str = Query(default="")): user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) user_id = user.get("id") if user and user.get("id") else None + if user_id is None: + # Repli SSO draco_session : un jeton valide désigne l'utilisateur + # lié, ou l'unique utilisateur actif (cas mono-utilisateur). + try: + from app.services import draco as draco_service + + draco_user = draco_service.user_for_draco(request) + user_id = draco_user.get("id") if draco_user else None + except Exception: + user_id = None + if user_id is None: + raise HTTPException(status_code=401, detail="Authentication required") data = search_service(q, user_id=user_id) return { @@ -25,3 +46,24 @@ def search(request: Request, q: str = Query(default="")): "collections": data["collections"], "total": len(data["pages"]) + len(data["collections"]), } + + +@router.get("/recherche", response_class=HTMLResponse) +def recherche_page(request: Request, q: str = Query(default="")): + """Page de résultats unifiée « Rechercher partout » (fusion #68). + + Coquille seule : les résultats sont chargés côté client par + static/js/recherche.js (API de recherche de chaque app, en + parallèle, états par application). La palette Ctrl+K native et + ``GET /api/search`` restent inchangés par ailleurs. + """ + from app.services import draco_urls + from app.templating import ENV + + user = SessionManager.decode_session(request.cookies.get("flowdeck_session", "")) + bases = draco_urls.toutes() + template = ENV.get_template("recherche.html") + return HTMLResponse(template.render( + request=request, q=q.strip(), user=user, + bases={k: bases[k] for k in ("obsigate", "flowdeck", "tiktak", "kanbante")}, + ))