diff --git a/backend/tests/test_security_review_blockers.py b/backend/tests/test_security_review_blockers.py index 7cb4017..8b5b90c 100644 --- a/backend/tests/test_security_review_blockers.py +++ b/backend/tests/test_security_review_blockers.py @@ -1285,3 +1285,82 @@ def test_malformed_visibility_legacy_syntax_not_migrated(client, user_store, log from app.services.groups import resolved_visibility assert resolved_visibility({"visibility": "evil", "owner_user_id": "x"}) is None + + +def test_delete_group_cascades_sessions_and_keeps_other_org_sessions( + client, user_store, login +): + """Deleting a product removes the group, its personas (stored in the group), + its own sessions, and uploaded filenames — but not sessions of another group.""" + # Admin in org-default + admin_token = _setup_admin(user_store, login) + _create_user(user_store, login, username="trainee-delete-cascade", org_id="org-default") + + groups = client.application.extensions["group_store"] + sess = client.application.extensions["session_store"] + + # Build a ready product (group) directly with one persona. + g = groups.create( + org_id="org-default", + creator_id="admin", + title="Cascade test product", + status="ready", + input_data={"files": ["upload-a.pdf"]}, + sales_kit={"productName": "Cascade product"}, + report={"summary": "Cascade report"}, + personas=[{"id": "p-1", "name": "Persona One", "tier": "A"}], + ) + gid = g["id"] + + # A real session (chat) bound to this product + same org. + sess.sessions.create({ + "id": "sess-p1", + "org_id": "org-default", + "user_id": "trainee-delete-cascade", + "group_id": gid, + "persona_id": "p-1", + "persona_name": "Persona One", + "mode": "trainee", + "status": "finished", + "outcome": "won", + "debrief": {"score": 80}, + }, key="sess-p1") + + # A session of ANOTHER (different) group that must survive. + g2 = groups.create( + org_id="org-default", + creator_id="admin", + title="Other product", + status="ready", + sales_kit={"productName": "Other"}, + report={"summary": "R"}, + personas=[{"id": "p-x", "name": "Persona X", "tier": "B"}], + ) + sess.sessions.create({ + "id": "sess-x", + "org_id": "org-default", + "user_id": "trainee-delete-cascade", + "group_id": g2["id"], + "persona_id": "p-x", + "persona_name": "Persona X", + "mode": "trainee", + "status": "finished", + "outcome": "lost", + }, key="sess-x") + + # Sanity: product + its session + other session exist before delete. + assert groups.get_or_none(gid) is not None + assert sess.sessions.get_or_none("sess-p1") is not None + assert sess.sessions.get_or_none("sess-x") is not None + + # Delete the product via the API (admin). + resp = client.delete(f"/api/groups/{gid}", headers=_headers(admin_token)) + assert resp.status_code == 200, resp.get_json() + + # Product + its personas (group) and its own session are gone. + assert groups.get_or_none(gid) is None + assert sess.sessions.get_or_none("sess-p1") is None + # An unrelated session survives. + assert sess.sessions.get_or_none("sess-x") is not None + # Other product survives. + assert groups.get_or_none(g2["id"]) is not None