\Tests\FeatureDataScopeServiceTest

数据范围推导

被测对象:DataScopeService(visibleDeptIds/isExempt/apply)与 UserConfigService/ConfigRoleService/ConfigPostService 的高危防护路径 守护约定:岗位范围 ∪ 个人范围 ∪ 负责人部门推导;超管/豁免角色/超级管理员岗位全见豁免; 超级管理员岗位任职、角色/岗位锚点防伪、个人范围自扩保护、停用规则等安全红线。

Summary

Methods
Properties
Constants
test_explicit_org_scope()
test_explicit_dept_scope()
test_personal_scope_company_wide()
test_personal_scope_dept()
test_leader_sees_own_dept_subtree()
test_inactive_dept_excluded()
test_exempt_users()
test_super_post_exempts_member()
test_regular_post_not_exempt()
test_super_post_assignment_blocked_for_non_super()
test_super_post_assignment_allowed_for_super()
test_super_post_rejects_dept_id()
test_apply_filters_by_visible_users()
test_disabled_post_scope_not_expanded()
test_leader_visibility_independent_of_post_status()
test_disabled_company_org_scope_excluded()
test_disabled_company_personal_company_wide_excluded()
test_dept_ids_for_user_scopes_reflects_items()
test_self_scope_expansion_blocked()
test_self_scope_unchanged_allowed()
test_sync_user_roles_exempt_blocked_for_non_super()
test_sync_user_roles_target_visibility_enforced()
test_sync_user_roles_exempt_allowed_for_super()
test_role_create_super_code_blocked()
test_role_update_to_super_code_blocked()
test_super_role_exempt_cannot_be_removed()
test_post_create_super_code_blocked()
test_self_scope_expansion_by_empty_dept_blocked()
test_self_membership_expansion_by_empty_dept_blocked()
test_post_scope_rejects_inactive_dept()
test_personal_scope_rejects_inactive_dept()
test_sync_user_roles_keep_exempt_role_allowed()
test_update_cannot_disable_super()
test_update_cannot_disable_self()
test_batch_cannot_disable_self()
test_super_post_scope_sync_blocked()
test_post_scope_rejects_inactive_company()
test_led_dept_names()
test_led_dept_names_empty()
test_post_user_groups()
test_scope_isolation_no_cross_user_leak()
No public properties found
No constants found
requireRedis()
buildCacheRegistry()
setUp()
No protected properties found
N/A
buildSchema()
seedData()
makeUser()
addMembership()
addPostScope()
sortedVisible()
$company
$root
$child
$grand
$post
$userA
$userB
N/A

Properties

$company

$company : \App\Models\SysCompany

Type

SysCompany

$root

$root : \App\Models\SysDept

Type

SysDept

$child

$child : \App\Models\SysDept

Type

SysDept

$grand

$grand : \App\Models\SysDept

Type

SysDept

$post

$post : \App\Models\SysPost

Type

SysPost

$userA

$userA : \App\Models\SysUser

Type

SysUser

$userB

$userB : \App\Models\SysUser

Type

SysUser

Methods

test_explicit_org_scope()

test_explicit_org_scope() : void

显式组织 MODE_ORG:整组织全部启用部门(与任职部门无关)

test_explicit_dept_scope()

test_explicit_dept_scope() : void

显式末级部门 MODE_DEPT:仅叶子部门本身(不含下级,末级即自身)

test_personal_scope_company_wide()

test_personal_scope_company_wide() : void

个人范围(无任职):dept_id=0 整组织

test_personal_scope_dept()

test_personal_scope_dept() : void

个人范围(部门级):该部门子树

test_leader_sees_own_dept_subtree()

test_leader_sees_own_dept_subtree() : void

负责人 is_leader=1:自动全见本部门(含下级),独立于岗位范围

test_inactive_dept_excluded()

test_inactive_dept_excluded() : void

停用部门从可见集剔除

test_exempt_users()

test_exempt_users() : void

豁免:超管与直授豁免角色 → 全见;任职超级管理员岗位 → 全见;普通用户不豁免

test_super_post_exempts_member()

test_super_post_exempts_member() : void

