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:
@@ -1777,3 +1777,52 @@ async def test_service_get_instance_not_found(db_session):
|
||||
|
||||
result = await get_instance(db_session, tenant_id, str(uuid.uuid4()))
|
||||
assert result is None
|
||||
|
||||
|
||||
# ── Cross-tenant isolation + RBAC tests ──
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_cross_tenant_workflow_isolation(client: AsyncClient, db_session):
|
||||
"""Workflow created in tenant A is not visible to tenant B."""
|
||||
from httpx import ASGITransport
|
||||
from httpx import AsyncClient as AC
|
||||
|
||||
import app.main
|
||||
|
||||
await seed_tenant_and_users(db_session)
|
||||
await login_client(client, "admin@tenanta.com")
|
||||
create_resp = await client.post(
|
||||
"/api/v1/workflows",
|
||||
json={"name": "Tenant A WF", "steps": VALID_STEPS},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert create_resp.status_code == 201
|
||||
wf_id = create_resp.json()["id"]
|
||||
|
||||
# Tenant B admin must not see tenant A's workflow
|
||||
app_instance = app.main.app
|
||||
async with AC(transport=ASGITransport(app=app_instance), base_url="http://test") as client_b:
|
||||
await login_client(client_b, "admin@tenantb.com")
|
||||
list_resp = await client_b.get("/api/v1/workflows")
|
||||
assert list_resp.status_code == 200
|
||||
assert all(w["id"] != wf_id for w in list_resp.json()["items"])
|
||||
# Direct access to tenant A's workflow → 404
|
||||
get_resp = await client_b.get(f"/api/v1/workflows/{wf_id}")
|
||||
assert get_resp.status_code == 404
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_rbac_workflow_no_permission(client: AsyncClient, db_session):
|
||||
"""User without workflows:write permission gets 403 on create."""
|
||||
from tests.conftest import create_no_perm_user
|
||||
|
||||
seed = await seed_tenant_and_users(db_session)
|
||||
await create_no_perm_user(db_session, seed)
|
||||
await login_client(client, "noperm@tenanta.com")
|
||||
resp = await client.post(
|
||||
"/api/v1/workflows",
|
||||
json={"name": "No Perm WF", "steps": VALID_STEPS},
|
||||
headers=ORIGIN_HEADER,
|
||||
)
|
||||
assert resp.status_code == 403
|
||||
|
||||
Reference in New Issue
Block a user