// OrgService 作用域越权判定单测(assertInScope 纯逻辑,不连 DB)。 // // assertInScope 是 Service 层"第一道防线"——请求显式 id 与 token 作用域冲突时返回 1004。 // 数据层的第二道防线(Repository Scoping 强制过滤)由 handler 包 e2e 覆盖。 package service import ( "errors" "testing" apperrors "yuansiwei/unified-backend/internal/infra/errors" appscope "yuansiwei/unified-backend/internal/infra/scope" ) // newScope 快捷构造作用域(单测用)。 func newScope(inst, campus int64, super bool, role string) *appscope.Scope { return &appscope.Scope{InstitutionID: inst, CampusID: campus, SuperAdmin: super, Role: role, UserID: "01TESTUID000000000000000"} } // TestAssertInScope 覆盖 assertInScope 各分支。 func TestAssertInScope(t *testing.T) { svc := &OrgService{} // 零值;assertInScope 不触碰 db/仓储 cases := []struct { name string sc *appscope.Scope reqInst int64 reqCamp int64 wantErr bool wantCode int }{ {"nil_作用域_按未授权拒绝", nil, 0, 0, true, apperrors.CodeUnauth}, {"超管_跨机构放行", newScope(0, 0, true, "super_admin"), 99, 99, false, 0}, {"未显式指定_放行", newScope(11, 3, false, "teacher"), 0, 0, false, 0}, {"机构一致_放行", newScope(11, 3, false, "teacher"), 11, 0, false, 0}, {"校区一致_放行", newScope(11, 3, false, "teacher"), 11, 3, false, 0}, {"跨机构_越权1004", newScope(11, 3, false, "teacher"), 22, 0, true, apperrors.CodeScopeViolation}, {"校区锁定_token请求别的校区_越权1004", newScope(11, 3, false, "teacher"), 0, 4, true, apperrors.CodeScopeViolation}, {"机构级token_下钻别的校区_放行", newScope(11, 0, false, "academic"), 0, 4, false, 0}, {"机构级token_跨机构_越权1004", newScope(11, 0, false, "academic"), 22, 0, true, apperrors.CodeScopeViolation}, } for _, tc := range cases { t.Run(tc.name, func(t *testing.T) { err := svc.assertInScope(tc.sc, tc.reqInst, tc.reqCamp) if tc.wantErr { if !errors.Is(err, apperrors.ErrUnscoped) && !(tc.wantCode == apperrors.CodeUnauth && errors.Is(err, apperrors.ErrUnauth)) { t.Fatalf("期望 code=%d 错误,实际 %v", tc.wantCode, err) } return } if err != nil { t.Fatalf("期望放行,实际 %v", err) } }) } }