""""Mes assets" (voir plan Phase 1, §2) — bibliothèque d'images PAR COMPTE, distincte du dossier d'un jeu (routes/uploads/upload_file.py) : réutilisable d'un projet à l'autre du MÊME compte, jamais visible par un autre.""" import io import auth def test_create_and_list_user_asset(client): with client.session_transaction() as sess: user_id = sess["user_id"] asset_id = auth.create_user_asset(user_id, "abc123.png", original_name="photo.png", source="upload") assets = auth.list_user_assets(user_id) assert any(a["id"] == asset_id and a["filename"] == "abc123.png" for a in assets) def test_list_user_assets_is_isolated_per_account(client, user_client): with client.session_transaction() as sess: admin_id = sess["user_id"] with user_client.session_transaction() as sess: user_id = sess["user_id"] auth.create_user_asset(admin_id, "admin_only.png") assets = auth.list_user_assets(user_id) assert all(a["filename"] != "admin_only.png" for a in assets) def test_get_user_asset_returns_none_for_unknown_id(): assert auth.get_user_asset(999999) is None def test_delete_user_asset_refuses_when_not_the_owner(client, user_client): with client.session_transaction() as sess: admin_id = sess["user_id"] with user_client.session_transaction() as sess: user_id = sess["user_id"] asset_id = auth.create_user_asset(admin_id, "admin_only.png") assert auth.delete_user_asset(asset_id, user_id) is False assert auth.get_user_asset(asset_id) is not None def test_upload_user_asset_route_stores_the_file_and_returns_a_url(client): resp = client.post( "/assets/upload", data={"file": (io.BytesIO(b"fake-image-bytes"), "photo.png")}, content_type="multipart/form-data", ) assert resp.status_code == 200 body = resp.get_json() assert body["id"] assert "/assets/" in body["url"] dl = client.get(body["url"]) assert dl.status_code == 200 assert dl.data == b"fake-image-bytes" def test_upload_user_asset_route_requires_a_file(client): resp = client.post("/assets/upload", data={}, content_type="multipart/form-data") assert resp.status_code == 400 def test_serve_user_asset_route_403s_for_another_account(client, user_client): # Un compte "user" fraîchement inscrit (sans projet) est redirigé vers # l'onboarding pour toute route hors _REACHABLE_WITHOUT_PROJECT (voir # core/auth_guard.py) — lui assigner un projet ici isole ce test sur # le SEUL comportement qu'on veut vérifier : l'isolation par # propriétaire de "Mes assets", pas le parcours d'onboarding. with user_client.session_transaction() as sess: other_user_id = sess["user_id"] auth.set_project_slug(other_user_id, "pytest_dummy_project") resp = client.post( "/assets/upload", data={"file": (io.BytesIO(b"fake-image-bytes"), "photo.png")}, content_type="multipart/form-data", ) url = resp.get_json()["url"] resp2 = user_client.get(url) assert resp2.status_code == 403