Skip to content

禅道 API 参考

权限与角色问题

禅道 API v2 权限与角色相关问题

1. 用户无角色导致 403 和空列表

现象

  • 创建操作返回 HTTP 403: {"status":"error","message":"Not allowed"}
  • 列表操作返回空数据(recTotal: 0),但其他用户/模块正常

根因

用户 role 字段为空(""),未分配任何角色。禅道权限模型:

  • 读取权限:登录用户即可访问(如 story listbug list
  • 写入权限:需要角色对应的 capability(如 storyCreateepicCreate
  • 模块权限:某些模块(如 systems)需要特定角色才能访问

诊断步骤

bash
# 1. 查看当前用户角色
chandao user get <numeric_id>
# 检查返回的 "role" 字段是否为空

# 2. 如果 user get <account_name> 返回 "User does not exist"
# 用数字 ID 重试(字符串账号名查询不稳定)

解决方案

禅道 Web 后台 → 组织 → 用户 → 编辑 → 分配角色

受影响的端点(已验证)

端点无角色时表现有角色后预期
POST /epics403200 + 创建成功
POST /requirements403200 + 创建成功
POST /stories403200 + 创建成功
GET /products/{id}/systems403200 + 系统列表
GET /products/{id}/requirements200 但 recTotal: 0200 + 实际数据
GET /products/{id}/epics200 但 recTotal: 0200 + 实际数据
GET /products/{id}/feedbacks200 但 recTotal: 0200 + 实际数据
GET /products/{id}/tickets200 但 recTotal: 0200 + 实际数据

注意:列表端点不会返回 403,而是返回空数据。这是最容易误判的情况——看起来像代码解析问题,实际是权限问题。

2. 角色级模块权限差异(qa vs dev/po/pm)

现象

用户已分配角色(如 qa),但特定模块仍返回 403。

根因

禅道的权限是按角色 × 模块配置的,不同角色默认拥有不同模块的访问权限:

模块qa(测试)dev(开发)po(产品)pm(项目)
Bug✅ 读写✅ 读写✅ 读✅ 读
Story✅ 读✅ 读写✅ 读写✅ 读
Epic✅ 读✅ 读写✅ 读
System(应用)✅ 读写✅ 读写
Testcase✅ 读写✅ 读✅ 读✅ 读
Testtask✅ 读写✅ 读✅ 读

已验证(xiaoqian, role=qa, product=21):

  • GET /products/21/epics → 200 ✅(qa 可读 epic)
  • POST /epics → 403 ❌(qa 无 epic 写入权限)
  • GET /products/21/systems → 403 ❌(qa 无 system 模块权限)
  • POST /systems → 403 ❌

解决方案

  1. 在禅道后台给角色添加对应模块的权限:组织 → 权限 → 选择角色 → 勾选模块
  2. 或者换用更高权限的角色(如 popm

⚠️ 角色可能被清空

在禅道后台修改权限配置时,用户的 role 字段可能被意外清空。修改权限后建议重新检查:

bash
chandao user get <id>
# 确认 "role" 字段不为空

3. user get 字符串账号名不稳定

现象

bash
chandao user get xiaoqian   # → "User does not exist."
chandao user get 6          # → 正常返回用户详情

根因

禅道 API v2 的 /users/{id} 端点对字符串账号名的查找逻辑不一致,某些账号名无法被识别。

建议

始终使用数字用户 ID 查询,不要依赖字符串账号名。


API v2 常见坑点

ZenTao RESTful API v2.0 常见坑点

1. 创建接口参数名必须带 ID 后缀

API v2 的创建接口(POST)要求关联字段使用 xxxID 格式,而非裸字段名。

实体API 请求体字段说明
Task createexecutionID不能用 execution
Story createproductID不能用 product
Bug createproductID不能用 product
Execution createproject特殊,不需要 ID 后缀
Project createmodel, begin, end项目类型字段是 model,非 type

错误表现

参数名错误时,API 返回 HTTP 403:

json
{"status": "fail", "message": "Not allowed"}

重要:这个 403 不是权限问题,是参数名错误!

如果参数名已确认正确仍返回 403,检查用户是否分配了角色(role 字段非空)。见 zentao-api-permissions.md

2. Bug create 的 openedBuild 是数组

json
{
  "productID": 21,
  "title": "Bug标题",
  "openedBuild": ["trunk"]
}

3. Task create 的必填字段

  • executionID — 所属执行 ID
  • name — 任务名称
  • type — 任务类型(devel/test/design/discuss/ui)

4. 登录端点差异

  • API v2 登录:POST /api.php/v2/users/login(脚本使用此端点)
  • 旧版登录:POST /api.php/v2/tokens

5. list 端点默认过滤导致返回空数据

以下模块的 list 命令返回空数据。根因:每个 list API 都有默认过滤参数,只返回特定状态的数据。

模块API 参数名默认值说明
requirement listbrowseunclosed未关闭的需求
epic listbrowseunclosed未关闭的史诗
testtask listbrowseTypeall所有测试单
  • story listbug list 不受影响,默认就能返回数据

6. PUT/DELETE 端点可能返回空响应

禅道 API 的 PUT/DELETE 端点可能返回空响应体(HTTP 200 但 body 为空)。脚本内部已处理空响应,自动返回 {"status": "success"}

7. 状态修改不能通过通用 PUT 端点

PUT /bugs/{id} 请求体中的 status 字段会被静默忽略

操作端点必填参数
解决 BugPUT /bugs/{id}/resolveresolution, resolvedBuild
关闭 BugPUT /bugs/{id}/close
激活 BugPUT /bugs/{id}/activate
完成 TaskPUT /tasks/{id}/finishconsumed
关闭 TaskPUT /tasks/{id}/close
激活 TaskPUT /tasks/{id}/activate

关键教训:API 返回 "成功" 不代表操作真的生效了。修改类操作后必须回查验证。

8. Bug resolve 会清空指派人

PUT /bugs/{id}/resolve 如果不传 assignedTo 参数,会将指派人清空为空字符串

脚本 bug resolve action 支持 --assignedTo 参数,建议在解决 Bug 时显式传入。

9. 修改参数后必须同步更新 SKILL.md

脚本参数修改后,SKILL.md 中的参数表必须同步更新,否则 agent 会按过时文档引导用户。

参考链接


v2 API 创建接口必填参数与字段名速查

禅道 v2 API 创建接口 — 必填参数与字段名速查

来源:禅道官方文档 https://www.zentao.net/book/api/ + Memos 笔记交叉验证 整理日期:2026-05-08

通用规则

  • 请求 Header:token: <token>
  • 返回格式:{status: 'success'|'fail', ...}
  • 分页:recPerPage ≤ 1000, pageID 从 1 开始
  • 日期格式:YYYY-MM-DD
  • URL 格式:{CHANDAO_URL}/api.php/v2/<resource>

创建接口必填参数

接口端点必填参数关键可选参数
创建BugPOST /bugsproductID, title, openedBuildproject, execution, severity, pri, type, steps, story
创建需求POST /storiesproductID, titlepri, module, parent, estimate, spec, category, source, verify, assignedTo, reviewer, project, execution
创建任务POST /tasksname, executionIDtype, assignedTo, estStarted, deadline, pri, estimate, module, story, desc
创建项目POST /projectsname, model, begin, end, workflowGroupproducts, parent, PM
创建产品POST /productsnameprogram, line, type, PO, reviewer, desc, QD, RD, acl
创建测试用例POST /testcasesproductID, titlemodule, story, pri, type, precondition, steps, expects, stepType, project, execution
创建执行POST /executionsproject, name, begin, endlifetime, days, products, plans, PO, QD, PM, RD, acl
创建测试单POST /testtasksproductID, name, build, begin, endexecution, type, owner, status, desc
创建史诗POST /epicsproductID, titlepri, parent, estimate, spec, category, source, verify, assignedTo, reviewer
创建用户需求POST /requirementsproductID, titlepri, module, parent, estimate, spec, category, source, verify, assignedTo, reviewer
创建工单POST /ticketsproductID, titlepri, type, assignedTo, deadline, description
创建反馈POST /feedbacksproductID, titlepri, type, assignedTo, deadline, description

关键字段名(易错)

正确字段名错误写法用于接口
productIDproductBug, Story, Testcase, Testtask, Epic, Requirement, Ticket, Feedback
executionIDexecutionTask
projectprojectIDExecution
openedBuildopenedBuild[]Bug(数组格式,主干填 ["trunk"]

状态流转

Bug

  • active → resolved(PUT /bugs/:id/resolve)
  • active/resolved → closed(PUT /bugs/:id/close)
  • closed/resolved → active(PUT /bugs/:id/activate)

Task

  • wait → started(PUT /tasks/:id/start)
  • started → finished(PUT /tasks/:id/finish)
  • finished → closed(PUT /tasks/:id/close)
  • closed/finished → active(PUT /tasks/:id/activate)

Story

  • draft → active(评审通过)
  • active → closed(PUT /stories/:id/close)
  • closed → active(PUT /stories/:id/activate)

官方文档链接

Memos 笔记参考

笔记 ID内容
brJN8LeEXhLsKyuwWerZNw禅道 RESTful API v2.0 文档索引(总)
8BYQFtAujXdcNn7iBKrdPL禅道 RESTful API v2.0 文档索引(上)
KPcXoBDz4Z6WzbPCKAgCiQ禅道 RESTful API v2.0 文档索引(下)
K2z5NfrYKVQXWB48YMNiNQ禅道 v2 API 入参出参详解(二)
QVFR3ZSZFQ8Vy3b3r732um禅道 v2 API 入参出参详解(一)
dUNfXqs3de9FRYmCLqjbqJ禅道 v2 API 入参出参详解(P0核心模块)

基于非商业使用许可证发布