豁免:任职内置超级管理员岗位(code=super)→ 全见(替代原岗位 is_exempt 开关)

test_regular_post_not_exempt()

test_regular_post_not_exempt() : void

豁免:任职普通岗位不豁免(与 super 岗位区分)

test_super_post_assignment_blocked_for_non_super()

test_super_post_assignment_blocked_for_non_super() : void

任职拦截(高危防护):非超管为他人任职超级管理员岗位 → 403(防制造全见用户提权)

test_super_post_assignment_allowed_for_super()

test_super_post_assignment_allowed_for_super() : void

任职放行:超管可为他人任职超级管理员岗位(全局 dept_id=0,负责人强制 0)

test_super_post_rejects_dept_id()

test_super_post_rejects_dept_id() : void

任职校验:超级管理员岗位不挂部门,非 0 dept_id 拒绝

test_apply_filters_by_visible_users()

test_apply_filters_by_visible_users() : void

apply 追加过滤:非豁免只可见范围内用户;豁免全见

test_disabled_post_scope_not_expanded()

test_disabled_post_scope_not_expanded() : void

停用岗位:其范围行不参与展开(与权限侧 resolveUserRoleIds 的 status=1 同规)

test_leader_visibility_independent_of_post_status()

test_leader_visibility_independent_of_post_status() : void

负责人可见性独立于岗位启停(is_leader 不依赖岗位范围)

test_disabled_company_org_scope_excluded()

test_disabled_company_org_scope_excluded() : void

停用公司:显式组织(MODE_ORG)不再展开(停用即回收,与停用部门同规)

test_disabled_company_personal_company_wide_excluded()

test_disabled_company_personal_company_wide_excluded() : void

停用公司:个人范围整组织(dept_id=0)不再展开

test_dept_ids_for_user_scopes_reflects_items()

test_dept_ids_for_user_scopes_reflects_items() : void

deptIdsForUserScopes:按提交 items 推导可见部门集(任职取当前值)——自扩可被检测

test_self_scope_expansion_blocked()

test_self_scope_expansion_blocked() : void

个人范围自我保护(高危修复):非豁免操作者给自己配扩大范围 → 403

test_self_scope_unchanged_allowed()

test_self_scope_unchanged_allowed() : void

个人范围自我保护:持平提交(未扩大)→ 正常覆盖保存

test_sync_user_roles_exempt_blocked_for_non_super()

test_sync_user_roles_exempt_blocked_for_non_super() : void

角色直授防线:非超管给可见用户授予豁免角色 → 403(防自挂/互挂豁免绕过数据范围)

test_sync_user_roles_target_visibility_enforced()

test_sync_user_roles_target_visibility_enforced() : void

角色直授防线:非豁免操作者给范围外用户授角色 → 403(目标可见性)

test_sync_user_roles_exempt_allowed_for_super()

test_sync_user_roles_exempt_allowed_for_super() : void

角色直授防线:超管给用户授予豁免角色 → 放行(豁免角色仅超管可授)

test_role_create_super_code_blocked()

test_role_create_super_code_blocked() : void

角色锚点防伪:create 禁止 code=super(防伪造不可删除的伪超管角色)

test_role_update_to_super_code_blocked()

test_role_update_to_super_code_blocked() : void

角色锚点防伪:普通角色 update 改为 code=super → 拒绝

test_super_role_exempt_cannot_be_removed()

test_super_role_exempt_cannot_be_removed() : void

超管角色豁免锁定:super 角色 is_exempt 1→0 → 拒绝(数据全见锚点不可降级)

test_post_create_super_code_blocked()

test_post_create_super_code_blocked() : void

岗位锚点防伪:create 禁止 code=super(防伪造不可删除的伪超管岗位)

test_self_scope_expansion_by_empty_dept_blocked()

test_self_scope_expansion_by_empty_dept_blocked() : void

个人范围自扩保护按部门集比对:加无人任职的部门(用户集不变但部门集扩大)→ 403

test_self_membership_expansion_by_empty_dept_blocked()

test_self_membership_expansion_by_empty_dept_blocked() : void

