Fix: canvas sharing bug. (#9339)

### What problem does this PR solve?


### Type of change

- [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
Kevin Hu
2025-08-08 18:31:51 +08:00
committed by GitHub
parent b9eeb8e64f
commit 90eb5fd31b
2 changed files with 40 additions and 26 deletions

View File

@ -62,7 +62,7 @@ def canvas_list():
@login_required @login_required
def rm(): def rm():
for i in request.json["canvas_ids"]: for i in request.json["canvas_ids"]:
if not UserCanvasService.query(user_id=current_user.id,id=i): if not UserCanvasService.accessible(i, current_user.id):
return get_json_result( return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.', data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR) code=RetCode.OPERATING_ERROR)
@ -86,7 +86,7 @@ def save():
if not UserCanvasService.save(**req): if not UserCanvasService.save(**req):
return get_data_error_result(message="Fail to save canvas.") return get_data_error_result(message="Fail to save canvas.")
else: else:
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]): if not UserCanvasService.accessible(req["id"], current_user.id):
return get_json_result( return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.', data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR) code=RetCode.OPERATING_ERROR)
@ -100,10 +100,9 @@ def save():
@manager.route('/get/<canvas_id>', methods=['GET']) # noqa: F821 @manager.route('/get/<canvas_id>', methods=['GET']) # noqa: F821
@login_required @login_required
def get(canvas_id): def get(canvas_id):
e, c = UserCanvasService.get_by_tenant_id(canvas_id) if not UserCanvasService.accessible(canvas_id, current_user.id):
tids = [t.tenant_id for t in UserTenantService.query(user_id=current_user.id)]
if not e or (c["user_id"] != current_user.id and c["user_id"] not in tids):
return get_data_error_result(message="canvas not found.") return get_data_error_result(message="canvas not found.")
e, c = UserCanvasService.get_by_tenant_id(canvas_id)
return get_json_result(data=c) return get_json_result(data=c)
@ -132,14 +131,15 @@ def run():
files = req.get("files", []) files = req.get("files", [])
inputs = req.get("inputs", {}) inputs = req.get("inputs", {})
user_id = req.get("user_id", current_user.id) user_id = req.get("user_id", current_user.id)
e, cvs = UserCanvasService.get_by_id(req["id"]) if not UserCanvasService.accessible(req["id"], current_user.id):
if not e:
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result( return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.', data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR) code=RetCode.OPERATING_ERROR)
e, cvs = UserCanvasService.get_by_id(req["id"])
if not e:
return get_data_error_result(message="canvas not found.")
if not isinstance(cvs.dsl, str): if not isinstance(cvs.dsl, str):
cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False) cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False)
@ -173,14 +173,14 @@ def run():
@login_required @login_required
def reset(): def reset():
req = request.json req = request.json
if not UserCanvasService.accessible(req["id"], current_user.id):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
try: try:
e, user_canvas = UserCanvasService.get_by_id(req["id"]) e, user_canvas = UserCanvasService.get_by_id(req["id"])
if not e: if not e:
return get_data_error_result(message="canvas not found.") return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id) canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
canvas.reset() canvas.reset()
@ -291,15 +291,12 @@ def input_form():
@login_required @login_required
def debug(): def debug():
req = request.json req = request.json
if not UserCanvasService.accessible(req["id"], current_user.id):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
try: try:
e, user_canvas = UserCanvasService.get_by_id(req["id"]) e, user_canvas = UserCanvasService.get_by_id(req["id"])
if not e:
return get_data_error_result(message="canvas not found.")
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id) canvas = Canvas(json.dumps(user_canvas.dsl), current_user.id)
canvas.reset() canvas.reset()
canvas.message_id = get_uuid() canvas.message_id = get_uuid()
@ -405,6 +402,12 @@ def list_kbs():
def setting(): def setting():
req = request.json req = request.json
req["user_id"] = current_user.id req["user_id"] = current_user.id
if not UserCanvasService.accessible(req["id"], current_user.id):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
e,flow = UserCanvasService.get_by_id(req["id"]) e,flow = UserCanvasService.get_by_id(req["id"])
if not e: if not e:
return get_data_error_result(message="canvas not found.") return get_data_error_result(message="canvas not found.")
@ -416,10 +419,7 @@ def setting():
flow["permission"] = req["permission"] flow["permission"] = req["permission"]
if req["avatar"]: if req["avatar"]:
flow["avatar"] = req["avatar"] flow["avatar"] = req["avatar"]
if not UserCanvasService.query(user_id=current_user.id, id=req["id"]):
return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
num= UserCanvasService.update_by_id(req["id"], flow) num= UserCanvasService.update_by_id(req["id"], flow)
return get_json_result(data=num) return get_json_result(data=num)
@ -442,8 +442,10 @@ def trace():
@login_required @login_required
def sessions(canvas_id): def sessions(canvas_id):
tenant_id = current_user.id tenant_id = current_user.id
if not UserCanvasService.query(user_id=tenant_id, id=canvas_id): if not UserCanvasService.accessible(canvas_id, tenant_id):
return get_error_data_result(message=f"You don't own the agent {canvas_id}.") return get_json_result(
data=False, message='Only owner of canvas authorized for this operation.',
code=RetCode.OPERATING_ERROR)
user_id = request.args.get("user_id") user_id = request.args.get("user_id")
page_number = int(request.args.get("page", 1)) page_number = int(request.args.get("page", 1))

View File

@ -121,6 +121,18 @@ class UserCanvasService(CommonService):
agents = agents.paginate(page_number, items_per_page) agents = agents.paginate(page_number, items_per_page)
return list(agents.dicts()), count return list(agents.dicts()), count
@classmethod
@DB.connection_context()
def accessible(cls, canvas_id, tenant_id):
from api.db.services.user_service import UserTenantService
e, c = UserCanvasService.get_by_tenant_id(canvas_id)
if not e:
return False
tids = [t.tenant_id for t in UserTenantService.query(user_id=tenant_id)]
if c["user_id"] != canvas_id and c["user_id"] not in tids:
return False
return True
def completion(tenant_id, agent_id, session_id=None, **kwargs): def completion(tenant_id, agent_id, session_id=None, **kwargs):
query = kwargs.get("query", "") or kwargs.get("question", "") query = kwargs.get("query", "") or kwargs.get("question", "")