feat(audit): P1 cross-tenant/RBAC tests, P3 test fixes, P2/P3 frontend fixes
Check Cross-Plugin Imports / check (push) Has been cancelled
Check Cross-Plugin Imports / check (push) Has been cancelled
- P1-Tests: 12 test files with new cross-tenant isolation + RBAC tests - P3-Tests: 8 fixes (duplicate fixtures, sys.path.insert, unused imports, KeyError) - P3-Frontend: LucideIcons → ICON_MAP (2 files), inline styles → Tailwind (2 files) - P3-Frontend: DOMPurify for iframe XSS, redundant regex removed, console.log → console.debug - P2-Frontend: 2 notification API TODOs retained (requires larger refactor) - conftest.py: create_no_perm_user helper added - pyproject.toml: pythonpath for scripts/ added - All checks green: ruff 0, F821 0, tsc 0, app 495 routes, cross-plugin 0
This commit is contained in:
@@ -351,3 +351,45 @@ class TestCompanyAuditAndSoftDelete:
|
||||
names = [item["name"] for item in list_resp.json()["items"]]
|
||||
assert "SoftDelete Corp" not in names
|
||||
assert "Company Alpha" in names # Seed company still present
|
||||
|
||||
|
||||
# ── Visibility filter test ──
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
class TestCompanyVisibilityFilter:
|
||||
"""Row-level visibility filter hides non-owned, non-shared companies."""
|
||||
|
||||
async def test_visibility_filter_hides_owned_company_from_viewer(self, client: AsyncClient, db_session):
|
||||
"""A company owned by admin_a is not visible to viewer_a in the contacts list."""
|
||||
await seed_tenant_and_users(db_session)
|
||||
await login_client(client, "admin@tenanta.com")
|
||||
# Create a company via /api/v1/contacts so owner_id is set to admin_a
|
||||
create_resp = await client.post(
|
||||
"/api/v1/contacts",
|
||||
json={"type": "company", "name": "Owned Corp", "displayname": "Owned Corp"},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert create_resp.status_code == 201
|
||||
owned_id = create_resp.json()["id"]
|
||||
|
||||
# Admin (owner) sees it in the contacts list with type=company
|
||||
list_resp = await client.get("/api/v1/contacts?type=company", headers=ORIGIN_HEADER)
|
||||
assert list_resp.status_code == 200
|
||||
assert any(c["id"] == owned_id for c in list_resp.json()["items"])
|
||||
|
||||
# Viewer (non-owner, not shared) must NOT see it
|
||||
await login_client(client, "viewer@tenanta.com")
|
||||
viewer_list = await client.get("/api/v1/contacts?type=company", headers=ORIGIN_HEADER)
|
||||
assert viewer_list.status_code == 200
|
||||
assert all(c["id"] != owned_id for c in viewer_list.json()["items"])
|
||||
|
||||
async def test_visibility_filter_shows_tenant_owned_company(self, client: AsyncClient, db_session):
|
||||
"""A tenant-owned company (owner_id NULL) is visible to all users with read permission."""
|
||||
await seed_tenant_and_users(db_session)
|
||||
await login_client(client, "viewer@tenanta.com")
|
||||
# Seed company 'Company Alpha' has owner_id NULL → tenant-owned → visible to viewer
|
||||
list_resp = await client.get("/api/v1/contacts?type=company", headers=ORIGIN_HEADER)
|
||||
assert list_resp.status_code == 200
|
||||
names = [c["name"] for c in list_resp.json()["items"]]
|
||||
assert "Company Alpha" in names
|
||||
|
||||
Reference in New Issue
Block a user