API 实战流程

本文档介绍如何通过 API 完成角色权限配置和用户同步的完整流程,适用于需要自动化批量创建用户、配置角色权限、同步用户所属空间以及设置用户级权限覆盖的场景。

场景描述

假设当前的空间 ID 为 default,有一张商品表,sid 为 dim_prods_default

现在需要添加一个「店长」角色,让该角色默认只能查看「产品类型 = 电子产品」的数据,并控制部分指标的可见范围;同时为个别用户配置更细粒度的用户级权限覆盖。

API 通用配置

获取 API Key

管理员账号 → 右上角⚙️按钮 → API密钥,生成一个密钥。

必需的请求头

所有 API 请求都需要包含以下请求头:

Authorization: Bearer <YOUR_TOKEN>
X-SPACES: default
Content-Type: application/json

环境变量

以下命令假设服务部署在 http://localhost:13000,实际使用时请替换为您的域名:

export BASE_URL="http://localhost:13000"

创建或更新角色并配置权限

使用 yiask_roles:updateOrCreateWithPermissions API,一次调用即可完成角色创建、权限配置和用户绑定:

curl '$BASE_URL/api/yiask_roles:updateOrCreateWithPermissions' \
  -H 'Authorization: Bearer YOUR_TOKEN_HERE' \
  -H 'X-SPACES: default' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "name": "storeOwner",
    "title": "店长",
    "yiaskActions": ["view"],
    "permissions": {
      "dim_prods_default": {
        "rowPermissions": {
          "$and": [
            {
              "产品类型": {
                "$eq": "电子产品"
              }
            }
          ]
        },
        "columnPermissions": {}
      }
    },
    "metricPermissions": [
      {
        "code": "sales_amount",
        "hasPermission": true
      },
      {
        "code": "profit_rate",
        "hasPermission": false
      }
    ],
    "users": [
      {
        "username": "zhangsan",
        "nickname": "张三",
        "email": "zhangsan@example.com",
        "phone": "13800138001",
        "position": "店长",
        "spaces": ["default"],
        "password": "Password123!"
      },
      {
        "username": "lisi",
        "nickname": "李四",
        "email": "aaa@example.com",
        "phone": "13800138002",
        "position": "招商主管",
        "spaces": ["default", "north"],
        "password": "Password123!",
        "permissions": {
          "dim_prods_default": {
            "rowPermissions": {
              "$and": [
                {
                  "产品名称": {
                    "$eq": "笔记本电脑1"
                  }
                }
              ]
            },
            "columnPermissions": {}
          }
        },
        "metricPermissions": [
          {
            "code": "sales_amount",
            "hasPermission": true
          }
        ]
      }
    ]
  }'

参数说明

必填参数

参数类型说明
namestring角色名称(唯一标识)
permissionsobject权限配置对象

可选参数

参数类型默认值说明
titlestringname角色显示名称
yiaskActionsstring[]不传是否显式覆盖 yiask 数据源的通用权限。传 ["view"] 表示保留 yiask 通用查看权限;传 [] 表示移除 yiask 通用查看权限
metricPermissionsarray不传角色级指标权限配置。按指标 code 配置可见性,服务端会将其合并到对应 schema 的 columnPermissions.view
usersarray不传用户全量列表。显式传入时会按该数组全量覆盖当前 role 的用户关联;传 [] 表示清空;不传则保持现有关联不变

yiaskActions 用法

yiaskActions 用于控制角色在 yiask 数据源级别 的通用权限。

  • ["view"]:允许该角色具备 yiask 通用查看权限
  • []:移除该角色的 yiask 通用查看权限
  • 不传:不主动修改当前角色的 yiask 通用权限配置

例如,只保留单表权限、不保留 yiask 通用查看权限时,可以这样传:

{
  "name": "storeOwner",
  "yiaskActions": [],
  "permissions": {
    "dim_prods_default": {
      "columnPermissions": {
        "view": null
      }
    }
  }
}

permissions 格式

{
  permissions: {
    "[schemaSid]": {
      // 行权限:数据过滤条件
      rowPermissions: {
        "$and": [
          {
            "字段名": { "操作符": "值" }
          }
        ]
      },
      // 列权限:每个 action 可访问的字段列表
      columnPermissions: {
        "[actionName]": ["字段1", "字段2"],  // 只能访问指定字段
        "[actionName]": null                   // null 表示允许访问所有字段
      }
    }
  }
}

users 格式

