测试: GetDBTable 显式传 WithPermission,补充权限组合覆盖

Permission 不传时按零值处理,行级过滤和字段脱敏都会跳过(见 options.go 里
Permission 字段的注释),这是既有设计,不是这次改的。但 resx 包自己的测试
之前几乎都没传 WithPermission,实际上一直跑在"权限检查关闭"的状态下——
字段脱敏、写权限过滤、行级过滤相关的断言全部失效但没有暴露出来。

给 res_mask_field_test.go/res_interceptor_test.go 里所有 GetDBTable 调用
显式加上 WithPermission(ResAll),让这些测试真正跑在权限检查打开的状态下。
另外新增 res_permission_test.go,单独验证 WithPermission 各个取值(不传/
显式传 0/单独 ResRow/单独 ResMask/ResAll/按位组合)分别独立生效,作为这个
默认行为的回归防护。
This commit is contained in:
2026-08-20 15:59:24 +08:00
parent 5cdf1cc00d
commit f39adfa46c
3 changed files with 177 additions and 47 deletions
+26 -26
View File
@@ -178,7 +178,7 @@ func (t *maskFieldTest) newStarJoinApp() (user, dept, manager req.Resource) {
func (t *maskFieldTest) TestDefaultSelect_MasksRestrictedField() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).Select(db.Star()).Executor().ToSQL()
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).Select(db.Star()).Executor().ToSQL()
t.Contains(sql, "`name`")
t.Contains(sql, "-999999999 AS `salary`", "受限字段应该被替换成内置的数字哨兵值,而不是裸列")
@@ -188,7 +188,7 @@ func (t *maskFieldTest) TestDefaultSelect_MasksRestrictedField() {
func (t *maskFieldTest) TestDefaultSelect_RoleMatchShowsRealColumn() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}).Select(db.Star()).Executor().ToSQL()
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}, req.WithPermission(req.ResAll)).Select(db.Star()).Executor().ToSQL()
// 没有字段需要脱敏,直接维持原来的 SELECT *,不会被改写成展开的列表
t.Contains(sql, "SELECT *")
@@ -199,7 +199,7 @@ func (t *maskFieldTest) TestDefaultSelect_RoleMatchShowsRealColumn() {
func (t *maskFieldTest) TestDefaultSelect_NoRestrictedFieldsLeavesWildcard() {
res, _ := t.newResource(nameField)
sql, _, _ := res.GetDBTable(testUser{}).Select(db.Star()).Executor().ToSQL()
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).Select(db.Star()).Executor().ToSQL()
t.Contains(sql, "SELECT *")
}
@@ -210,7 +210,7 @@ func (t *maskFieldTest) TestDefaultSelect_NoRestrictedFieldsLeavesWildcard() {
func (t *maskFieldTest) TestExplicitColumn_MaskFieldMarkedColumnGetsMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.C("name"), resx.MaskField("salary").As("salary")).
Executor().ToSQL()
@@ -223,7 +223,7 @@ func (t *maskFieldTest) TestExplicitColumn_MaskFieldMarkedColumnGetsMasked() {
func (t *maskFieldTest) TestExplicitColumn_UnmarkedColumnNeverMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.C("salary")).
Executor().ToSQL()
@@ -237,7 +237,7 @@ func (t *maskFieldTest) TestExplicitColumn_UnmarkedColumnNeverMasked() {
func (t *maskFieldTest) TestQualifiedWildcard_OwnAliasExpandsAndMasks() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.T("User").All()).
Executor().ToSQL()
@@ -251,7 +251,7 @@ func (t *maskFieldTest) TestQualifiedWildcard_OwnAliasExpandsAndMasks() {
func (t *maskFieldTest) TestQualifiedWildcard_OtherAliasNeverMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.T("Department").All()).
Executor().ToSQL()
@@ -263,7 +263,7 @@ func (t *maskFieldTest) TestQualifiedWildcard_OtherAliasNeverMasked() {
func (t *maskFieldTest) TestExplicitColumn_CustomAliasPreserved() {
res, _ := t.newResource(salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(resx.MaskField("salary").As("employee_salary")).
Executor().ToSQL()
@@ -279,7 +279,7 @@ func (t *maskFieldTest) TestExplicitColumn_CustomAliasPreserved() {
func (t *maskFieldTest) TestExplicitColumn_JoinedResourceFieldMasked() {
user, dept := t.newJoinedApp()
sql, _, _ := user.GetDBTable(testUser{}).
sql, _, _ := user.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.C("name"), resx.MaskField("Department.budget").As("budget")).
Executor().ToSQL()
@@ -294,7 +294,7 @@ func (t *maskFieldTest) TestExplicitColumn_JoinedResourceFieldMasked() {
func (t *maskFieldTest) TestExplicitColumn_JoinedResourceFieldRoleMatchNotMasked() {
user, dept := t.newJoinedApp()
sql, _, _ := user.GetDBTable(testUser{roles: []string{"finance"}}).
sql, _, _ := user.GetDBTable(testUser{roles: []string{"finance"}}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.C("name"), resx.MaskField("Department.budget").As("budget")).
Executor().ToSQL()
@@ -310,7 +310,7 @@ func (t *maskFieldTest) TestExplicitColumn_JoinedResourceFieldRoleMatchNotMasked
func (t *maskFieldTest) TestExplicitColumn_DirectIdentifierAliasJoinResolves() {
user, _ := t.newJoinedApp()
sql, _, _ := user.GetDBTable(testUser{}).
sql, _, _ := user.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(db.T("departments").As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.C("name"), resx.MaskField("Department.budget").As("budget")).
Executor().ToSQL()
@@ -331,7 +331,7 @@ func (t *maskFieldTest) TestExplicitColumn_SelfJoinDifferentAliasesResolveIndepe
)
register(category)
sql, _, _ := category.GetDBTable(testUser{}, req.WithAlias("Child")).
sql, _, _ := category.GetDBTable(testUser{}, req.WithAlias("Child"), req.WithPermission(req.ResAll)).
LeftJoin(category.GetTableExpr().As("Parent"), db.On(db.I("Child.pid").Eq(db.I("Parent.id")))).
Select(
resx.MaskField("Child.secret").As("child_secret"),
@@ -349,7 +349,7 @@ func (t *maskFieldTest) TestExplicitColumn_SelfJoinDifferentAliasesResolveIndepe
func (t *maskFieldTest) TestExplicitColumn_ChainedJoinResolvesThirdTable() {
user, dept, company := t.newChainedJoinApp()
sql, _, _ := user.GetDBTable(testUser{}).
sql, _, _ := user.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
LeftJoin(company.GetTableExpr().As("Company"), db.On(db.I("Department.company_id").Eq(db.I("Company.id")))).
Select(db.C("name"), resx.MaskField("Company.budget").As("budget")).
@@ -366,7 +366,7 @@ func (t *maskFieldTest) TestExplicitColumn_ChainedJoinResolvesThirdTable() {
func (t *maskFieldTest) TestExplicitColumn_StarJoinResolvesEachBranchIndependently() {
user, dept, manager := t.newStarJoinApp()
sql, _, _ := user.GetDBTable(testUser{roles: []string{"finance"}}).
sql, _, _ := user.GetDBTable(testUser{roles: []string{"finance"}}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
LeftJoin(manager.GetTableExpr().As("Manager"), db.On(db.I("User.manager_id").Eq(db.I("Manager.id")))).
Select(
@@ -386,7 +386,7 @@ func (t *maskFieldTest) TestExplicitColumn_StarJoinResolvesEachBranchIndependent
func (t *maskFieldTest) TestExplicitColumn_FieldNotFoundOnResourceErrors() {
user, dept := t.newJoinedApp()
_, _, err := user.GetDBTable(testUser{}).
_, _, err := user.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.C("name"), resx.MaskField("Department.no_such_field").As("x")).
Executor().ToSQL()
@@ -399,7 +399,7 @@ func (t *maskFieldTest) TestExplicitColumn_FieldNotFoundOnResourceErrors() {
func (t *maskFieldTest) TestExplicitColumn_UnresolvableAliasErrors() {
res, _ := t.newResource(nameField, salaryField)
_, _, err := res.GetDBTable(testUser{}).
_, _, err := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.C("name"), resx.MaskField("NoSuchResource.budget").As("budget")).
Executor().ToSQL()
@@ -427,7 +427,7 @@ func (t *maskFieldTest) TestExplicitColumn_GetResourceUnavailableErrors() {
resx.WithFields(nameField),
)
_, _, sqlErr := res.GetDBTable(testUser{}).
_, _, sqlErr := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(db.T("departments").As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.C("name"), resx.MaskField("Department.budget").As("budget")).
Executor().ToSQL()
@@ -459,7 +459,7 @@ func (t *maskFieldTest) TestExplicitColumn_OwnAliasSkipsGetResourceEntirely() {
resx.WithFields(nameField, salaryField),
)
sql, _, sqlErr := res.GetDBTable(testUser{}).
sql, _, sqlErr := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(resx.MaskField("User.name").As("name"), resx.MaskField("User.salary").As("salary")).
Executor().ToSQL()
@@ -477,7 +477,7 @@ func (t *maskFieldTest) TestExplicitColumn_OwnAliasSkipsGetResourceEntirely() {
func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideFuncArgGetsMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.Func("CONCAT", resx.MaskField("salary"), db.L("' extra'")).As("computed")).
Executor().ToSQL()
@@ -489,7 +489,7 @@ func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideFuncArgGetsMasked() {
func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideFuncArgRoleMatchNotMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}).
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}, req.WithPermission(req.ResAll)).
Select(db.Func("CONCAT", resx.MaskField("salary"), db.L("' extra'")).As("computed")).
Executor().ToSQL()
@@ -503,7 +503,7 @@ func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideFuncArgRoleMatchNotMas
func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideNestedFuncArgGetsMasked() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
Select(db.Func("UPPER", db.Func("CONCAT", resx.MaskField("salary"), db.L("' extra'"))).As("computed")).
Executor().ToSQL()
@@ -515,7 +515,7 @@ func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideNestedFuncArgGetsMaske
func (t *maskFieldTest) TestExplicitColumn_MaskFieldInsideJoinedFuncArgGetsMasked() {
user, dept := t.newJoinedApp()
sql, _, _ := user.GetDBTable(testUser{}).
sql, _, _ := user.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).
LeftJoin(dept.GetTableExpr().As("Department"), db.On(db.I("User.dept_id").Eq(db.I("Department.id")))).
Select(db.Func("CONCAT", resx.MaskField("Department.budget"), db.L("' extra'")).As("computed")).
Executor().ToSQL()
@@ -545,7 +545,7 @@ func (t *maskFieldTest) TestCustomMaskFunc_Override() {
resx.WithFields(salaryField),
)
sql, _, _ := customRes.GetDBTable(testUser{}).Select(db.Star()).Executor().ToSQL()
sql, _, _ := customRes.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).Select(db.Star()).Executor().ToSQL()
t.Contains(sql, "REDACTED")
t.NotContains(sql, "-999999999")
@@ -557,7 +557,7 @@ func (t *maskFieldTest) TestCustomMaskFunc_Override() {
func (t *maskFieldTest) TestInsert_DropsFieldWithoutWriteAccess() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).Insert().
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).Insert().
Rows(db.Record{"name": "张三", "salary": 999999}).
Executor().ToSQL()
@@ -569,7 +569,7 @@ func (t *maskFieldTest) TestInsert_DropsFieldWithoutWriteAccess() {
func (t *maskFieldTest) TestInsert_KeepsFieldWithWriteAccess() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}).Insert().
sql, _, _ := res.GetDBTable(testUser{roles: []string{"hr"}}, req.WithPermission(req.ResAll)).Insert().
Rows(db.Record{"name": "张三", "salary": 999999}).
Executor().ToSQL()
@@ -580,7 +580,7 @@ func (t *maskFieldTest) TestInsert_KeepsFieldWithWriteAccess() {
func (t *maskFieldTest) TestUpdate_DropsFieldWithoutWriteAccess() {
res, _ := t.newResource(nameField, salaryField)
sql, _, _ := res.GetDBTable(testUser{}).Update().
sql, _, _ := res.GetDBTable(testUser{}, req.WithPermission(req.ResAll)).Update().
Set(db.Record{"name": "李四", "salary": 888888}).
Where(db.C("id").Eq(1)).
Executor().ToSQL()