-
Notifications
You must be signed in to change notification settings - Fork 2
feat: support multi-user #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: cap
Are you sure you want to change the base?
Conversation
bfeaec8 to
6b5bb81
Compare
Change-Id: I1dbd079817dbb351eba8f7ce2e72121b163a6f05
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
相比于 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
user_optional 是有必要的吗?在哪里会用到呢?
src/code/agent/utils/user_auth.py
Outdated
| return None | ||
|
|
||
|
|
||
| def user_required(func): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 模块名: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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
如果这个需要每个 handler 都定义一个,是不是可以放到 @self.bp.before_request 里?
| } | ||
| }), 400 | ||
|
|
||
| # 注入user_id到extra_data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
中英文之前有空格
| client_id = "" | ||
|
|
||
| # 注入user_id到extra_data | ||
| user_id = getattr(g, 'user_id', 'default') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
constants 看起来没被用到?
| ) | ||
| return user_id | ||
|
|
||
| return 'system' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这里返回 '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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
在此之前,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: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fallback_id 太怪了
|
|
||
| for task_id, task in self._tasks.items(): | ||
| # 只清理当前用户的任务 | ||
| if task.user_id != user_id: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
有一个方法是 get_current_user_tasks,可以复用吗?
|
|
||
| # 只有当任务确实是运行中状态时才减少计数 | ||
| # 这里再次检查状态,确保计数器准确 | ||
| if old_status in [TaskStatus.PENDING, TaskStatus.RUNNING]: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
298 行已经判断过了,这里是不是不需要再判断了?
| self._running_count_by_user[user_id] -= 1 | ||
|
|
||
| cancelled = True | ||
| should_stop_polling = True |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
同理: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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
History 原子操作辅助方法存在的意义是什么呢?
| # 单节点任务执行结束 | ||
| data = message.get("data", {}) | ||
| prompt_id = data.get("prompt_id") | ||
| node_id = data.get("node") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
这个 node_id 是有用的不?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
若中间节点有输出,history会返回该工作流的所有output,元数据有nodeId,表示是那个节点的输出。
1dcd1a8 to
21576ad
Compare
dfee1e1 to
bc10f1c
Compare
Change-Id: I1dbd079817dbb351eba8f7ce2e72121b163a6f05