# go/tableDB v1.1.8 `tableDB` 是基于 `@go/db` 的高级数据库抽象引擎,支持动态 Schema 管理、身份驱动的行级隔离 (RLS) 以及 ABAC 权限策略。 ## 🎯 核心设计理念 - **动态 Schema**: 像操作数据一样操作表和字段,无需手动 SQL 迁移。 - **内置标准字段**: 所有数据表强制且自动携带 5 个标准字段:`id` (全局唯一)、`creator`、`createTime`、`updater`、`updateTime`。系统会自动在插入和更新时维护它们。 - **身份驱动**: 所有操作强制绑定 `userID`,系统基于此自动拦截并填充创建者、更新者。 - **ABAC 权限模型**: 支持 SQL 条件过滤、属性权限及关系继承,替代传统的 Role 体系。 - **极速性能**: 通过内存展平策略实现零 RTT 鉴权,支持 O(1) 字段验证。 ## 📦 安装 ```bash go get apigo.cc/go/tableDB ``` ## 🛠 API 指南 ### 1. 初始化与授权 ```go // 获取未授权实例 (无法直接操作数据),可传入 redis 地址用于分布式 ID 生成 unauth := tableDB.GetDB("sqlite://data.db", logger, "") // 必须绑定身份后才能使用 app := unauth.Auth("user_123") sys := unauth.Auth(tableDB.SystemUserID) // 超管权限,绕过所有 RLS ``` ### 2. 动态架构管理 (Schema) ```go // 1. 设置表元数据 sys.SetTable(tableDB.TableSchema{ Name: "orders", EnableRLS: true, // 开启行级安全拦截 Memo: "业务订单表", }) // 2. 批量维护字段 (支持动态迁移) app.Table("orders").SetField( tableDB.FieldSchema{Name: "title", Type: "v128", IsIndex: true}, tableDB.FieldSchema{Name: "amount", Type: "i"}, tableDB.FieldSchema{Name: "status", Type: "i", IsIndex: true}, ) // 3. 查看有权访问的表 tables, _ := app.Tables() ``` ### 3. 数据操作 (CRUD) ```go table := app.Table("orders") // 保存数据 (自动填充 creator) table.Set(map[string]any{"title": "测试订单", "amount": 100}) // 获取单条 (自动进行权限校验) order, err := table.Get("id_xxx") // 列表查询 (自动注入过滤条件: creator = userID OR policy_conditions) list, _ := table.List(map[string]any{"amount >": 50}) // 结构化查询 (支持 Join 和 Select 验证) res, _ := table.Query(tableDB.QueryRequest{ Select: []string{"id", "title"}, Where: "status = ?", Args: []any{1}, }) ``` ### 4. 策略与权限管理 (ABAC) 策略允许用户访问非自己创建的数据。 ```go // 1. 授权策略: 允许 user_A 读取订单,但仅限金额小于 1000 的 sys.SetPolicy(tableDB.PolicySchema{ UserID: "user_A", Type: "table", Targets: []string{"orders"}, Action: "read", Condition: "amount < ?", ConditionArgs: []any{1000}, }) // 2. 继承策略: manager 继承 clerk 的所有权限 sys.SetPolicy(tableDB.PolicySchema{ UserID: "manager", Type: "inherit", Targets: []string{"clerk"}, }) // 3. 自主授权: 对表拥有 'full' 权限的用户,可以给其他人授权该表 manager.SetPolicy(tableDB.PolicySchema{ UserID: "clerk", Type: "table", Targets: []string{"orders"}, Action: "read", }) ``` ## 🛡 安全契约 1. **隐式隔离**: 只要表开启了 `EnableRLS` 且包含 `creator` 字段,查询将自动限制在用户创建的数据范围内。 2. **零开销拦截**: 鉴权逻辑已下推至 SQL WHERE 层,消除 N+1 查询隐患。 3. **特权保护**: 系统表 `_Table`, `_Field`, `_Policy` 禁止普通用户通过 Table API 直接修改,必须通过专属 API 进行管理。 4. **命名规范**: 全局强制驼峰命名,禁止使用 `json` tag。 ## 🔗 Hook 事件 (Hooks) `tableDB` 提供了一系列 Hook,允许开发者在表结构变更或数据更新时注入自定义逻辑(如:缓存同步、消息推送、业务校验等)。 ### 1. 注册 Hook Hook 需要在 `Auth` 之前,在 `TableDBUnauthorized` 实例上注册。 ```go unauth := tableDB.GetDB("sqlite://data.db", logger, "") // 监听数据更新 (用于缓存同步) unauth.Hooks.OnUpdatedRows = func(rows []map[string]any, table *tableDB.TableSchema, fields []tableDB.FieldSchema) { for _, row := range rows { fmt.Printf("表 %s 的数据已更新: %v\n", table.Name, row["id"]) } } // 数据写入前校验 (返回 error 将中断操作) unauth.Hooks.OnUpdatingRow = func(row map[string]any, table *tableDB.TableSchema, fields []tableDB.FieldSchema) error { if table.Name == "orders" && cast.Int(row["amount"]) > 1000000 { return errors.New("金额过大,需要人工审核") } return nil } app := unauth.Auth("user_123") ``` ### 2. 支持的事件列表 | 事件名 | 触发时机 | 参数说明 | | :--- | :--- | :--- | | `OnCreatedTable` | 新表创建后 | `table`: 表架构信息 | | `OnRemovedTable` | 表被删除后 | `table`: 表架构信息 | | `OnUpdatedField` | 字段新增或修改后 | `table`: 表架构,`field`: 字段架构 | | `OnRemovedField` | 字段删除后 | `table`: 表架构,`fieldName`: 字段名 | | `OnUpdatingRow` | **数据写入前** | `row`: 待写入数据,`table`: 表架构。**返回 error 可拦截写入**。 | | `OnUpdatedRows` | 数据写入/更新后 | `rows`: 已更新的数据列表(包含完整字段) | | `OnRemovedRows` | 数据删除后 | `ids`: 已删除的主键列表 |