{
  users: [
    {
      username: "string",      // 必填,用户名(唯一标识)
      nickname: "string",      // 可选,显示名称
      email: "string",         // 可选,邮箱
      phone: "string",         // 可选,手机号
      position: "string",      // 可选,岗位
      spaces: ["string"],      // 可选,用户所属空间列表。显式传入时会同步到 spacesUsers,只确保加入这些空间,不会移除用户原有的其他空间关联
      password: "string",      // 可选,密码。仅创建新用户时生效,更新已有用户时不会覆盖密码
      permissions: {           // 可选,用户级权限覆盖,格式与顶层 permissions 相同
        "[schemaSid]": {
          rowPermissions: {},
          columnPermissions: {}
        }
      },
      metricPermissions: [     // 可选,用户级指标权限覆盖
        {
          code: "string",
          hasPermission: true
        }
      ]
    }
  ]
}

metricPermissions 格式

{
  metricPermissions: [
    {
      code: "sales_amount",   // 指标 code
      hasPermission: true     // true 表示允许查看,false 表示移除查看权限
    }
  ]
}
  • metricPermissions 既可出现在请求顶层,也可出现在 users[].metricPermissions 中。
  • 服务端会按当前空间中的指标 code 查找对应字段,查找范围包括 yiask_propertyyiask_custom_metric
  • 找到后会将结果合并到对应 schema 的 columnPermissions.view 中,不会在响应里额外返回独立的 metricPermissions 字段。
  • hasPermission: true 会将该指标字段加入 viewhasPermission: false 会将该指标字段从 view 中移除。
  • 如果某个 code 不存在,接口会返回 404,例如 metricPermissions[0].code "missing_metric" not found

例如,为角色补充指标可见范围:

{
  "permissions": {
    "dwd_sales_detail_default": {
      "columnPermissions": {
        "view": ["店铺ID"]
      }
    }
  },
  "metricPermissions": [
    {
      "code": "sales_amount",
      "hasPermission": true
    },
    {
      "code": "profit_rate",
      "hasPermission": false
    }
  ]
}

以上配置会把 sales_amount 对应的指标字段加入 dwd_sales_detail_default.columnPermissions.view;如果 profit_rate 已在 view 中,则会被移除。

说明:如果某个 schema 的 columnPermissions.viewnull,再传 metricPermissions 后,最终会改写为仅包含 hasPermission = true 的指标字段列表,而不是继续表示“可查看全部字段”。

幂等语义

  • permissions 会按本次请求整体重建,适合直接传最新完整配置。
  • metricPermissions 会按指标 code 解析并并入角色级 permissions[*].columnPermissions.view
  • users 显式传入时,会被视为当前 role 的全量用户列表。服务端会先清空该 role 现有的用户关联和相关 usersYiaskCollections 记录,再按数组内容重建。
  • users: [] 表示清空当前 role 的所有用户关联。
  • users 不传表示只更新角色和权限,不修改 users 与 role 的关联。
  • users[].spaces 显式传入时,会确保用户加入这些空间,并同步到 spacesUsers;不会删除该用户已有但未声明的其他空间关联。
  • users[].spaces 中的空间必须已存在;如果传入不存在的空间名,接口会返回 400
  • users[].permissions 会写入当前空间对应的 usersYiaskPermissions 记录,用于用户级权限覆盖。
  • users[].metricPermissions 会按相同方式写入当前空间对应的 usersYiaskPermissions,用于用户级指标权限覆盖。
  • 同一张表上,用户级 permissions 会覆盖角色级 permissions;未配置用户级覆盖的表,仍然继承角色权限。
  • users[].password 仅在创建新用户时生效;如果用户已存在,本接口不会覆盖其密码。

说明users[].spaces 用于配置用户所属空间;users[].permissionsusers[].metricPermissions 仍然只会写入当前请求头 X-SPACES 指定的空间。

字段名自动转换

建议使用属性的名称(如 产品类型),同时也支持属性的 ID(如 productTypeproductName),输入属性的 ID 会自动转换为属性名称。

{
  "permissions": {
    "dim_prods_default": {
      "rowPermissions": {
        "$and": [
          {
            "productType": { "$eq": "电子产品" }  // 属性 ID → 自动转换为 "产品类型"
          }
        ]
      },
      "columnPermissions": {
        "view": ["productName", "productType"]  // → ["产品名称", "产品类型"]
      }
    }
  }
}

