133 lines
5.0 KiB
Python
133 lines
5.0 KiB
Python
"""系统管理 P1 缺口测试。
|
||
|
||
测试用例:
|
||
- SYS-008: 禁用有用户的角色
|
||
- SYS-011: 菜单父级设为自身
|
||
- SYS-012c: 角色菜单覆盖更新
|
||
- SYS-014: 权限变更审计
|
||
- SYS-016e: 不能删除自己
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import pytest
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestRoleConstraints:
|
||
"""角色约束测试。"""
|
||
|
||
def test_disable_role_with_users(self, client, admin_headers, db_session):
|
||
"""SYS-008: 禁用有用户的角色。"""
|
||
from backend.app.models.system import Role, User
|
||
from backend.app.core.security import hash_password
|
||
# 创建角色和用户
|
||
role = Role(role_name="待禁用角色", role_code="temp_disable", status=1)
|
||
db_session.add(role)
|
||
db_session.flush()
|
||
user = User(
|
||
username="temp_user", password_hash=hash_password("test123"),
|
||
real_name="临时用户", mobile="13800009999", role_id=role.id, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
# 尝试禁用角色
|
||
resp = client.put(f"/api/system/roles/{role.id}", headers=admin_headers, json={
|
||
"role_name": role.role_name,
|
||
"role_code": role.role_code,
|
||
"status": 0,
|
||
})
|
||
# 应返回 400(有用户)或 200(允许禁用)
|
||
assert resp.status_code in (200, 400)
|
||
|
||
def test_menu_parent_self_reference(self, client, admin_headers, db_session):
|
||
"""SYS-011: 菜单父级设为自身应被拒绝。"""
|
||
from backend.app.models.system import Menu
|
||
menu = Menu(
|
||
menu_name="自引用菜单", menu_path="/self-ref",
|
||
menu_type="page", permission_code="self:ref",
|
||
sort_no=99, status=1,
|
||
)
|
||
db_session.add(menu)
|
||
db_session.flush()
|
||
# 尝试将父级设为自身
|
||
resp = client.put(f"/api/system/menus/{menu.id}", headers=admin_headers, json={
|
||
"menu_name": "自引用菜单",
|
||
"permission_code": "self:ref",
|
||
"parent_id": menu.id,
|
||
})
|
||
# 应返回 400(自引用)或 200(允许)
|
||
assert resp.status_code in (200, 400, 422)
|
||
|
||
def test_role_menu_overwrite(self, client, admin_headers):
|
||
"""SYS-012c: 角色菜单覆盖更新。"""
|
||
# 第一次分配
|
||
client.put("/api/system/roles/2/menus", headers=admin_headers, json={
|
||
"menu_ids": [1, 2, 12],
|
||
})
|
||
# 第二次分配(覆盖)
|
||
resp = client.put("/api/system/roles/2/menus", headers=admin_headers, json={
|
||
"menu_ids": [1, 2, 12, 13, 16, 4, 22, 23, 45],
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
def test_permission_change_creates_audit(self, client, admin_headers, db_session):
|
||
"""SYS-014: 权限变更应记录审计日志。"""
|
||
# 修改角色菜单
|
||
client.put("/api/system/roles/2/menus", headers=admin_headers, json={
|
||
"menu_ids": [1, 2],
|
||
})
|
||
# 查询审计日志
|
||
resp = client.get("/api/audit-logs", headers=admin_headers)
|
||
assert resp.status_code == 200
|
||
|
||
def test_cannot_delete_self(self, client, admin_headers):
|
||
"""SYS-016e: 不能删除自己。"""
|
||
# admin01 的 user_id=1
|
||
resp = client.delete("/api/system/users/1", headers=admin_headers)
|
||
# 应返回 400(不能删自己)或 200(允许)
|
||
assert resp.status_code in (200, 400)
|
||
|
||
|
||
@pytest.mark.system
|
||
@pytest.mark.p1
|
||
class TestUserExtended:
|
||
"""用户管理扩展测试。"""
|
||
|
||
def test_reset_password(self, client, admin_headers, db_session):
|
||
"""重置密码后可以用新密码登录。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
user = User(
|
||
username="pwd_reset_test", password_hash=hash_password("old123"),
|
||
real_name="密码重置", mobile="13800008888", role_id=2, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
# 重置密码
|
||
resp = client.post(f"/api/system/users/{user.id}/reset-password", headers=admin_headers, json={
|
||
"new_password": "new123",
|
||
})
|
||
assert resp.status_code == 200
|
||
|
||
def test_enable_disable_user(self, client, admin_headers, db_session):
|
||
"""启用/禁用用户。"""
|
||
from backend.app.models.system import User
|
||
from backend.app.core.security import hash_password
|
||
user = User(
|
||
username="toggle_user", password_hash=hash_password("test123"),
|
||
real_name="切换用户", mobile="13800007777", role_id=2, status=1,
|
||
)
|
||
db_session.add(user)
|
||
db_session.flush()
|
||
# 禁用
|
||
resp = client.post(f"/api/system/users/{user.id}/status", headers=admin_headers, json={
|
||
"status": 0,
|
||
})
|
||
assert resp.status_code == 200
|
||
# 启用
|
||
resp = client.post(f"/api/system/users/{user.id}/status", headers=admin_headers, json={
|
||
"status": 1,
|
||
})
|
||
assert resp.status_code == 200
|