dingdanquanliucheng/backend/tests/test_data_isolation.py
2026-06-19 23:03:14 +08:00

175 lines
7.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""数据隔离测试 — 覆盖角色间数据可见性边界。
测试用例:
- ISO-001: 业务员订单隔离sales01 vs sales02
- ISO-002: 司机任务隔离driver01 vs driver02
- ISO-003: 业务员客户隔离
- ISO-004: 管理员看全部数据
- ISO-005: 经理看全部数据
"""
from __future__ import annotations
import pytest
@pytest.mark.p0
class TestOrderIsolation:
"""ISO-001: 业务员订单数据隔离。"""
def test_salesman_only_see_own_orders(self, client, salesman_headers, salesman2_headers, make_order):
"""sales01 创建的订单, sales02 看不到。"""
order = make_order(salesman_id=2) # sales01
# sales01 能看到
resp1 = client.get("/api/orders", headers=salesman_headers)
ids1 = [o["order_id"] for o in resp1.json()["data"]["list"]]
assert order.id in ids1
# sales02 看不到
resp2 = client.get("/api/orders", headers=salesman2_headers)
ids2 = [o["order_id"] for o in resp2.json()["data"]["list"]]
assert order.id not in ids2
def test_admin_see_all_orders(self, client, admin_headers, salesman_headers, make_order):
"""管理员能看到所有业务员的订单。"""
order = make_order(salesman_id=2)
resp = client.get("/api/orders", headers=admin_headers)
ids = [o["order_id"] for o in resp.json()["data"]["list"]]
assert order.id in ids
def test_manager_see_all_orders(self, client, manager_headers, make_order):
"""经理能看到所有订单。"""
order = make_order(salesman_id=2)
resp = client.get("/api/orders", headers=manager_headers)
ids = [o["order_id"] for o in resp.json()["data"]["list"]]
assert order.id in ids
@pytest.mark.p0
class TestTaskIsolation:
"""ISO-002: 司机任务数据隔离。"""
def test_driver_only_see_own_tasks(self, client, driver_headers, driver2_headers, make_task):
"""driver01 的任务, driver02 看不到。"""
task = make_task(driver_id=5) # driver01
# driver01 能看到
resp1 = client.get("/api/driver/tasks", headers=driver_headers)
ids1 = [t["task_id"] for t in resp1.json()["data"]["list"]]
assert task.id in ids1
# driver02 看不到
resp2 = client.get("/api/driver/tasks", headers=driver2_headers)
ids2 = [t["task_id"] for t in resp2.json()["data"]["list"]]
assert task.id not in ids2
def test_admin_see_all_tasks(self, client, admin_headers, make_task):
"""管理员能看到所有物流任务。"""
task = make_task(driver_id=5)
resp = client.get("/api/logistics/tasks", headers=admin_headers)
assert resp.status_code == 200
@pytest.mark.p0
class TestCustomerIsolation:
"""ISO-003: 业务员客户数据隔离。"""
def test_salesman_only_see_own_customers(self, client, salesman_headers, salesman2_headers, make_customer):
"""sales01 创建的客户, sales02 看不到。"""
customer = make_customer(salesman_id=2)
resp1 = client.get("/api/customers", headers=salesman_headers)
ids1 = [c["customer_id"] for c in resp1.json()["data"]["list"]]
assert customer.id in ids1
resp2 = client.get("/api/customers", headers=salesman2_headers)
ids2 = [c["customer_id"] for c in resp2.json()["data"]["list"]]
assert customer.id not in ids2
def test_admin_see_all_customers(self, client, admin_headers, make_customer):
"""管理员能看到所有客户。"""
customer = make_customer(salesman_id=2)
resp = client.get("/api/customers", headers=admin_headers)
ids = [c["customer_id"] for c in resp.json()["data"]["list"]]
assert customer.id in ids
def test_manager_see_all_customers(self, client, manager_headers, make_customer):
"""经理能看到所有客户。"""
customer = make_customer(salesman_id=2)
resp = client.get("/api/customers", headers=manager_headers)
ids = [c["customer_id"] for c in resp.json()["data"]["list"]]
assert customer.id in ids
@pytest.mark.p0
class TestOrderDetailIsolation:
"""订单详情字段级权限隔离。"""
def test_salesman_detail_hides_finance(self, client, salesman_headers, make_order):
"""业务员看订单详情, 隐藏成本和利润字段。"""
order = make_order(salesman_id=2)
resp = client.get(f"/api/orders/{order.id}", headers=salesman_headers)
data = resp.json()["data"]
# 业务员不应看到成本价和利润率
assert data.get("cost_price_total") is None or data.get("cost_price_total") == 0
def test_manager_detail_shows_finance(self, client, manager_headers, make_order):
"""经理看订单详情, 显示成本和利润字段。"""
order = make_order(salesman_id=2)
resp = client.get(f"/api/orders/{order.id}", headers=manager_headers)
data = resp.json()["data"]
# 经理应能看到利润信息
assert "profit_total" in data or "profit_rate" in data
def test_driver_detail_hides_finance(self, client, driver_headers, make_task):
"""司机看任务详情, 隐藏财务信息。"""
task = make_task(driver_id=5)
resp = client.get(f"/api/driver/tasks/{task.id}", headers=driver_headers)
data = resp.json()["data"]
# 司机不应看到价格信息
assert data.get("sale_price") is None
assert data.get("cost_price") is None
@pytest.mark.p0
class TestPermissionBoundary:
"""权限边界测试 — 各角色不能越权操作。"""
def test_salesman_cannot_approve(self, client, salesman_headers, make_order):
"""业务员不能审批订单。"""
order = make_order(order_status="pending_approve", salesman_id=2)
resp = client.post(f"/api/orders/{order.id}/approve", headers=salesman_headers, json={
"approve_result": "pass",
})
assert resp.status_code == 403
def test_salesman_cannot_create_logistics_task(self, client, salesman_headers, make_order):
"""业务员不能创建物流任务。"""
order = make_order(order_status="approved", salesman_id=2)
resp = client.post("/api/logistics/tasks", headers=salesman_headers, json={
"order_id": order.id,
"driver_id": 5,
"pickup_address": "工厂",
"delivery_address": "仓库",
})
assert resp.status_code == 403
def test_driver_cannot_approve(self, client, driver_headers, make_order):
"""司机不能审批订单。"""
order = make_order(order_status="pending_approve")
resp = client.post(f"/api/orders/{order.id}/approve", headers=driver_headers, json={
"approve_result": "pass",
})
assert resp.status_code == 403
def test_driver_cannot_view_reports(self, client, driver_headers):
"""司机不能查看报表。"""
resp = client.get("/api/reports/performance", headers=driver_headers)
assert resp.status_code == 403
def test_salesman_cannot_manage_system(self, client, salesman_headers):
"""业务员不能访问系统管理。"""
resp = client.get("/api/system/users", headers=salesman_headers)
assert resp.status_code == 403
def test_manager_cannot_manage_users(self, client, manager_headers):
"""经理不能管理用户。"""
resp = client.post("/api/system/users", headers=manager_headers, json={
"username": "test", "password": "test123", "role_id": 2,
})
assert resp.status_code == 403