说明:以上示例中,假设「产品名称」的属性 ID 为 productName,「产品类型」的属性 ID 为 productType

转换规则:

  • 如果字段是某个 property 的 name(如 产品类型),直接保留
  • 如果字段是某个 property 的 id(如 productType),自动转换为 name
  • 如果字段既不是 name 也不是 id(如 $and$eq 等操作符),保留原样

数据范围语法说明

数据范围(rowPermissions)使用类似 MongoDB 的查询语法来定义数据过滤条件。

逻辑操作符

操作符说明示例
$and逻辑与,所有条件都必须满足见下方示例
$or逻辑或,满足任一条件即可见下方示例

$and 示例(同时满足多个条件):

{
  "rowPermissions": {
    "$and": [
      { "status": { "$eq": "active" } },
      { "age": { "$gte": 18 } }
    ]
  }
}

$or 示例(满足任一条件即可):

{
  "rowPermissions": {
    "$or": [
      { "status": { "$eq": "active" } },
      { "role": { "$eq": "admin" } }
    ]
  }
}

比较操作符

操作符说明示例
$eq等于{ "status": { "$eq": "active" } }
$ne不等于{ "status": { "$ne": "deleted" } }
$gt大于{ "age": { "$gt": 18 } }
$gte大于等于{ "age": { "$gte": 18 } }
$lt小于{ "age": { "$lt": 65 } }
$lte小于等于{ "age": { "$lte": 65 } }
$in包含在数组中{ "status": { "$in": ["active", "pending"] } }
$nin不包含在数组中{ "status": { "$nin": ["deleted", "banned"] } }

字符串操作符

操作符说明示例
$includes包含指定字符串(模糊匹配){ "name": { "$includes": "张三" } }
$notIncludes不包含指定字符串{ "name": { "$notIncludes": "测试" } }
$startsWith以指定字符串开头{ "username": { "$startsWith": "user_" } }
$notStartsWith不以指定字符串开头{ "username": { "$notStartsWith": "admin_" } }
$endWith以指定字符串结尾{ "email": { "$endWith": "@example.com" } }
$notEndWith不以指定字符串结尾{ "email": { "$notEndWith": "@spam.com" } }

数组操作符

操作符说明示例
$anyOf数组包含任一指定元素{ "tags": { "$anyOf": ["urgent", "important"] } }
$noneOf数组不包含任何指定元素{ "tags": { "$noneOf": ["spam", "test"] } }
$match数组完全匹配{ "permissions": { "$match": ["read", "write"] } }
$notMatch数组不完全匹配{ "permissions": { "$notMatch": ["admin"] } }
$arrayEmpty数组为空{ "tags": { "$arrayEmpty": true } }
$arrayNotEmpty数组不为空{ "tags": { "$arrayNotEmpty": true } }

日期操作符

操作符说明示例
$dateOn日期等于某天{ "createdAt": { "$dateOn": "2024-01-01" } }
$dateNotOn日期不等于某天{ "createdAt": { "$dateNotOn": "2024-01-01" } }
$dateBefore日期在指定日期之前{ "createdAt": { "$dateBefore": "2024-01-01" } }
$dateNotBefore日期不在指定日期之前(≥){ "createdAt": { "$dateNotBefore": "2024-01-01" } }
$dateAfter日期在指定日期之后{ "createdAt": { "$dateAfter": "2024-01-01" } }
$dateNotAfter日期不在指定日期之后(≤){ "createdAt": { "$dateNotAfter": "2024-01-01" } }
$dateBetween日期在两个日期之间{ "createdAt": { "$dateBetween": ["2024-01-01", "2024-12-31"] } }

空值/布尔操作符

操作符说明示例
$empty为空(null、undefined、空字符串或空数组){ "phone": { "$empty": true } }
$notEmpty不为空{ "phone": { "$notEmpty": true } }
$isFalsy为假值{ "deleted": { "$isFalsy": true } }
$isTruly为真值{ "verified": { "$isTruly": true } }

用户级权限覆盖

如果某个用户需要比角色更细粒度的权限,可以在 users[].permissions 中单独配置数据行/列权限,也可以在 users[].metricPermissions 中单独配置指标可见性。

例如,角色默认可以查看所有「电子产品」,但李四只能查看「笔记本电脑1」:

{
  "users": [
    {
      "username": "lisi",
      "permissions": {
        "dim_prods_default": {
          "rowPermissions": {
            "$and": [
              {
                "产品名称": {
                  "$eq": "笔记本电脑1"
                }
              }
            ]
          },
          "columnPermissions": {}
        }
      }
    }
  ]
}