任职自扩保护按部门集比对:已有 child 范围任职,再新增 emptyDept 范围任职(部门集扩大)→ 403

test_post_scope_rejects_inactive_dept()

test_post_scope_rejects_inactive_dept() : void

后端兜底:岗位范围 syncScopeRules 勾选停用部门 → 400

test_personal_scope_rejects_inactive_dept()

test_personal_scope_rejects_inactive_dept() : void

后端兜底:个人范围 syncUserScopes 勾选停用部门 → 400

test_sync_user_roles_keep_exempt_role_allowed()

test_sync_user_roles_keep_exempt_role_allowed() : void

回归修复(复审发现):非超管给已持有豁免角色的用户增补普通角色(豁免角色保留随列表)→ 放行

test_update_cannot_disable_super()

test_update_cannot_disable_super() : void

停用规则:超管不可被停用(单接口 update,即使操作者是超管)

test_update_cannot_disable_self()

test_update_cannot_disable_self() : void

停用规则:不可停用当前登录用户(单接口 update,自我锁出防护)

test_batch_cannot_disable_self()

test_batch_cannot_disable_self() : void

停用规则:批量停用不可包含当前登录用户(与单接口同规)

test_super_post_scope_sync_blocked()

test_super_post_scope_sync_blocked() : void

纵深防御(复审补强):super 岗位数据范围同步 → 403(与角色侧 super 角色分配只读同规)

test_post_scope_rejects_inactive_company()

test_post_scope_rejects_inactive_company() : void

停用组织禁勾(复审补强):syncScopeRules 勾选停用组织 → 400(与停用部门同规)

test_led_dept_names()

test_led_dept_names() : void

负责人反向:ledDeptNames = 档案负责人(leader_id)∪ 任职负责人(is_leader=1)双向并集

test_led_dept_names_empty()

test_led_dept_names_empty() : void

负责人反向:未担任任何部门负责人 → 空列表

test_post_user_groups()

test_post_user_groups() : void

岗位视角用户分组:挂部门岗位 → 任职用户(含负责人标记)

test_scope_isolation_no_cross_user_leak()

test_scope_isolation_no_cross_user_leak() : void

隔离性:他人岗位范围/负责人部门/个人范围一律不进入本用户可见集——不是本人的全部 NO

requireRedis()

requireRedis() : void

Redis 依赖探针:直连 Redis 的测试(限流/会话/验证码)在无 Redis 环境(如 CI) 跳过而非失败——其余用例不受影响。CI 可设 TEST_REQUIRE_REDIS=1 强制模式: Redis 不可达即失败而非跳过,安全回归套件不允许静默消失。

buildCacheRegistry()

buildCacheRegistry(array  $items) : void

建缓存注册表最小 schema(td_sys_cache)并灌入注册项。

测试跑 sqlite :memory:,生产迁移含 PostgreSQL 专属 DDL 跑不通(DataScopeServiceTest 同因自建 schema); 而 CacheManager::registry() 现已从数据库表读取——凡走注册表的测试(remember/get/key/失效推导) 必须在 setUp 先调用本方法,否则注册表为空、remember 未登记名会走「自动登记」路径。

Parameters

array $items

setUp()

setUp() : void

buildSchema()

buildSchema() : void

最小 schema:仅 DataScopeService 推导路径涉及的表/列(create_time 靠 DB 默认值,模型不写)

seedData()

seedData() : void

makeUser()

makeUser(string  $username) : \App\Models\SysUser

Parameters

string $username

Returns

\App\Models\SysUser —

addMembership()

addMembership(\App\Models\SysUser  $user, \App\Models\SysDept  $dept, bool  $leader = false, ?\App\Models\SysPost  $post = null) : void

Parameters

\App\Models\SysUser $user
\App\Models\SysDept $dept
bool $leader
?\App\Models\SysPost $post

addPostScope()

addPostScope(int  $mode, int  $companyId, int  $deptId) : void

Parameters

int $mode
int $companyId
int $deptId

sortedVisible()

sortedVisible(\App\Models\SysUser  $user) : array

Parameters

\App\Models\SysUser $user

Returns

array —