fix: un dossier perso n'est plus visible par les autres comptes #194
CI / lint (push) Successful in 2m57s
CI / security (push) Successful in 1m40s
CI / test (push) Successful in 4m39s
CI / build (push) Successful in 1m34s
CI / e2e (push) Successful in 17m44s

L'admin (vaults: ["*"]) voyait le home de chaque utilisateur dans sa
barre latérale : "*" ouvrait tous les vaults, home-* compris.

- backend/auth/middleware.py : check_vault_access exige un octroi
  explicite pour tout vault home-* (nouveau is_home_vault()).
- Filtres « * » en dur remplacés par check_vault_access : dashboard,
  conflits, liens retour, favoris, abonnements push.
- /api/search : search_vaults(is_allowed=…) filtre les bruts avant
  pagination (total et page restent justes).
- backend/user_home.py : _grant n'écarte plus les comptes « * » —
  l'admin reçoit son propre home-admin (auto-réparé au démarrage).
- Tests : test_user_home.py +2, assertion API inversée dans
  test_auth_api.py (admin ne voit plus home-alice).
This commit is contained in:
2026-10-10 16:42:00 -04:00
parent 10453d8dfe
commit 8662d23ec8
23 changed files with 152 additions and 39 deletions
+5 -2
View File
@@ -514,8 +514,11 @@ class TestUserHome:
assert (home / "alice").is_dir()
names = [v["name"] for v in auth_client.get("/api/vaults", headers=admin).json()]
assert "home-alice" in names
# L'octroi atterrit bien dans le user → visible dans son JWT/liste de vaults
# #194 : « * » n'inclut pas les dossiers persos — l'admin ne voit pas
# le home d'alice (il ne verrait sinon celui de chaque utilisateur).
assert "home-alice" not in names
assert "TestVault" in names
# L'octroi atterrit bien dans le user
assert "home-alice" in resp.json()["vaults"]
# Isolation : alice ne voit QUE son propre dossier
+42
View File
@@ -191,6 +191,48 @@ class TestIsolation:
assert check_vault_access("home-alice", get_user("bob")) is False
assert check_vault_access("home-bob", get_user("alice")) is False
def test_wildcard_admin_does_not_cover_homes(self, home_env):
"""#194 : « * » n'inclut JAMAIS un dossier perso, même pour l'admin."""
from backend.auth.middleware import check_vault_access
from backend.auth.user_store import create_user, get_user
from backend.user_home import ensure_user_home
create_user("root", "Motdepasse1!", role="admin", vaults=["*"])
_create_user("alice")
_run(ensure_user_home("alice"))
admin = get_user("root")
assert check_vault_access("home-alice", admin) is False # pas le sien
assert check_vault_access("TestVault", admin) is True # « * » intact
# L'octroi explicite suffit (y compris pour l'admin, cf. _grant)
_run(ensure_user_home("root"))
assert check_vault_access("home-root", get_user("root")) is True
class TestSearchFiltering:
def test_search_service_filters_before_pagination(self, monkeypatch):
"""#194 : /api/search ne doit pas renvoyer les notes d'un autre user."""
import backend.search as search_mod
from backend.services import search as search_service
hits = [
{"vault": "home-bruno", "path": "secret.md"},
{"vault": "TestVault", "path": "note.md"},
{"vault": "home-bruno", "path": "autre.md"},
]
monkeypatch.setattr(
search_mod, "search",
lambda q, vault_filter="all", tag_filter=None: list(hits),
)
page = search_service.search_vaults("x", limit=50, is_allowed=lambda v: v == "TestVault")
assert page["total"] == 1, "total = résultats filtrés"
assert [r["vault"] for r in page["results"]] == ["TestVault"]
# Sans filtre (tool layer, qui filtre lui-même) : inchangé.
assert search_service.search_vaults("x", limit=50)["total"] == 3
class TestEnsureAll:
def test_repairs_every_existing_user(self, home_env):