Commit Graph
23 Commits
Author SHA1 Message Date
what b81faafd18 perf: 缓存 GetStruct 构造的 struct 类型
reflect.StructOf 即使命中 runtime 自己的类型缓存, 仍然要重新构造
[]StructField、算签名、加锁查表。实测 12 字段的 struct:

  reflect.StructOf(相同字段, 已缓存)   2349 ns / 2549 B / 31 allocs
  reflect.TypeOf(已知类型)                2.3 ns /    0 B /  0 allocs

相差三个数量级。而 fields 在资源构造之后不再变化, 相同的 extends 必然得到
同一个类型, 完全可以缓存复用。

GetStruct/GetSliceStruct 抽出共用的 structType(), 结果按 extends 缓存:

  GetStruct()          1399 ns / 2352 B / 28 allocs  ->  22.2 ns /  48 B / 1 alloc   63x
  GetStruct(extends)   1673 ns / 3592 B / 31 allocs  ->  47.1 ns / 176 B / 2 allocs  36x
  GetSliceStruct()     1457 ns / 2376 B / 29 allocs  ->  31.5 ns /  24 B / 1 alloc   46x

缓存用切片线性扫描而不是 map: 键是 []reflect.StructField, 要做 map key 得先
拼字符串, 那笔开销反而可能盖过 StructOf 本身; 而 extends 的取值组合来自关联
配置, 数量很少, 逐项比对最省。条目数设了上限, 超出后退回每次现算, 保证内存有界。

一个容易踩的坑: 缓存键会复制一份再存。调用方常把 extends 当临时缓冲区复用
(append 到同一个底层数组上), 直接持有会让键在之后被改写, 变成命中错误类型的
隐蔽 bug。TestGetStructExtendsAliasing 专门守这个。

行为不变: GetStruct 仍然每次返回新实例, 只是复用类型。
新增 4 个测试(类型稳定性/extends 隔离/别名安全/并发)与 3 个基准。
2026-08-28 19:50:54 +08:00
what 1d95bf64a2 chore: 清理 go.mod,移除本地 replace,db/reflux 锁定真实版本
上一个提交(User 默认实现移到 req/userx)之后 req 不再依赖 contracts,
连带它拉进来的一大堆间接依赖(grpc/viper/hcl/mcp-go 等)一起清掉了。
db/reflux 之前靠指向本地兄弟目录(../db-v2、../reflux)的 replace 绕开
版本解析,现在锁定成各自 master 最新的真实 commit,去掉 replace——本地
多仓库协同开发改用父目录的 go.work,不用再靠单个仓库自己的 replace。
2026-08-20 18:01:14 +08:00
what 3c757d53c5 重构: User 默认实现移到 req/userx,消除 req 对 contracts 的循环依赖
GetAnonymous/GetSystemUser 原来在 contracts/base 里实现,req 自己的测试
又要用它们构造测试用户,形成 req(测试)依赖 contracts、contracts(正式
代码)依赖 req 的循环——两边 go.mod 只能靠指向本地兄弟目录的 replace 绕过,
没法各自独立解析成真实版本号。

跟 resx 之于 req.Resource 一个思路:接口留在 req 包,默认实现挪到子包
req/userx,req 主包保持不引入实现细节所需的依赖(这里是 samber/lo)。
req 自己的测试文件改用 req/userx,不用触碰 contracts 了;contracts/base
里的 GetAnonymous/GetSystemUser 改成指向 req/userx 的函数别名,保持
兼容不用改调用方。
2026-08-20 18:00:40 +08:00
what 632c5476a0 docs: 新增 README,说明当前分支的能力范围
配合 v1-legacy 维护分支的拆分,记录 master 这条线(resx 默认实现、字段级脱敏、
ResFlags 权限开关、虚拟资源、读写钩子编排)目前有哪些能力,方便新接入的项目
了解现状,也跟 v1-legacy 分支做区分。
2026-08-20 16:23:41 +08:00
what f39adfa46c 测试: 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/按位组合)分别独立生效,作为这个
默认行为的回归防护。
2026-08-20 15:59:24 +08:00
what 5cdf1cc00d 重构: 虚拟资源改用 NewVirtualResource 显式构造,移除 WithVirtual
WithVirtual(bool) 只是给 New() 打一个标记位,虚拟资源需要的表达式(子查询)没有
承载的地方,之前借用 table string 字段硬拼字符串。改成 NewVirtualResource(res,
code, table, opts...) 专门构造:table 参数直接接收 exp.SQLExpression,
GetTableExpr 对虚拟资源直接用它生成子查询表达式,不用再手工拼括号和字符串;
container/conn/historyRoles 从传入的父资源上直接复用。

