Files
site_aegisone/py_service/tests/test_02_session_role_switch.py
angel bd048ea23d v1.5.4: test infrastructure + bug fixes + CI/CD + deploy gate
- 6 new test files: route discovery, strict permissions, role switch,
  CRUD operations, 500 error protection
- permission_config.py: central permission definitions for all 110+ routes
- Bug fixes: is_active checkbox in users_edit, int(id) 500 crash,
  missing validation in users_create/users_delete
- Pre-commit hooks: lint + static routing tests
- GitHub Actions CI: full pytest suite on push
- Deploy gate: pytest runs before deploy, aborts on failure
- All 3 deploy scripts: --skip-tests flag support
2026-05-22 20:45:27 +03:00

143 lines
4.7 KiB
Python

"""Test role switching lifecycle — owner→engineer→reset, etc.
These tests verify that the session remains consistent after role switches.
The critical check: after a reset, the original role's access is fully restored.
"""
import httpx
from tests.conftest import SERVER_URL, PASSWORD
class TestRoleSwitch:
def _login(self, role: str) -> httpx.Client:
"""Create a fresh authenticated client."""
c = httpx.Client(base_url=SERVER_URL, follow_redirects=False, timeout=10)
resp = c.post("/service/login", data={"login": role, "password": PASSWORD})
assert resp.status_code == 302
return c
def _switch_role(self, client: httpx.Client, target: str):
resp = client.post("/service/api/role/switch", json={"role": target})
assert resp.status_code == 200
data = resp.json()
assert data["ok"] is True
return data
def _reset_role(self, client: httpx.Client):
resp = client.post("/service/api/role/reset")
assert resp.status_code == 200
data = resp.json()
assert data["ok"] is True
return data
def test_owner_to_engineer_and_back(self):
"""Owner switches to engineer, then resets — full access restored."""
client = self._login("owner")
# Owner can access owner pages
r = client.get("/service/users")
assert r.status_code == 200
# Switch to engineer
data = self._switch_role(client, "engineer")
assert data["role"] == "engineer"
assert data["original_role"] == "owner"
# Engineer cannot access owner pages
r = client.get("/service/users")
assert r.status_code == 403, "Engineer should be denied owner pages"
# Engineer CAN access shared pages
r = client.get("/service/customers")
assert r.status_code == 200
# Reset to owner
data = self._reset_role(client)
assert data["role"] == "owner"
# CRITICAL: Owner access restored
r = client.get("/service/users")
assert r.status_code == 200, "Owner access not restored after reset!"
# Dashboard still works
r = client.get("/service/dashboard")
assert r.status_code == 200
def test_owner_to_technician_and_back(self):
"""Owner switches directly to technician."""
client = self._login("owner")
r = client.get("/service/users")
assert r.status_code == 200
self._switch_role(client, "technician")
r = client.get("/service/users")
assert r.status_code == 403
r = client.get("/service/tasks")
assert r.status_code == 200
self._reset_role(client)
r = client.get("/service/users")
assert r.status_code == 200
def test_engineer_to_technician_and_back(self):
"""Engineer switches to technician, then resets."""
client = self._login("engineer")
# Engineer can access engineer pages
r = client.get("/service/customers")
assert r.status_code == 200
self._switch_role(client, "technician")
# Technician cannot access engineer pages
r = client.get("/service/customers")
assert r.status_code == 403
r = client.get("/service/checklist")
assert r.status_code == 200
self._reset_role(client)
# Engineer access restored
r = client.get("/service/customers")
assert r.status_code == 200
def test_double_switch_owner_engineer_technician_then_reset(self):
"""Multi-step: owner→engineer→technician→reset→owner."""
client = self._login("owner")
self._switch_role(client, "engineer")
r = client.get("/service/users")
assert r.status_code == 403
# Switch deeper while already impersonating
self._switch_role(client, "technician")
r = client.get("/service/users")
assert r.status_code == 403
r = client.get("/service/tasks")
assert r.status_code == 200
# Single reset should restore owner
self._reset_role(client)
r = client.get("/service/users")
assert r.status_code == 200
def test_forbidden_switch_technician_cannot_switch(self):
"""Technician cannot use role switch (not in allowed_roles)."""
client = self._login("technician")
resp = client.post("/service/api/role/switch", json={"role": "owner"})
assert resp.status_code == 403
def test_reset_without_switch_does_not_error(self):
"""Reset without an active override should still work."""
client = self._login("owner")
resp = client.post("/service/api/role/reset")
assert resp.status_code == 200
data = resp.json()
assert data["role"] == "owner"