"""Real-Postgres proof that a write is traced to the project it lands in. Two projects of one user: the session's own and another. Each locator kind is resolved from a real row, and check_act answers for a session standing in the first. """ import pytest import pytest_asyncio from sqlalchemy import select from grimoire.models import async_session from grimoire.models.milestone import Milestone from grimoire.models.note import Note from grimoire.models.project import Project from grimoire.models.system import System from grimoire.services import write_scope from tests.helpers import ensure_user pytestmark = [pytest.mark.integration, pytest.mark.usefixtures("_dispose_engine")] OWNER = "write_scope_owner" BATCH = "write-scope-test-batch" @pytest_asyncio.fixture async def two_projects(): async with async_session() as s: user = await ensure_user(s, OWNER) for model in (Note, Milestone, System, Project): for row in (await s.execute(select(model).where(model.user_id == user.id))).scalars(): await s.delete(row) await s.flush() home = Project(user_id=user.id, title="Home") other = Project(user_id=user.id, title="Elsewhere") s.add_all([home, other]) await s.flush() plan = Milestone(user_id=user.id, project_id=other.id, title="Their plan") area = System(user_id=user.id, project_id=other.id, name="Their area") s.add_all([plan, area]) await s.flush() theirs = Note(user_id=user.id, project_id=other.id, milestone_id=plan.id, title="Their task", body="", note_type="note", task_kind="work", status="todo") mine = Note(user_id=user.id, project_id=home.id, title="My task", body="", note_type="note", task_kind="work", status="todo") trashed = Note(user_id=user.id, project_id=other.id, title="Trashed", body="", note_type="note", deleted_batch_id=BATCH) s.add_all([theirs, mine, trashed]) await s.commit() return {"user": user.id, "home": home.id, "other": other.id, "plan": plan.id, "area": area.id, "theirs": theirs.id, "mine": mine.id} async def test_each_locator_finds_the_project_of_the_row_it_names(two_projects): ids = two_projects other, home, uid = ids["other"], ids["home"], ids["user"] async def lands(tool, **args): return await write_scope.tool_targets(uid, tool, args) assert await lands("add_task_log", task_id=ids["theirs"]) == {other} assert await lands("update_task", task_id=ids["mine"]) == {home} assert await lands("update_task", task_id=ids["mine"], milestone_id=ids["plan"]) == {home, other} assert await lands("delete_milestone", milestone_id=ids["plan"]) == {other} assert await lands("update_system", system_id=ids["area"]) == {other} assert await lands("restore", deleted_batch_id=BATCH) == {other} assert await lands("create_rule", topic_id=1) == set() async def test_a_session_in_one_project_is_asked_before_writing_in_the_other(two_projects): ids = two_projects uid, home, other = ids["user"], ids["home"], ids["other"] own = await write_scope.check_act(uid, home, tool="add_task_log", args={"task_id": ids["mine"]}) assert own["allowed"] is True theirs = await write_scope.check_act(uid, home, tool="add_task_log", args={"task_id": ids["theirs"]}) assert theirs["allowed"] is False assert theirs["targets"] == [{"id": other, "title": "Elsewhere"}] assert "Home" in theirs["reason"] and "Elsewhere" in theirs["reason"] issue = await write_scope.check_act(uid, home, tool="create_task", args={"project_id": other, "kind": "issue"}) assert issue["allowed"] is True and issue["issue"] is True