feat: check_task_owner/check_tenant_owner 任务操作 owner 校验(通用引擎任务放行)

This commit is contained in:
ymq 2026-08-24 12:25:05 +08:00
parent d417772f42
commit e5ae2f1555
2 changed files with 62 additions and 7 deletions

View File

@ -513,7 +513,7 @@ def load_pipeline_service():
from .human_task_capability import ( from .human_task_capability import (
create_human_task, complete_human_task, qc_human_task, create_human_task, complete_human_task, qc_human_task,
list_project_human_tasks, count_my_human_tasks, list_my_human_todos, bug_accept) list_project_human_tasks, count_my_human_tasks, list_my_human_todos, bug_accept)
from .project_capability import check_project_owner from .project_capability import check_project_owner, check_task_owner, check_tenant_owner
env.create_human_task = create_human_task env.create_human_task = create_human_task
env.complete_human_task = complete_human_task env.complete_human_task = complete_human_task
env.qc_human_task = qc_human_task env.qc_human_task = qc_human_task
@ -522,6 +522,8 @@ def load_pipeline_service():
env.list_my_human_todos = list_my_human_todos env.list_my_human_todos = list_my_human_todos
env.bug_accept = bug_accept env.bug_accept = bug_accept
env.check_project_owner = check_project_owner env.check_project_owner = check_project_owner
env.check_task_owner = check_task_owner
env.check_tenant_owner = check_tenant_owner
# Register default handler # Register default handler
register_default_handler() register_default_handler()

View File

@ -104,22 +104,23 @@ async def create_project(name, project_type="web_app", description="",
return True, pid return True, pid
async def check_project_owner(project_id, user_id): async def check_project_owner(project_id, user_id, sor=None):
"""校验 user_id 是否为项目 owner(sd_projects.created_by)。 """校验 user_id 是否为项目 owner(sd_projects.created_by)。
独立开 context(供 pipeline-task 等 dspy 直接调用)。 独立开 context(供 pipeline-task 等 dspy 直接调用);传入 sor 时复用它(供
pipeline-sdlc dspy 在已有 get_sor_context 内调用,避免嵌套 context 的 MDL 锁)。
返回 (True, '') 或 (False, 错误信息)。 返回 (True, '') 或 (False, 错误信息)。
""" """
if not project_id: if not project_id:
return False, "缺少 project_id" return False, "缺少 project_id"
if not user_id: if not user_id:
return False, "未登录" return False, "未登录"
db, dbname = _get_db()
async with db.sqlorContext(dbname) as sor: async def _check(_sor):
recs = await sor.sqlExe( recs = await _sor.sqlExe(
"SELECT created_by, name FROM sd_projects WHERE id=${pid}$", "SELECT created_by, name FROM sd_projects WHERE id=${pid}$",
{"pid": project_id}) {"pid": project_id})
await sor.sqlExe("COMMIT", {}) await _sor.sqlExe("COMMIT", {})
if not recs: if not recs:
return False, "项目不存在" return False, "项目不存在"
owner = getattr(recs[0], 'created_by', '') or '' owner = getattr(recs[0], 'created_by', '') or ''
@ -127,6 +128,58 @@ async def check_project_owner(project_id, user_id):
return True, '' return True, ''
return False, "仅项目 owner 可执行此操作" return False, "仅项目 owner 可执行此操作"
if sor is not None:
return await _check(sor)
db, dbname = _get_db()
async with db.sqlorContext(dbname) as _s:
return await _check(_s)
async def check_task_owner(task_id, user_id):
"""校验 user_id 是否为 task 所属 SDLC 项目的 owner。
SDLC 任务 tenant_id=project_id,须校验 owner;通用引擎任务 tenant_id=org_id(非
项目 id),放行返回 (True, '')。独立开 context(供 pipeline-task dspy 调用)。
"""
if not task_id:
return False, "缺少 task_id"
if not user_id:
return False, "未登录"
db, dbname = _get_db()
async with db.sqlorContext(dbname) as sor:
recs = await sor.sqlExe(
"SELECT tenant_id FROM pipeline_tasks WHERE id=${tid}$", {"tid": task_id})
await sor.sqlExe("COMMIT", {})
if not recs:
return False, "任务不存在"
tenant = getattr(recs[0], 'tenant_id', '') or ''
p = await sor.sqlExe(
"SELECT id FROM sd_projects WHERE id=${pid}$", {"pid": tenant})
await sor.sqlExe("COMMIT", {})
if not p:
# 通用引擎任务(tenant_id 非 SDLC 项目),无 owner 概念,放行
return True, ''
return await check_project_owner(tenant, user_id, sor)
async def check_tenant_owner(tenant_id, user_id):
"""校验 user_id 是否为 tenant_id 所属 SDLC 项目的 owner。非项目 tenant 放行。
独立开 context(供 pipeline-task 的 task_submit 等 dspy 调用)。
"""
if not user_id:
return False, "未登录"
if not tenant_id:
return True, ''
db, dbname = _get_db()
async with db.sqlorContext(dbname) as sor:
p = await sor.sqlExe(
"SELECT id FROM sd_projects WHERE id=${pid}$", {"pid": tenant_id})
await sor.sqlExe("COMMIT", {})
if not p:
return True, ''
return await check_project_owner(tenant_id, user_id, sor)
async def start_project(project_id, who=None, agent_id=None): async def start_project(project_id, who=None, agent_id=None):
"""启动项目:draft → active(也兼容 archived → active 重新激活)。""" """启动项目:draft → active(也兼容 archived → active 重新激活)。"""