tableDB/README.md

5.2 KiB
Raw Blame History

go/tableDB v1.1.8

tableDB 是基于 @go/db 的高级数据库抽象引擎,支持动态 Schema 管理、身份驱动的行级隔离 (RLS) 以及 ABAC 权限策略。

🎯 核心设计理念

  • 动态 Schema: 像操作数据一样操作表和字段,无需手动 SQL 迁移。
  • 内置标准字段: 所有数据表强制且自动携带 5 个标准字段:id (全局唯一)、creatorcreateTimeupdaterupdateTime。系统会自动在插入和更新时维护它们。
  • 身份驱动: 所有操作强制绑定 userID,系统基于此自动拦截并填充创建者、更新者。
  • ABAC 权限模型: 支持 SQL 条件过滤、属性权限及关系继承,替代传统的 Role 体系。
  • 极速性能: 通过内存展平策略实现零 RTT 鉴权,支持 O(1) 字段验证。

📦 安装

go get apigo.cc/go/tableDB

🛠 API 指南

1. 初始化与授权

// 获取未授权实例 (无法直接操作数据),可传入 redis 地址用于分布式 ID 生成
unauth := tableDB.GetDB("sqlite://data.db", logger, "")

// 必须绑定身份后才能使用
app := unauth.Auth("user_123")
sys := unauth.Auth(tableDB.SystemUserID) // 超管权限,绕过所有 RLS

2. 动态架构管理 (Schema)

// 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)

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)

策略允许用户访问非自己创建的数据。

// 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 实例上注册。

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: 已删除的主键列表