GetTableExpr 返回值类型从 exp.LiteralExpression 放宽成 exp.Aliaseable,
兼容 db.T(...)(IdentifierExpression)和 db.L(...)(LiteralExpression)两种
返回值。
2026-08-20 15:58:03 +08:00
what acb55bb53a 重构: ResScope 改成 ResFlags 位标志,行级过滤与字段脱敏拆成独立开关
ResScope(Off/On/All 三选一)改成 ResFlags 位标志:ResRow/ResRowRelations 管行级权限过滤,ResMask/ResMaskRelations 管字段级脱敏,两个维度可以按位独立组合(*Relations 那两位只保留定义,还没接入判断逻辑)。WithRolesScope 改名 WithPermission(req.ResFlags),dataProcessor 里原来单一的 skipPermission 拆成 skipRowFilter/skipFieldMask 分别控制。
2026-07-22 14:03:33 +08:00
what 6fc7854b0a chore: 更新 go.mod/go.sum 依赖版本 2026-07-22 09:12:10 +08:00
what 09f4c40d67 新增 resx 包剩余实现:字段/查询字段/脱敏/变更行等类型及测试
res_field.go/res_field_option.go(字段定义)、res_query_field.go/res_query_field_option.go(查询字段)、res_change_row.go(变更行)、res_mask_field.go(字段脱敏标记)及对应测试文件,配合此前已提交的 resource.go/res_interceptor.go 组成完整的 resx 资源实现包。
2026-07-22 09:11:50 +08:00
what 1868c8dd15 重构: User 相关类型拆分出 user_accessor.go/user_runtime.go
UserAccessor、UserRuntime 从 user.go 拆成独立文件,user.go 只保留 User 接口本身。
2026-07-22 09:11:26 +08:00
what a0ec297b61 重构: global_params.go/global_params_support.go 合并为 gparams.go 2026-07-22 09:11:00 +08:00
what 6d0c01c21f feat: Router.Call 拆分出 CallWithUser,支持指定内部调用身份
新增 CallWithUser(r, u, code, params, opts...),内部转发请求时可以冒充成指定用户身份,而不是沿用外部传入 request 自带的身份,用于类似"查自己的信息不该受字段级角色权限限制"这种需要以系统用户身份发起内部调用的场景。Call 本身签名不变,不影响现有调用方。
2026-07-21 18:01:28 +08:00
what 7f74caead4 feat: 新增 WithSilent/WithRolesScope 写操作选项
WithSilent 让写操作跳过变更通知(ResChangeEventFunc/ResWatcher),权限过滤/字段脱敏不受影响,用于类似"记录登录 IP"这种高频写但不需要广播"资源变了"的场景,避免不必要的缓存刷新。

WithRolesScope 显式指定权限过滤范围(ResScopeOn/All 才按角色过滤,Off 或不传都跳过),替代原来一直没接线生效的 Access 选项。两个选项相互独立,可以单独用也可以一起用。
2026-07-21 18:01:05 +08:00
what cc3f6d90e7 重构: ResAuthDB 重命名为 ResScope,统一权限过滤范围命名
原名字跟"身份认证"(Auth)容易混淆,实际控制的是资源查询/写入时按角色过滤的范围(关闭/仅自身/含关联资源),改用 Scope 更准确。ResAuthOff/On/All 同步改名为 ResScopeOff/On/All,数值保持不变,兼容数据库里已有的 is_auth_db 存量数据。
2026-07-21 18:00:39 +08:00
what f1774e5ca2 [feat] 完善 Router.Call Router.Get 方法 2024-11-26 17:35:11 +08:00
what bccb0382d8 [feat] 完善 Router.Call Router.Get 方法 2024-11-26 17:00:24 +08:00
what fd3625802b [feat] 完善 Router.Call Router.Get 方法 2024-11-26 16:45:45 +08:00
what 4ef8c130a7 [feat] 类型调整 int => byte 2024-05-09 11:44:00 +08:00
what f8a11598db [feat] 类型调整 int => byte 2024-05-09 11:39:36 +08:00
what c8cda2d8db [feat] RouteParamType 命名规范 2024-05-09 11:35:23 +08:00
what 6501b5ed0f [feat] 类型调整 int => byte 2024-05-09 11:16:26 +08:00
what f00b993f9c [feat] 移除 GetResource, 由 git.fsdpf.net/go/contracts 支持 2024-05-09 11:13:32 +08:00
what 672fc634ef first commit 2024-05-08 21:35:26 +08:00