fix: A3–A8 — bloc « fallback admin » de l'audit sécurité (401 sans session, ACL, CSRF)
- A3 : helper `_require_user_id()` (401 sans session) sur profile/password/token/forge ; `PUT /api/user/password` exige `current_password` vérifié ; `/api/user` sorti de la liste CSRF exemptée - A4 : `POST /api/v1/token` → 401 sans session, chemin legacy `user_id=0` supprimé - A5 : CRUD membres d'espace (POST/PUT/DELETE) : session + rôle admin de l'espace (ou admin global), placeholder user créé en `is_admin=0`, GET membres sans session → 401 - A6 : `_require_view` → 404 et `_require_edit` → 401 quand il n'y a pas de session (fin du legacy single-user sur les collections) - A7 : création ET lecture de page → 401 sans session (PermissionManager conservé) ; `/board/api/pages` sorti de `EXCLUDED_PATHS` ; header CSRF manquant ajouté sur setItemIcon (local_workspace) - A8 : seed admin sans mot de passe codé en dur — aléatoire au premier boot loggé une fois, ou `FLOWDECK_ADMIN_PASSWORD` ; re-seed seulement si absent - tests : client connecté par défaut via `_TestSessionAuth` (session + CSRF injectés à la volée, jamais dans le cookie jar → plus de CookieConflict), helper `anon()` sur les 40 tests d'anonymat ; 1016/1016 verts, `ruff check app tests` OK
This commit is contained in:
@@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from conftest import anon
|
||||
|
||||
from app.auth.session import SessionManager
|
||||
|
||||
|
||||
@@ -81,6 +83,7 @@ def test_extract_article(client):
|
||||
# ── API tests ──
|
||||
|
||||
def test_clip_requires_auth(client):
|
||||
anon(client)
|
||||
r = client.post("/api/v2/web-clipper/clip", json={"url": "https://example.com", "title": "T"})
|
||||
assert r.status_code == 401
|
||||
|
||||
@@ -225,7 +228,7 @@ def test_clip_bearer_token_auth(client):
|
||||
conn.execute("INSERT INTO api_tokens (user_id, name, token_hash, token_prefix) VALUES (?,?,?,?)", (uid, "test", th, token[:12]))
|
||||
conn.commit()
|
||||
# No session cookie
|
||||
client.cookies.clear()
|
||||
anon(client)
|
||||
r = client.post(
|
||||
"/api/v2/web-clipper/clip",
|
||||
json={"url": "https://example.com/bearer", "title": "BearerClip", "content": "<p>via bearer</p>", "device_id": "bearer-dev"},
|
||||
@@ -241,7 +244,7 @@ def test_status_and_devices_flow(client):
|
||||
uid = _insert_user("clip_status")
|
||||
_insert_workspace(uid)
|
||||
# unauth status
|
||||
client.cookies.clear()
|
||||
anon(client)
|
||||
r = client.get("/api/v2/web-clipper/status")
|
||||
assert r.status_code == 200
|
||||
assert r.json()["authenticated"] is False
|
||||
|
||||
Reference in New Issue
Block a user