fix: A21 phase 1 — 352 routes async sans await → threadpool (v7.8.0)
- Conversion `async def` → `def` de TOUTES les routes dont le corps ne contient ni `await`, ni `async with`, ni `async for`, ni `asyncio` (scan automatique corps par corps sur app/ : 352 converties, 0 dangereuses, vérifié `asyncio`/`run_coroutine`/`.result()` absents). FastAPI exécute ces handlers dans son threadpool → tout leur SQLite (`get_conn()` + `conn.execute`) quitte l'event loop, sans changer une ligne de logique. - Répartition : api_v2 60, dashboard 40, collections 25, board 23, workspace 19, wiki 17, permissions 14, api 14, main.py 6, + 35 fichiers. - Les 4 routers prioritaires de l'audit sont couverts par ce lot : api_v2 60 + dashboard 40 + collections 25 + board 23 = 148 conversions (le reste de leurs routes attend la phase 2 : elles ont de vrais `await`). - Reste (phase 2) : les 311 routes avec de vrais `await` → enrouler les blocs DB dans `await anyio.to_thread.run_sync(...)` ; pas de wrapper partagé livré (rien ne l'appellerait — YAGNI jusqu'au premier usage). suite **1037/1037** (233 s) · `ruff check app tests` OK · docs à jour
This commit is contained in:
+60
-60
@@ -93,7 +93,7 @@ async def create_token(request: Request, authorization: str | None = Header(defa
|
||||
return data
|
||||
|
||||
@router.get("/tokens")
|
||||
async def list_tokens(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_tokens(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -109,7 +109,7 @@ async def list_tokens(request: Request, authorization: str | None = Header(defau
|
||||
return {"tokens": out}
|
||||
|
||||
@router.delete("/tokens/{token_id}")
|
||||
async def revoke_token(token_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def revoke_token(token_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -124,7 +124,7 @@ async def revoke_token(token_id: int, request: Request, authorization: str | Non
|
||||
return {"id": token_id, "status": "revoked"}
|
||||
|
||||
@router.post("/tokens/{token_id}/rotate")
|
||||
async def rotate_token(token_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def rotate_token(token_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -147,7 +147,7 @@ async def rotate_token(token_id: int, request: Request, authorization: str | Non
|
||||
# ── Users ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/users/me")
|
||||
async def get_me(request: Request, authorization: str | None = Header(default=None)):
|
||||
def get_me(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -199,7 +199,7 @@ async def patch_me(request: Request, authorization: str | None = Header(default=
|
||||
return row_to_dict(row)
|
||||
|
||||
@router.get("/users/search")
|
||||
async def search_users(request: Request, q: str = "", authorization: str | None = Header(default=None)):
|
||||
def search_users(request: Request, q: str = "", authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
q = (q or request.query_params.get("q") or "").strip()
|
||||
@@ -213,7 +213,7 @@ async def search_users(request: Request, q: str = "", authorization: str | None
|
||||
# ── Workspaces ────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/workspaces")
|
||||
async def list_workspaces(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_workspaces(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -264,7 +264,7 @@ async def create_workspace(request: Request, authorization: str | None = Header(
|
||||
return JSONResponse(content=data, status_code=201)
|
||||
|
||||
@router.get("/workspaces/{workspace_id}")
|
||||
async def get_workspace(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def get_workspace(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -310,7 +310,7 @@ async def patch_workspace(workspace_id: int, request: Request, authorization: st
|
||||
return {"id": workspace_id, "status": "updated"}
|
||||
|
||||
@router.delete("/workspaces/{workspace_id}")
|
||||
async def delete_workspace(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_workspace(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -325,7 +325,7 @@ async def delete_workspace(workspace_id: int, request: Request, authorization: s
|
||||
return {"id": workspace_id, "status": "deleted"}
|
||||
|
||||
@router.get("/workspaces/{workspace_id}/members")
|
||||
async def list_workspace_members(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_workspace_members(workspace_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -400,7 +400,7 @@ async def update_member_role(workspace_id: int, uid: int, request: Request, auth
|
||||
return {"workspace_id": workspace_id, "user_id": uid, "role": role, "status": "updated"}
|
||||
|
||||
@router.delete("/workspaces/{workspace_id}/members/{uid}")
|
||||
async def remove_member(workspace_id: int, uid: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def remove_member(workspace_id: int, uid: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -419,7 +419,7 @@ async def remove_member(workspace_id: int, uid: int, request: Request, authoriza
|
||||
# ── Collections ───────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections")
|
||||
async def list_collections_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_collections_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -494,7 +494,7 @@ async def create_collection_v2(request: Request, authorization: str | None = Hea
|
||||
return JSONResponse(content=data, status_code=201)
|
||||
|
||||
@router.get("/collections/{collection_id}")
|
||||
async def get_collection_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def get_collection_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -532,7 +532,7 @@ async def patch_collection_v2(collection_id: int, request: Request, authorizatio
|
||||
return {"id": collection_id, "status": "updated"}
|
||||
|
||||
@router.delete("/collections/{collection_id}")
|
||||
async def delete_collection_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_collection_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -582,7 +582,7 @@ async def create_linked_db(collection_id: int, request: Request, authorization:
|
||||
return {"id": nid, "name": name, "status": "created"}
|
||||
|
||||
@router.post("/collections/{collection_id}/task")
|
||||
async def toggle_task(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def toggle_task(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -597,7 +597,7 @@ async def toggle_task(collection_id: int, request: Request, authorization: str |
|
||||
return {"id": collection_id, "is_task": bool(new_val)}
|
||||
|
||||
@router.get("/collections/{collection_id}/sources")
|
||||
async def list_sources(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_sources(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -631,7 +631,7 @@ async def add_source(collection_id: int, request: Request, authorization: str |
|
||||
return {"collection_id": collection_id, "source_collection_id": src_id, "status": "added"}
|
||||
|
||||
@router.delete("/collections/{collection_id}/sources/{source_id}")
|
||||
async def remove_source(collection_id: int, source_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def remove_source(collection_id: int, source_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -643,7 +643,7 @@ async def remove_source(collection_id: int, source_id: int, request: Request, au
|
||||
# ── Collection pages ──────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections/{collection_id}/pages")
|
||||
async def list_collection_pages_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_collection_pages_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -753,7 +753,7 @@ async def create_collection_page_v2(collection_id: int, request: Request, author
|
||||
return JSONResponse(content=data, status_code=201)
|
||||
|
||||
@router.get("/pages/{page_id}")
|
||||
async def get_page_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def get_page_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -881,7 +881,7 @@ async def move_page_v2(page_id: int, request: Request, authorization: str | None
|
||||
return {"id": page_id, "status": "moved"}
|
||||
|
||||
@router.get("/pages/{page_id}/sub-items")
|
||||
async def list_sub_items_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_sub_items_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -912,7 +912,7 @@ async def create_sub_item_v2(page_id: int, request: Request, authorization: str
|
||||
return {"id": nid, "status": "created"}
|
||||
|
||||
@router.get("/pages/{page_id}/dependencies")
|
||||
async def list_dependencies_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_dependencies_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -945,7 +945,7 @@ async def add_dependency_v2(page_id: int, request: Request, authorization: str |
|
||||
return {"status": "added"}
|
||||
|
||||
@router.delete("/pages/{page_id}/dependencies/{dep_id}")
|
||||
async def remove_dependency_v2(page_id: int, dep_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def remove_dependency_v2(page_id: int, dep_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -957,7 +957,7 @@ async def remove_dependency_v2(page_id: int, dep_id: int, request: Request, auth
|
||||
# ── Properties ────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections/{collection_id}/properties")
|
||||
async def list_properties_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_properties_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1016,7 +1016,7 @@ async def patch_property_v2(prop_id: int, request: Request, authorization: str |
|
||||
return {"id": prop_id, "status": "updated"}
|
||||
|
||||
@router.delete("/properties/{prop_id}")
|
||||
async def delete_property_v2(prop_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_property_v2(prop_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1093,7 +1093,7 @@ async def compute_rollup_v2(request: Request, authorization: str | None = Header
|
||||
# ── Views & dashboards ────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections/{collection_id}/views")
|
||||
async def list_views_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_views_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1157,7 +1157,7 @@ async def patch_view_v2(view_id: int, request: Request, authorization: str | Non
|
||||
return {"id": view_id, "status": "updated"}
|
||||
|
||||
@router.delete("/views/{view_id}")
|
||||
async def delete_view_v2(view_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_view_v2(view_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1188,7 +1188,7 @@ async def save_as_view_v2(view_id: int, request: Request, authorization: str | N
|
||||
return {"id": nid, "name": name, "status": "created"}
|
||||
|
||||
@router.get("/collections/{collection_id}/dashboards")
|
||||
async def list_dashboards_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_dashboards_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1234,7 +1234,7 @@ async def patch_dashboard_v2(dashboard_id: int, request: Request, authorization:
|
||||
return {"id": dashboard_id, "status": "updated"}
|
||||
|
||||
@router.delete("/dashboards/{dashboard_id}")
|
||||
async def delete_dashboard_v2(dashboard_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_dashboard_v2(dashboard_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1245,7 +1245,7 @@ async def delete_dashboard_v2(dashboard_id: int, request: Request, authorization
|
||||
# ── Comments & mentions ───────────────────────────────────────────────────
|
||||
|
||||
@router.get("/pages/{page_id}/comments")
|
||||
async def list_comments_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_comments_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -1304,7 +1304,7 @@ async def patch_comment_v2(comment_id: int, request: Request, authorization: str
|
||||
return {"id": comment_id, "status": "updated"}
|
||||
|
||||
@router.delete("/comments/{comment_id}")
|
||||
async def delete_comment_v2(comment_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_comment_v2(comment_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1349,7 +1349,7 @@ async def create_mention_v2(page_id: int, request: Request, authorization: str |
|
||||
# ── Notifications ─────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/notifications")
|
||||
async def list_notifications_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_notifications_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -1364,7 +1364,7 @@ async def list_notifications_v2(request: Request, authorization: str | None = He
|
||||
return {"notifications": [row_to_dict(r) for r in rows], "total": total, "limit": limit, "offset": offset}
|
||||
|
||||
@router.get("/notifications/unread-count")
|
||||
async def unread_count(request: Request, authorization: str | None = Header(default=None)):
|
||||
def unread_count(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1372,7 +1372,7 @@ async def unread_count(request: Request, authorization: str | None = Header(defa
|
||||
return {"unread": cnt}
|
||||
|
||||
@router.post("/notifications/{notif_id}/read")
|
||||
async def mark_read(notif_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def mark_read(notif_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1381,7 +1381,7 @@ async def mark_read(notif_id: int, request: Request, authorization: str | None =
|
||||
return {"id": notif_id, "status": "read"}
|
||||
|
||||
@router.post("/notifications/read-all")
|
||||
async def mark_all_read(request: Request, authorization: str | None = Header(default=None)):
|
||||
def mark_all_read(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1411,7 +1411,7 @@ async def patch_prefs(request: Request, authorization: str | None = Header(defau
|
||||
# ── Favorites / Tags / Recents ────────────────────────────────────────────
|
||||
|
||||
@router.get("/favorites")
|
||||
async def list_favorites_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_favorites_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1455,7 +1455,7 @@ async def remove_favorite_v2(page_id: int, request: Request, authorization: str
|
||||
return {"page_id": page_id, "status": "removed"}
|
||||
|
||||
@router.get("/tags")
|
||||
async def list_tags_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_tags_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
q = (request.query_params.get("q") or "").strip()
|
||||
@@ -1506,7 +1506,7 @@ async def patch_tag_v2(tag_id: int, request: Request, authorization: str | None
|
||||
return {"id": tag_id, "status": "updated"}
|
||||
|
||||
@router.delete("/tags/{tag_id}")
|
||||
async def delete_tag_v2(tag_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_tag_v2(tag_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1534,7 +1534,7 @@ async def attach_tag_v2(page_id: int, request: Request, authorization: str | Non
|
||||
return {"page_id": page_id, "tag_id": tag_id, "status": "attached"}
|
||||
|
||||
@router.delete("/pages/{page_id}/tags/{tag_id}")
|
||||
async def detach_tag_v2(page_id: int, tag_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def detach_tag_v2(page_id: int, tag_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1543,7 +1543,7 @@ async def detach_tag_v2(page_id: int, tag_id: int, request: Request, authorizati
|
||||
return {"status": "detached"}
|
||||
|
||||
@router.get("/recents")
|
||||
async def list_recents_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_recents_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit = int(request.query_params.get("limit", "20"))
|
||||
@@ -1558,7 +1558,7 @@ async def list_recents_v2(request: Request, authorization: str | None = Header(d
|
||||
# ── Sharing / publish ─────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/pages/{page_id}/shares")
|
||||
async def list_shares_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_shares_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1611,7 +1611,7 @@ async def patch_share_v2(share_id: int, request: Request, authorization: str | N
|
||||
return {"id": share_id, "status": "updated"}
|
||||
|
||||
@router.delete("/shares/{share_id}")
|
||||
async def delete_share_v2(share_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_share_v2(share_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1651,7 +1651,7 @@ async def unpublish_page_v2(page_id: int, request: Request, authorization: str |
|
||||
# ── History ───────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/pages/{page_id}/history")
|
||||
async def list_history_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_history_v2(page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1693,7 +1693,7 @@ async def restore_history_v2(page_id: int, request: Request, authorization: str
|
||||
# ── Sprints ───────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections/{collection_id}/sprints")
|
||||
async def list_sprints_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_sprints_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -1751,7 +1751,7 @@ async def patch_sprint_v2(sprint_id: int, request: Request, authorization: str |
|
||||
return {"id": sprint_id, "status": "updated"}
|
||||
|
||||
@router.delete("/sprints/{sprint_id}")
|
||||
async def delete_sprint_v2(sprint_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_sprint_v2(sprint_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1779,7 +1779,7 @@ async def assign_sprint_v2(sprint_id: int, request: Request, authorization: str
|
||||
return {"sprint_id": sprint_id, "page_id": pid, "status": "assigned"}
|
||||
|
||||
@router.delete("/sprints/{sprint_id}/assign/{page_id}")
|
||||
async def unassign_sprint_v2(sprint_id: int, page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def unassign_sprint_v2(sprint_id: int, page_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1788,7 +1788,7 @@ async def unassign_sprint_v2(sprint_id: int, page_id: int, request: Request, aut
|
||||
return {"status": "removed"}
|
||||
|
||||
@router.get("/sprints/{sprint_id}/burndown")
|
||||
async def burndown_v2(sprint_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def burndown_v2(sprint_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1816,7 +1816,7 @@ async def burndown_v2(sprint_id: int, request: Request, authorization: str | Non
|
||||
# ── Templates ─────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/collections/{collection_id}/templates")
|
||||
async def list_templates_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_templates_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1860,7 +1860,7 @@ async def patch_template_v2(template_id: int, request: Request, authorization: s
|
||||
return {"id": template_id, "status": "updated"}
|
||||
|
||||
@router.delete("/templates/{template_id}")
|
||||
async def delete_template_v2(template_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_template_v2(template_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1869,7 +1869,7 @@ async def delete_template_v2(template_id: int, request: Request, authorization:
|
||||
return {"id": template_id, "status": "deleted"}
|
||||
|
||||
@router.post("/templates/{template_id}/apply")
|
||||
async def apply_template_v2(template_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def apply_template_v2(template_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1884,7 +1884,7 @@ async def apply_template_v2(template_id: int, request: Request, authorization: s
|
||||
return {"template_id": template_id, "page_id": pid, "status": "applied"}
|
||||
|
||||
@router.get("/templates/database")
|
||||
async def list_db_templates_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_db_templates_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -1917,7 +1917,7 @@ async def apply_db_template_v2(template_id: int, request: Request, authorization
|
||||
# ── Export / Import ───────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/pages/{page_id}/export")
|
||||
async def export_page_v2(page_id: int, request: Request, format: str = "markdown", authorization: str | None = Header(default=None)):
|
||||
def export_page_v2(page_id: int, request: Request, format: str = "markdown", authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
fmt = (format or request.query_params.get("format") or "markdown").lower()
|
||||
@@ -1941,7 +1941,7 @@ async def export_page_v2(page_id: int, request: Request, format: str = "markdown
|
||||
raise HTTPException(500, f"Export failed: {e}") from None
|
||||
|
||||
@router.get("/collections/{collection_id}/export/csv")
|
||||
async def export_csv_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def export_csv_v2(collection_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
import csv
|
||||
@@ -2003,7 +2003,7 @@ async def import_csv_v2(collection_id: int, request: Request, authorization: str
|
||||
# ── Forges / Projects ─────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/projects")
|
||||
async def list_projects_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_projects_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -2029,7 +2029,7 @@ async def project_tree_v2(owner: str, repo: str, request: Request, path: str = "
|
||||
# ── Search (FTS5 + LIKE fallback) ─────────────────────────────────────────
|
||||
|
||||
@router.get("/search")
|
||||
async def search_v2(request: Request, query: str = "", workspace_id: int | None = None, type: str = "all", authorization: str | None = Header(default=None)):
|
||||
def search_v2(request: Request, query: str = "", workspace_id: int | None = None, type: str = "all", authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
q = (query or request.query_params.get("query") or "").strip()
|
||||
@@ -2053,7 +2053,7 @@ async def search_v2(request: Request, query: str = "", workspace_id: int | None
|
||||
# ── Admin ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@router.get("/admin/users")
|
||||
async def admin_list_users_v2(request: Request, limit: int = 30, offset: int = 0, authorization: str | None = Header(default=None)):
|
||||
def admin_list_users_v2(request: Request, limit: int = 30, offset: int = 0, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
if not user.get("is_admin") and not has_scope(user.get("_token_scopes"), "admin"):
|
||||
@@ -2092,7 +2092,7 @@ async def admin_patch_user_v2(uid: int, request: Request, authorization: str | N
|
||||
return {"id": uid, "status": "updated"}
|
||||
|
||||
@router.delete("/admin/users/{uid}")
|
||||
async def admin_delete_user_v2(uid: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def admin_delete_user_v2(uid: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
if not user.get("is_admin") and not has_scope(user.get("_token_scopes"), "admin"):
|
||||
@@ -2106,7 +2106,7 @@ async def admin_delete_user_v2(uid: int, request: Request, authorization: str |
|
||||
return {"id": uid, "status": "deleted"}
|
||||
|
||||
@router.get("/admin/audit-logs")
|
||||
async def admin_audit_logs_v2(request: Request, limit: int = 50, authorization: str | None = Header(default=None)):
|
||||
def admin_audit_logs_v2(request: Request, limit: int = 50, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
if not user.get("is_admin") and not has_scope(user.get("_token_scopes"), "admin"):
|
||||
@@ -2119,7 +2119,7 @@ async def admin_audit_logs_v2(request: Request, limit: int = 50, authorization:
|
||||
# ── Webhooks (v6.4.0 prod) ────────────────────────────────────────────────
|
||||
|
||||
@router.get("/webhooks/events")
|
||||
async def list_webhook_events_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_webhook_events_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
"""Catalogue of deliverable events (+ wildcard syntax)."""
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
@@ -2128,7 +2128,7 @@ async def list_webhook_events_v2(request: Request, authorization: str | None = H
|
||||
|
||||
|
||||
@router.get("/webhooks")
|
||||
async def list_webhooks_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
def list_webhooks_v2(request: Request, authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
limit, offset = parse_pagination(request)
|
||||
@@ -2193,7 +2193,7 @@ async def patch_webhook_v2(webhook_id: int, request: Request, authorization: str
|
||||
return {"id": webhook_id, "status": "updated"}
|
||||
|
||||
@router.delete("/webhooks/{webhook_id}")
|
||||
async def delete_webhook_v2(webhook_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
def delete_webhook_v2(webhook_id: int, request: Request, authorization: str | None = Header(default=None)):
|
||||
user = require_scope("write")(request, authorization)
|
||||
_v2_rate_check(request, user)
|
||||
with get_conn() as conn:
|
||||
@@ -2220,7 +2220,7 @@ async def test_webhook_v2(webhook_id: int, request: Request, authorization: str
|
||||
return {"webhook_id": webhook_id, "status": "tested", "delivered": ok}
|
||||
|
||||
@router.get("/webhooks/{webhook_id}/deliveries")
|
||||
async def list_deliveries_v2(webhook_id: int, request: Request,
|
||||
def list_deliveries_v2(webhook_id: int, request: Request,
|
||||
status: str | None = None,
|
||||
authorization: str | None = Header(default=None)):
|
||||
user = get_bearer_user(request, authorization)
|
||||
|
||||
Reference in New Issue
Block a user