Conversation
6b5bb81 to
141f860
Compare
src/code/agent/utils/user_auth.py
Outdated
| 1. JWT 方式:从 Art-Comfy-User header 提取(网关解析 JWT 后注入) | ||
| 2. Basic Auth 方式:从 Authorization: Basic header 中解析 username | ||
|
|
||
| 通过 ENABLE_COMFYUI_USER 环境变量控制: |
There was a problem hiding this comment.
相比于 ENABLE_COMFYUI_USER,ENABLE_MULTI_USER 是不是会好一些?
src/code/agent/utils/user_auth.py
Outdated
| return decorated_function | ||
|
|
||
|
|
||
| def user_optional(func): |
There was a problem hiding this comment.
user_optional 是有必要的吗?在哪里会用到呢?
src/code/agent/utils/user_auth.py
Outdated
| return None | ||
|
|
||
|
|
||
| def user_required(func): |
There was a problem hiding this comment.
- 模块名:user_auth => user_identity.py
- 函数名:user_required => identify_user # 明确表达:从多租户环境中识别用户
- 函数名:user_optional => identify_user_or_default
identify (识别) 比 auth (认证) 更准确,因为它描述的是“你是谁”,而不是“你的密码对不对”。
user_identity 作为一个模块名,清晰地告诉别人这里是处理用户身份识别逻辑的地方。
or_default 后缀比 optional 更清楚地说明了“如果获取不到会发生什么”(即:降级到默认用户)。
|
|
||
| def _register_prompt_handler(self): | ||
| @self.bp.route("/prompt", methods=["POST"]) | ||
| @user_required |
There was a problem hiding this comment.
如果这个需要每个 handler 都定义一个,是不是可以放到 @self.bp.before_request 里?
| } | ||
| }), 400 | ||
|
|
||
| # 注入user_id到extra_data |
| client_id = "" | ||
|
|
||
| # 注入user_id到extra_data | ||
| user_id = getattr(g, 'user_id', 'default') |
There was a problem hiding this comment.
serverless_handler 有必要修改么?webui 是不是不会走到这里?
| from services.process.websocket.websocket_manager import ws_manager | ||
| from utils.logger import log | ||
| from utils.user_auth import extract_user_from_header | ||
| import constants |
| ) | ||
| return user_id | ||
|
|
||
| return 'system' |
There was a problem hiding this comment.
这里返回 'system' 有什么特殊的考量吗?
其他的都是 getattr(g, 'user_id', 'default')
| return self._history_helper.get_history(user_id, max_items, offset) | ||
|
|
||
| @staticmethod | ||
| def _extract_prompt_id_from_body(prompt_body: dict, fallback_id: str) -> str: |
There was a problem hiding this comment.
在此之前,prompt_id 和 task_id 是一样的吗?
| return self._history_helper.get_history(user_id, max_items, offset) | ||
|
|
||
| @staticmethod | ||
| def _extract_prompt_id_from_body(prompt_body: dict, fallback_id: str) -> str: |
|
|
||
| for task_id, task in self._tasks.items(): | ||
| # 只清理当前用户的任务 | ||
| if task.user_id != user_id: |
There was a problem hiding this comment.
有一个方法是 get_current_user_tasks,可以复用吗?
|
|
||
| # 只有当任务确实是运行中状态时才减少计数 | ||
| # 这里再次检查状态,确保计数器准确 | ||
| if old_status in [TaskStatus.PENDING, TaskStatus.RUNNING]: |
| self._running_count_by_user[user_id] -= 1 | ||
|
|
||
| cancelled = True | ||
| should_stop_polling = True |
There was a problem hiding this comment.
同理:cancelled 和 should_stop_polling 这两个变量是不是也没必要了?
| except Exception as e: | ||
| log("ERROR", f"[TaskManager] Error stopping poller for task {task_id}: {e}") | ||
|
|
||
| # ==================== History 原子操作辅助方法(委托给 HistoryHelper)==================== |
There was a problem hiding this comment.
History 原子操作辅助方法存在的意义是什么呢?
| # 单节点任务执行结束 | ||
| data = message.get("data", {}) | ||
| prompt_id = data.get("prompt_id") | ||
| node_id = data.get("node") |
There was a problem hiding this comment.
若中间节点有输出,history会返回该工作流的所有output,元数据有nodeId,表示是那个节点的输出。
dfee1e1 to
bc10f1c
Compare
Change-Id: I1dbd079817dbb351eba8f7ce2e72121b163a6f05
7597cb1 to
74e1aa8
Compare
| @@ -19,8 +19,8 @@ | |||
| from utils.logger import log | |||
|
|
|||
|
|
|||
| # 认证相关常量 | |||
| JWT_USER_HEADER = 'Art-Comfy-User' | |||
There was a problem hiding this comment.
这个 header 常量放到 constants 里吧
| user_id = getattr(g, 'user_id', 'default') | ||
| if 'extra_data' not in request_data: | ||
| request_data['extra_data'] = {} | ||
| request_data['extra_data']['user_id'] = user_id |
There was a problem hiding this comment.
注入到 body 里是必要的吗?
/prompt 通过 task_manager 转发给 GPU 函数的时候是带着 x-art-comfy-user 的 header 的
33aa93a to
f703d8d
Compare
Change-Id: Ia655542268d9dce4a56132cfcf62f751635f4aa0
f703d8d to
2e08f11
Compare
src/code/agent/constants.py
Outdated
| ENABLE_COMFYUI_MULTI_USER = os.getenv('ENABLE_COMFYUI_MULTI_USER', '').lower() == 'true' | ||
|
|
||
| # 用户身份识别相关常量 | ||
| JWT_USER_HEADER = 'X-Art-Comfy-User' |
There was a problem hiding this comment.
改个名:
HEADER_FUNART_COMFY_USERID = 'X-FunArt-Comfy-UserId'
| user_id = getattr(g, 'user_id', 'default') | ||
| if 'extra_data' not in request_data: | ||
| request_data['extra_data'] = {} | ||
| request_data['extra_data']['x-art-comfy-user'] = user_id |
There was a problem hiding this comment.
x-art-comfy-user 不 hardcode,引用 consts
Change-Id: If2c4c240aa2d33650f992cd707779063bec16215
| from utils.logger import log | ||
|
|
||
|
|
||
| class HistoryHelper: |
There was a problem hiding this comment.
这个类叫 Helper 不太合适,实际上,他包含了完整的 crud
建议叫 HistoryManager
| with self._lock: | ||
| return self._tasks.get(task_id) | ||
|
|
||
| def get_user_running_count(self, user_id: str) -> int: |
There was a problem hiding this comment.
=> get_running_task_count_by_user
Change-Id: I9491b4b7c601219775f8964d722823539714cc17
Change-Id: Iaedb020f0aace2518969f96f6b5f19d1851c9163
ee792c6 to
6c8c530
Compare
Change-Id: I1dbd079817dbb351eba8f7ce2e72121b163a6f05