diff --git a/backend/app/models/project.py b/backend/app/models/project.py index 807ab867..6d841298 100644 --- a/backend/app/models/project.py +++ b/backend/app/models/project.py @@ -21,10 +21,10 @@ class ProjectManager: """Gestiona projectes: metadades a BD, fitxers a StorageService.""" @classmethod - def create_project(cls, name: str = "Unnamed Project", storage=None) -> Dict[str, Any]: + def create_project(cls, name: str = "Unnamed Project", storage=None, user_id: str = None) -> Dict[str, Any]: project_id = str(uuid.uuid4()) with get_session() as db: - proj = ProjectModel(id=project_id, name=name, status="created") + proj = ProjectModel(id=project_id, name=name, status="created", user_id=user_id) db.add(proj) db.commit() db.refresh(proj) @@ -59,10 +59,12 @@ class ProjectManager: db.commit() @classmethod - def list_projects(cls, limit: int = 50) -> List[Dict[str, Any]]: + def list_projects(cls, limit: int = 50, user_id: str = None) -> List[Dict[str, Any]]: from sqlalchemy import select, desc with get_session() as db: stmt = select(ProjectModel).order_by(desc(ProjectModel.created_at)).limit(limit) + if user_id is not None: + stmt = stmt.where(ProjectModel.user_id == user_id) projects = db.execute(stmt).scalars().all() for p in projects: db.expunge(p) @@ -302,6 +304,7 @@ class ProjectManager: return { "id": proj.id, "project_id": proj.id, + "user_id": proj.user_id, "name": proj.name, "status": proj.status, "analysis_summary": proj.analysis_summary, diff --git a/backend/tests/test_project_isolation.py b/backend/tests/test_project_isolation.py new file mode 100644 index 00000000..605efb27 --- /dev/null +++ b/backend/tests/test_project_isolation.py @@ -0,0 +1,61 @@ +"""Tests d'aïllament de projectes per user_id.""" +import pytest + + +@pytest.fixture(autouse=True) +def _db(in_memory_db): + pass + + +def _make_user(email, role='user'): + from backend.app.models.db_models import UserModel + from backend.app.db import get_session + with get_session() as db: + user = UserModel(email=email, name=email, role=role, status='active') + db.add(user) + db.commit() + db.refresh(user) + return user.id + + +def test_list_projects_filtered_by_user(): + from backend.app.models.project import ProjectManager + uid1 = _make_user('u1@test.com') + uid2 = _make_user('u2@test.com') + + ProjectManager.create_project(name="U1-A", user_id=uid1) + ProjectManager.create_project(name="U1-B", user_id=uid1) + ProjectManager.create_project(name="U2-A", user_id=uid2) + + u1_projects = ProjectManager.list_projects(user_id=uid1) + assert len(u1_projects) == 2 + assert all(p['user_id'] == uid1 for p in u1_projects) + + u2_projects = ProjectManager.list_projects(user_id=uid2) + assert len(u2_projects) == 1 + assert u2_projects[0]['name'] == 'U2-A' + + +def test_list_projects_no_filter_returns_all(): + from backend.app.models.project import ProjectManager + uid1 = _make_user('all1@test.com') + uid2 = _make_user('all2@test.com') + ProjectManager.create_project(name="P1", user_id=uid1) + ProjectManager.create_project(name="P2", user_id=uid2) + all_projects = ProjectManager.list_projects(user_id=None) + assert len(all_projects) >= 2 + + +def test_create_project_assigns_user_id(): + from backend.app.models.project import ProjectManager + uid = _make_user('owner@test.com') + proj = ProjectManager.create_project(name="Owned", user_id=uid) + assert proj['user_id'] == uid + + +def test_to_dict_includes_user_id(): + from backend.app.models.project import ProjectManager + uid = _make_user('dict@test.com') + proj = ProjectManager.create_project(name="DictTest", user_id=uid) + assert 'user_id' in proj + assert proj['user_id'] == uid