feat: 待办交付确认补标书文件链接(bid_delivery_confirm);project_file放宽到项目空间层校验(兼容旧平铺结构)+路径含项目标识防越权
This commit is contained in:
parent
36c4132b02
commit
9045323adb
@ -32,6 +32,16 @@ async with DBPools().sqlorContext(dbname) as sor:
|
|||||||
proj_org = getattr(precs[0], 'org_id', '0') or '0'
|
proj_org = getattr(precs[0], 'org_id', '0') or '0'
|
||||||
project_dir, workspace_base = await get_project_dir_by_id(sor, project_id)
|
project_dir, workspace_base = await get_project_dir_by_id(sor, project_id)
|
||||||
|
|
||||||
|
# 项目空间基准:产线空间层 {space}/——项目输出文件的合法根(新旧结构都在其下:
|
||||||
|
# 新结构 {space}/projects/{项目名}/,旧平铺 {space}/{项目名}_{id}/)
|
||||||
|
space_dir = ''
|
||||||
|
if project_dir:
|
||||||
|
# 新结构 project_dir = {space}/projects/{项目名} → 空间层 = 上两级
|
||||||
|
if os.path.basename(os.path.dirname(project_dir)) == 'projects':
|
||||||
|
space_dir = os.path.dirname(os.path.dirname(project_dir))
|
||||||
|
else:
|
||||||
|
space_dir = os.path.dirname(project_dir)
|
||||||
|
|
||||||
if not project_dir or not os.path.isdir(project_dir):
|
if not project_dir or not os.path.isdir(project_dir):
|
||||||
return {"widgettype": "Message", "options": {"title": "错误", "message": "项目目录不可用"}}
|
return {"widgettype": "Message", "options": {"title": "错误", "message": "项目目录不可用"}}
|
||||||
|
|
||||||
@ -46,10 +56,17 @@ if str(uorg) != '0' and str(proj_org) != '0' and str(uorg) != str(proj_org):
|
|||||||
# 路径解析:绝对路径直接用;相对路径拼项目目录
|
# 路径解析:绝对路径直接用;相对路径拼项目目录
|
||||||
cand = fpath if fpath.startswith('/') else os.path.join(project_dir, fpath)
|
cand = fpath if fpath.startswith('/') else os.path.join(project_dir, fpath)
|
||||||
|
|
||||||
# 路径穿越校验:真实路径必须落在项目目录内
|
# 防跨项目越权:真实路径必须落在本项目的产线空间内,且路径中含项目标识
|
||||||
|
# (项目目录名/项目id/项目名任一)——新结构落在项目目录内,旧平铺落在 {项目名}_{id}/ 内,均满足。
|
||||||
real_proj = os.path.realpath(project_dir)
|
real_proj = os.path.realpath(project_dir)
|
||||||
|
real_space = os.path.realpath(space_dir) if space_dir else real_proj
|
||||||
real_full = os.path.realpath(cand)
|
real_full = os.path.realpath(cand)
|
||||||
if not real_full.startswith(real_proj + os.sep):
|
_proj_rec_name = getattr(precs[0], 'name', '') or ''
|
||||||
|
_proj_idents = [x for x in (os.path.basename(project_dir), project_id, _proj_rec_name) if x]
|
||||||
|
_path_ok = (real_space and real_full.startswith(real_space + os.sep)) or \
|
||||||
|
real_full.startswith(real_proj + os.sep)
|
||||||
|
_ident_ok = any(ix in cand for ix in _proj_idents)
|
||||||
|
if not _path_ok or not _ident_ok:
|
||||||
return {"widgettype": "Message", "options": {"title": "错误", "message": "非法路径(不在项目空间内)"}}
|
return {"widgettype": "Message", "options": {"title": "错误", "message": "非法路径(不在项目空间内)"}}
|
||||||
if not os.path.isfile(real_full):
|
if not os.path.isfile(real_full):
|
||||||
return {"widgettype": "Message", "options": {"title": "文件不存在",
|
return {"widgettype": "Message", "options": {"title": "文件不存在",
|
||||||
|
|||||||
@ -493,6 +493,38 @@ async with DBPools().sqlorContext(dbname) as sor:
|
|||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
elif task_type == 'bid_delivery_confirm':
|
||||||
|
# 投标产线交付确认:展示最新标书文件(打开/下载链接)+ 确认按钮
|
||||||
|
bdoc = []
|
||||||
|
if project_id:
|
||||||
|
brecs = await sor.sqlExe(
|
||||||
|
"SELECT doc_name, file_path, version, total_score, max_score, status, updated_at "
|
||||||
|
"FROM bid_documents WHERE project_id=${p}$ AND file_path<>'' "
|
||||||
|
"ORDER BY version DESC LIMIT 1", {"p": project_id})
|
||||||
|
await sor.sqlExe("COMMIT", {})
|
||||||
|
if brecs:
|
||||||
|
bdoc = brecs
|
||||||
|
if bdoc:
|
||||||
|
b0 = bdoc[0]
|
||||||
|
md.append('## 待确认标书')
|
||||||
|
md.append('')
|
||||||
|
md.append('- 名称:' + (_s(getattr(b0, 'doc_name', '')) or '-')
|
||||||
|
+ ' | 版本:v' + _s(getattr(b0, 'version', ''))
|
||||||
|
+ ' | 评分:' + _s(getattr(b0, 'total_score', '')) + '/'
|
||||||
|
+ _s(getattr(b0, 'max_score', ''))
|
||||||
|
+ ' | 状态:' + (_s(getattr(b0, 'status', '')) or '-'))
|
||||||
|
md.append('')
|
||||||
|
md.append('请下载标书后核对用印/密封/份数/递交要求,确认无误后点击确认交付。')
|
||||||
|
md.append('')
|
||||||
|
_bf = _s(getattr(b0, 'file_path', ''))
|
||||||
|
if _bf:
|
||||||
|
_file_rows.append(_file_link_row(os.path.basename(_bf), project_id, _bf))
|
||||||
|
else:
|
||||||
|
md.append('## 待确认标书')
|
||||||
|
md.append('')
|
||||||
|
md.append('未找到该项目的标书文件记录。')
|
||||||
|
md.append('')
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if not desc:
|
if not desc:
|
||||||
md.append('## 待办说明')
|
md.append('## 待办说明')
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user