From 90eb5fd31b9d8b5fe0f354f495d9eb0d5195dfc9 Mon Sep 17 00:00:00 2001 From: Kevin Hu Date: Fri, 8 Aug 2025 18:31:51 +0800 Subject: [PATCH] Fix: canvas sharing bug. (#9339) ### What problem does this PR solve? ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue) --- api/apps/canvas_app.py | 54 ++++++++++++++++--------------- api/db/services/canvas_service.py | 12 +++++++ 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/api/apps/canvas_app.py b/api/apps/canvas_app.py index b94b29d12..cd335182f 100644 --- a/api/apps/canvas_app.py +++ b/api/apps/canvas_app.py @@ -62,7 +62,7 @@ def canvas_list(): @login_required def rm(): 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( data=False, message='Only owner of canvas authorized for this operation.', code=RetCode.OPERATING_ERROR) @@ -86,7 +86,7 @@ def save(): if not UserCanvasService.save(**req): return get_data_error_result(message="Fail to save canvas.") 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( data=False, message='Only owner of canvas authorized for this operation.', code=RetCode.OPERATING_ERROR) @@ -100,10 +100,9 @@ def save(): @manager.route('/get/', methods=['GET']) # noqa: F821 @login_required def get(canvas_id): - e, c = UserCanvasService.get_by_tenant_id(canvas_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): + if not UserCanvasService.accessible(canvas_id, current_user.id): return get_data_error_result(message="canvas not found.") + e, c = UserCanvasService.get_by_tenant_id(canvas_id) return get_json_result(data=c) @@ -132,14 +131,15 @@ def run(): files = req.get("files", []) inputs = req.get("inputs", {}) user_id = req.get("user_id", current_user.id) - e, cvs = 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"]): + 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, 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): cvs.dsl = json.dumps(cvs.dsl, ensure_ascii=False) @@ -173,14 +173,14 @@ def run(): @login_required def reset(): 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: 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.reset() @@ -291,15 +291,12 @@ def input_form(): @login_required def debug(): 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: 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.reset() canvas.message_id = get_uuid() @@ -405,6 +402,12 @@ def list_kbs(): def setting(): req = request.json 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"]) if not e: return get_data_error_result(message="canvas not found.") @@ -416,10 +419,7 @@ def setting(): flow["permission"] = req["permission"] if 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) return get_json_result(data=num) @@ -442,8 +442,10 @@ def trace(): @login_required def sessions(canvas_id): tenant_id = current_user.id - if not UserCanvasService.query(user_id=tenant_id, id=canvas_id): - return get_error_data_result(message=f"You don't own the agent {canvas_id}.") + if not UserCanvasService.accessible(canvas_id, tenant_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") page_number = int(request.args.get("page", 1)) diff --git a/api/db/services/canvas_service.py b/api/db/services/canvas_service.py index 09efe68ec..98d17e1d8 100644 --- a/api/db/services/canvas_service.py +++ b/api/db/services/canvas_service.py @@ -121,6 +121,18 @@ class UserCanvasService(CommonService): agents = agents.paginate(page_number, items_per_page) 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): query = kwargs.get("query", "") or kwargs.get("question", "")