说明:用户级 permissions 的格式与角色级 permissions 完全一致,但作用范围仅限当前用户、当前空间。

如果还需要单独控制某个用户的指标可见性,可以继续在同一用户下追加 metricPermissions

{
  "users": [
    {
      "username": "lisi",
      "metricPermissions": [
        {
          "code": "sales_amount",
          "hasPermission": true
        }
      ]
    }
  ]
}

这会将 sales_amount 对应的指标字段写入该用户当前空间的 usersYiaskPermissions.permissions[*].columnPermissions.view 中。

用户所属空间同步

如果需要在同一次调用中同步用户所属空间,可以在 users[].spaces 中传入空间列表。

例如,将张三加入 default,将李四同时加入 defaultnorth

{
  "users": [
    {
      "username": "zhangsan",
      "spaces": ["default"]
    },
    {
      "username": "lisi",
      "spaces": ["default", "north"]
    }
  ]
}
  • users[].spaces 会写入 spacesUsers
  • 显式传入时只会确保用户加入这些空间
  • 不会移除用户已有但未声明的其他空间
  • 如果空间名不存在,接口会返回 400

完整示例

创建「店长」角色,配置商品表权限和指标可见范围,同时创建两位用户,其中李四带有用户级权限覆盖:

curl '$BASE_URL/api/yiask_roles:updateOrCreateWithPermissions' \
  -H 'Authorization: Bearer YOUR_TOKEN_HERE' \
  -H 'X-SPACES: default' \
  -H 'Content-Type: application/json' \
  --data-raw '{
    "name": "storeOwner",
    "title": "店长",
    "yiaskActions": ["view"],
    "permissions": {
      "dim_prods_default": {
        "rowPermissions": {
          "$and": [
            {
              "产品类型": {
                "$eq": "电子产品"
              }
            }
          ]
        },
        "columnPermissions": {}
      }
    },
    "metricPermissions": [
      {
        "code": "sales_amount",
        "hasPermission": true
      },
      {
        "code": "profit_rate",
        "hasPermission": false
      }
    ],
    "users": [
      {
        "username": "zhangsan",
        "nickname": "张三",
        "email": "zhangsan@example.com",
        "phone": "13800138001",
        "position": "店长",
        "spaces": ["default"],
        "password": "Password123!"
      },
      {
        "username": "lisi",
        "nickname": "李四",
        "email": "aaa@example.com",
        "phone": "13800138001111",
        "position": "招商主管",
        "spaces": ["default", "north"],
        "password": "Password123!",
        "permissions": {
          "dim_prods_default": {
            "rowPermissions": {
              "$and": [
                {
                  "产品名称": {
                    "$eq": "笔记本电脑1"
                  }
                }
              ]
            },
            "columnPermissions": {}
          }
        },
        "metricPermissions": [
          {
            "code": "sales_amount",
            "hasPermission": true
          }
        ]
      }
    ]
  }'

返回结果:

{
  "name": "storeOwner",
  "title": "店长",
  "createdAt": "2024-01-01T00:00:00.000Z",
  "updatedAt": "2024-01-01T00:00:00.000Z",
  "id": 123456789,
  "permissions": {
    "dim_prods_default": {
      "rowPermissions": {
        "$and": [
          {
            "产品类型": {
              "$eq": "电子产品"
            }
          }
        ]
      },
      "columnPermissions": {
        "view": ["销售额"]
      }
    }
  }
}

执行结果

调用成功后:

  1. 创建了「店长」角色
  2. 自动配置了 dim_prods_default 的角色权限
  3. 创建或更新了张三、李四两位用户,并绑定到「店长」角色
  4. users[].spaces 同步到 spacesUsers,确保张三属于 default,李四属于 defaultnorth
  5. 如果用户不存在,会按请求中的 password 创建用户;如果用户已存在,不会覆盖其密码
  6. 将顶层 metricPermissions 按指标 code 解析后合并到角色权限的 columnPermissions.view
  7. users[].permissionsusers[].metricPermissions 同步到 usersYiaskPermissions
  8. 张三继承角色权限,可查看「产品类型 = 电子产品」的数据,并拥有 sales_amount 对应指标字段的查看权限
  9. 李四在 dim_prods_default 上使用用户级权限覆盖,只能查看「产品名称 = 笔记本电脑1」的数据,并额外写入自己的指标可见性配置