feat(admin): Add user management and upgrade to module permission system
Features - User Management (Phase 4.1): - Database: Add user_modules table for fine-grained module permissions - Database: Add 4 user permissions (view/create/edit/delete) to role_permissions - Backend: UserService (780 lines) - CRUD with tenant isolation - Backend: UserController + UserRoutes (648 lines) - 13 API endpoints - Backend: Batch import users from Excel - Frontend: UserListPage (412 lines) - list/filter/search/pagination - Frontend: UserFormPage (341 lines) - create/edit with module config - Frontend: UserDetailPage (393 lines) - details/tenant/module management - Frontend: 3 modal components (592 lines) - import/assign/configure - API: GET/POST/PUT/DELETE /api/admin/users/* endpoints Architecture Upgrade - Module Permission System: - Backend: Add getUserModules() method in auth.service - Backend: Login API returns modules array in user object - Frontend: AuthContext adds hasModule() method - Frontend: Navigation filters modules based on user.modules - Frontend: RouteGuard checks requiredModule instead of requiredVersion - Frontend: Remove deprecated version-based permission system - UX: Only show accessible modules in navigation (clean UI) - UX: Smart redirect after login (avoid 403 for regular users) Fixes: - Fix UTF-8 encoding corruption in ~100 docs files - Fix pageSize type conversion in userService (String to Number) - Fix authUser undefined error in TopNavigation - Fix login redirect logic with role-based access check - Update Git commit guidelines v1.2 with UTF-8 safety rules Database Changes: - CREATE TABLE user_modules (user_id, tenant_id, module_code, is_enabled) - ADD UNIQUE CONSTRAINT (user_id, tenant_id, module_code) - INSERT 4 permissions + role assignments - UPDATE PUBLIC tenant with 8 module subscriptions Technical: - Backend: 5 new files (~2400 lines) - Frontend: 10 new files (~2500 lines) - Docs: 1 development record + 2 status updates + 1 guideline update - Total: ~4900 lines of code Status: User management 100% complete, module permission system operational
This commit is contained in:
@@ -1,55 +1,63 @@
|
||||
# **CTO 代码审查报告:AI临床研究平台部署架构**
|
||||
|
||||
螳。譬ク蟇ケ雎。<EFBFBD>?莉ス迢ャ遶矩Κ鄂イ譁<EFBDB2>。?(Dify/Python/Node/Frontend/PostgreSQL)
|
||||
螳。譬ク莠コ<EFBFBD>夊劒諡滓楔譫<EFBFBD>ク?
|
||||
扈楢ョコ<EFBFBD>哂- (莨倡ァ)縲よ楔譫<E6A594>ョセ隶。隨ヲ蜷井コ大次逕溽炊蠢オ<E8A0A2>梧<EFBFBD>譛ャ荳取黄螻墓ァ蟷ウ陦。濶ッ螂ス縲ゆス<E38286>ュ伜惠鄂醍サ懷<EFBDBB>蜿」蜥御セ晁オ夜溜邇ッ荳、荳ェ蜈ウ髞ョ鬟朱勦轤ケ髴隗」蜀ウ縲?
|
||||
## **1\. 讓。蝮礼コァ豺ア蠎ヲ螳。隶?(Module-Level Audit)**
|
||||
审核对象:5份独立部署文档 (Dify/Python/Node/Frontend/PostgreSQL)
|
||||
审核人:虚拟架构师
|
||||
结论:A- (优秀)。架构设计符合云原生理念,成本与扩展性平衡良好。但存在网络出口和依赖闭环两个关键风险点需解决。
|
||||
|
||||
### **笨?1.1 蜑咲ォッ Nginx (SAE)**
|
||||
## **1\. 模块级深度审计 (Module-Level Audit)**
|
||||
|
||||
* **莨倡せ**<2A>壼、夐亳谿オ譫<EFBDB5>サコ莨倡ァ<EFBDA7>井ス鍋ァッ蟆擾シ会シ帷識蠅<E8AD98>序驥乗ウィ蜈・譁ケ譯茨シ<E88CA8>nvsubst<73>蛾撼蟶ク荳謎ク夲シ瑚ァ」蜀ウ莠<EFBDB3>撕諤<E69295>。オ髱「譌<EFBDA2>豕募勘諤<E58B98><E8ABA4>鄂ョ蜷守ォッ逧<EFBDAF>埓鬚倥?
|
||||
* **菫ョ豁」蟒コ隶ョ**<2A>?
|
||||
* 遑ョ隶、 nginx.conf 荳ュ蠑蜷?gzip<69>瑚ソ吝ッ?React 螟ァ菴鍋ァ?JS 譁<>サカ閾ウ蜈ウ驥崎ヲ√?
|
||||
* 譽譟?Nginx 逧?client\_max\_body\_size 驟咲スョ縲ょ現逍?PDF/Excel 蜿ッ閭ス雜<EFBDBD>ソ<EFBFBD>サ倩ョ、逧?1MB<4D>悟サコ隶ョ隶セ鄂ョ荳コ 50M縲?
|
||||
### **笨?1.2 蜷守ォッ Node.js (SAE)**
|
||||
### **✅ 1.1 前端 Nginx (SAE)**
|
||||
|
||||
* **莨倡せ**<2A>啀risma "蜿榊髄蜷梧ュ・" 豬∫ィ矩撼蟶ク蜉。螳橸シ瑚ァ」蜀ウ莠<EFBDB3>シ蜿台ケ<E58FB0>諠ッ荳崎ァ<E5B48E>激逧<E6BF80>琉鬚倥1ostgres-Only 逧<>楔譫<E6A594>栫螟ァ蝨ー髯堺ス惹コ<E683B9>ソ千サエ雍滓球縲?
|
||||
* **菫ョ豁」蟒コ隶ョ**<2A>?
|
||||
* **霑樊磁豕<E7A381>シ城」朱勦**<2A>啀ython 譛榊苅螯よ棡蜩榊コ疲<EFBDBA><E796B2>悟錘遶ッ逧?HTTP Client 隶セ鄂ョ雜<EFBDAE>慮莠<E685AE>雛<EFBFBD>溷サコ隶ョ隶セ鄂?timeout: 30s<30>碁亟豁「蜷守ォッ霑樊磁謨ー蝣<EFBDB0>ァッ縲?
|
||||
### **笨?1.3 Python 蠕ョ譛榊<E8AD9B>?(SAE)**
|
||||
* **优点**:多阶段构建优秀(体积小);环境变量注入方案(envsubst)非常专业,解决了静态页面无法动态配置后端的难题。
|
||||
* **修正建议**:
|
||||
* 确认 nginx.conf 中开启 gzip,这对 React 大体积 JS 文件至关重要。
|
||||
* 检查 Nginx 的 client\_max\_body\_size 配置。医疗 PDF/Excel 可能超过默认的 1MB,建议设置为 50M。
|
||||
|
||||
* **莨倡せ**<2A>壽<EFBFBD>遑ョ謖<EFBDAE><E8AC96>莠<EFBFBD> libGL 遲臥ウサ扈滉セ晁オ夜琉鬚假シ瑚ソ呎弍 Python 螳ケ蝎ィ蛹匁怙螟ァ逧<EFBDA7>搗<EFBFBD>梧枚譯」蟾イ謠仙燕隗<E78795>∩縲?
|
||||
* **菫ョ豁」蟒コ隶ョ**<2A>?
|
||||
* **OOM 鬟朱勦**<2A>啀ython 霑帷ィ具シ亥ー、蜈カ譏ッ PyMuPDF/OCR<43>蛾撼蟶ク蜷<EFBDB8><E89CB7>蟄倥ょ惠 2G 蜀<>ュ倬剞蛻カ荳具シ悟苅蠢<E88B85>剞蛻カ蟷カ蜿第焚<E7ACAC><E7849A>unicorn Workers 荳崎ヲ∬カ<E288AC>ソ<EFBFBD> 2 荳ェ<E88DB3>峨?
|
||||
### **笨?1.4 Dify (ECS)**
|
||||
### **✅ 1.2 后端 Node.js (SAE)**
|
||||
|
||||
* **莨倡せ**<2A>夐画叫莠?ECS 驛ィ鄂イ莉・菫晁ッ∵焚謐ョ遘∵怏蛹厄シ悟酔譌カ菴ソ逕?Swap 髦イ豁「 OOM<4F>碁撼蟶ク諛り。後?
|
||||
* **菫ョ豁」蟒コ隶ョ**<2A>?
|
||||
* **螳牙<EFBFBD>諤?*<2A>哘CS 逧?Redis 遶ッ蜿」 (6379) 蜥?Weaviate 遶ッ蜿」 (8080) **扈晏ッケ荳崎ヲ<E5B48E>**蟇ケ蜈ャ鄂大シ謾セ縲ゆサ<E38286><EFBDBB>隶ク localhost 蜥?VPC 蜀<>ス題ョソ髣ョ縲?
|
||||
### **笨?1.5 謨ー謐ョ蠎?(RDS)**
|
||||
* **优点**:Prisma "反向同步" 流程非常务实,解决了开发习惯不规范的问题。Postgres-Only 的架构极大地降低了运维负担。
|
||||
* **修正建议**:
|
||||
* **连接泄漏风险**:Python 服务如果响应慢,后端的 HTTP Client 设置超时了吗?建议设置 timeout: 30s,防止后端连接数堆积。
|
||||
|
||||
* **莨倡せ**<2A>售chema 髫皮ヲサ隶セ隶。譫∽スウ縲?
|
||||
* **菫ョ豁」蟒コ隶ョ**<2A>?
|
||||
* **Dify 謨ー謐ョ蠎馴囈遖?*<2A>夂。ョ隶?Dify 菴ソ逕ィ逧<EFBDA8>弍迢ャ遶狗<E981B6>?dify\_prod 蠎難シ御ク崎ヲ∝柱荳壼苅陦ィ豺キ蝨ィ ai\_clinical\_research 蠎謎クュ<EFBDB8>碁亟豁?Dify 蜊<>コァ閼壽悽隸ッ蛻<EFBDAF>荳壼苅陦ィ縲?
|
||||
## **2\. 霍ィ讓。蝮鈴寔謌宣」朱<EFBDA3>?(Integration Risks)**
|
||||
### **✅ 1.3 Python 微服务 (SAE)**
|
||||
|
||||
### **<2A>圷 鬟朱勦荳<E88DB3>售AE 逧?蟄、蟯帶譜蠎<E8AD9C>" (Internet Access)**
|
||||
* **优点**:明确指出了 libGL 等系统依赖问题,这是 Python 容器化最大的坑,文档已提前规避。
|
||||
* **修正建议**:
|
||||
* **OOM 风险**:Python 进程(尤其是 PyMuPDF/OCR)非常吃内存。在 2G 内存限制下,务必限制并发数(Gunicorn Workers 不要超过 2 个)。
|
||||
|
||||
* **髣ョ鬚<EFBDAE>**<2A>售AE 驛ィ鄂イ蝨?VPC 蜀<>シ碁サ倩ョ、**豐。譛牙<E8AD9B>鄂大<E98482>蜿」**縲?
|
||||
* **蝨コ譎ッ**<2A>壼錘遶ッ隹<EFBDAF><E99AB9>?DeepSeek API縲 ̄ython 荳玖スス蜈ャ鄂<EFBDAC> PDF縲¨PM 螳芽」<E88ABD>セ晁オ厄シ域桷蟒コ譌カ<E8AD8C>峨?
|
||||
* **蟇ケ遲<EFBFBD>**<2A>壼ソ<E5A3BC>。サ蝨ィ VPC 荳ュ驟咲ス?**NAT 鄂大<E98482>** (謗ィ闕<EFBDA8>) 謌也。ョ菫?SAE 譛臥サ大ョ壼<EFBDAE>鄂?IP 逧<><E980A7>蜉帙?*蜷ヲ蛻吩ク顔コソ蠖灘、ゥ謇譛?AI 蜉溯<E89C89>驛ス莨夊カ<E5A48A>慮縲?*
|
||||
### **✅ 1.4 Dify (ECS)**
|
||||
|
||||
* **优点**:选择了 ECS 部署以保证数据私有化,同时使用 Swap 防止 OOM,非常懂行。
|
||||
* **修正建议**:
|
||||
* **安全性**:ECS 的 Redis 端口 (6379) 和 Weaviate 端口 (8080) **绝对不要**对公网开放。仅允许 localhost 和 VPC 内网访问。
|
||||
|
||||
### **✅ 1.5 数据库 (RDS)**
|
||||
|
||||
* **优点**:Schema 隔离设计极佳。
|
||||
* **修正建议**:
|
||||
* **Dify 数据库隔离**:确认 Dify 使用的是独立的 dify\_prod 库,不要和业务表混在 ai\_clinical\_research 库中,防止 Dify 升级脚本误删业务表。
|
||||
|
||||
## **2\. 跨模块集成风险 (Integration Risks)**
|
||||
|
||||
### **🚨 风险一:SAE 的"孤岛效应" (Internet Access)**
|
||||
|
||||
* **问题**:SAE 部署在 VPC 内,默认**没有公网出口**。
|
||||
* **场景**:后端调用 DeepSeek API、Python 下载公网 PDF、NPM 安装依赖(构建时)。
|
||||
* **对策**:必须在 VPC 中配置 **NAT 网关** (推荐) 或确保 SAE 有绑定公网 IP 的能力。**否则上线当天所有 AI 功能都会超时。**
|
||||
|
||||
### **🔄 风险二:部署依赖死锁 (Deployment Deadlock)**
|
||||
|
||||
* **邇ー雎。**<2A>?
|
||||
1. 蜷守ォッ蜷ッ蜉ィ髴隕?DIFY\_API\_KEY縲?
|
||||
2. DIFY\_API\_KEY 髴隕?Dify 蜷ッ蜉ィ蟷カ莠コ蟾・逋サ蠖募錘謇崎<EFBFBD>逕滓<EFBFBD>縲?
|
||||
3. 蜷守ォッ螯よ棡驟咲スョ莠?蛛・蠎キ譽譟・螟ア雍・蛻咎㍾蜷ッ"<22>悟惠蝪ォ蜈・ Key 荵句燕莨壽裏髯宣㍾蜷ッ縲?
|
||||
* **蟇ケ遲<EFBFBD>**<2A>夐ヲ匁ャ。驛ィ鄂イ譌カ<E8AD8C>悟錘遶ッ邇ッ蠅<EFBDAF>序驥?DIFY\_API\_KEY 蜿ッ莉・蜈亥。ォ荳ェ蛛<EFBDAA>シ<C280>亥ヲ?temp<6D>会シ瑚ョゥ譛榊苅霍題オキ譚・縲らュ<E38289> Dify 驛ィ鄂イ螂ス諡ソ蛻ー逵<EFBDB0> Key 蜷趣シ梧峩譁ー SAE 驟咲スョ蟷カ驥榊星縲?
|
||||
### **<2A>倹 鬟朱勦荳会シ壼燕遶ッ荳?Dify 逧<>キィ蝓?(CORS)**
|
||||
* **现象**:
|
||||
1. 后端启动需要 DIFY\_API\_KEY。
|
||||
2. DIFY\_API\_KEY 需要 Dify 启动并人工登录后才能生成。
|
||||
3. 后端如果配置了"健康检查失败则重启",在填入 Key 之前会无限重启。
|
||||
* **对策**:首次部署时,后端环境变量 DIFY\_API\_KEY 可以先填个假值(如 temp),让服务跑起来。等 Dify 部署好拿到真 Key 后,更新 SAE 配置并重启。
|
||||
|
||||
### **🌐 风险三:前端与 Dify 的跨域 (CORS)**
|
||||
|
||||
* **问题**:前端直接调用后端(通过 Nginx 代理)没问题。但如果前端需要**直接嵌入** Dify 的 Web UI(如 iframe)或直接调用 Dify API(绕过后端),会遇到 CORS。
|
||||
* **对策**:坚持\*\*"所有请求走后端"\*\*的原则。前端 \-\> Nginx \-\> 后端 \-\> Dify。不要让前端直连 Dify,既安全又避免 CORS。
|
||||
|
||||
* **髣ョ鬚<EFBDAE>**<2A>壼燕遶ッ逶エ謗・隹<EFBDA5>畑蜷守ォッ<EFBDAB>磯夊ソ<E5A48A> Nginx 莉」逅<EFBDA3>シ画イ。髣ョ鬚倥ゆス<E38286>ヲよ棡蜑咲ォッ髴隕?*逶エ謗・蠏悟<E8A08F>** Dify 逧?Web UI<55>亥ヲ<E4BAA5> iframe<6D>画<EFBFBD>逶エ謗・隹<EFBDA5>畑 Dify API<50>育サ戊ソ<E6888A>錘遶ッ<E981B6>会シ御シ夐∞蛻ー CORS縲?
|
||||
* **蟇ケ遲<EFBDB9>**<2A>壼撓謖―*\*"謇譛芽ッキ豎りオー蜷守ォッ"\*\*逧<>次蛻吶ょ燕遶?\-\> Nginx \-\> 蜷守ォッ \-\> Dify縲ゆク崎ヲ∬ョゥ蜑咲ォッ逶エ霑<EFBDB4> Dify<66>梧里螳牙<E89EB3>蜿磯∩蜈?CORS縲?
|
||||
## **3\. 架构关系图谱**
|
||||
|
||||
\[浏览器\]
|
||||
@@ -69,18 +77,19 @@
|
||||
|
|
||||
\+--(HTTPS)--\> \[OSS 对象存储\]
|
||||
|
|
||||
\+--(NAT鄂大<EFBFBD>)--\> \[莠定#鄂? DeepSeek/OpenAI\]
|
||||
\+--(NAT网关)--\> \[互联网: DeepSeek/OpenAI\]
|
||||
|
||||
## **4\. 扈?1-2 莠コ蝗「髦溽噪逕溷ュ伜サコ隶ョ**
|
||||
## **4\. 给 1-2 人团队的生存建议**
|
||||
|
||||
1. **逵<EFBFBD>蝶鮟醍ァ第橿**<EFBFBD>?
|
||||
* SAE 2.0 譛?*髣イ鄂ョ隶。雍ケ**蜉溯<E89C89>縲ょシ蜿醍識蠅<E8AD98>シ域オ玖ッ慕識蠅<E8AD98>シ牙苅蠢<E88B85>シ蜷ッ<E89CB7>梧イ。莠コ逕ィ譌カ荳肴噺 CPU/蜀<>ュ<EFBFBD> 雍ケ縲?
|
||||
* RDS 雍ュ荵ー**騾夂畑蝙?* (2譬?G) 蜊ウ蜿ッ<EFBFBD>御ク崎ヲ∽ケー迢ャ莠ォ蝙具シ悟、溽畑蠕井ケ<EFBFBD>?
|
||||
2. **荳崎ヲ∬<EFBFBD>蟒コ逶第而**<EFBFBD>?
|
||||
* 逶エ謗・逕ィ髦ソ驥御コ<EFBFBD> **ARMS** (蠎皮畑螳樊慮逶第而譛榊苅) 逧<><E980A7>雍ケ鬚晏コヲ謌門渕遑迚医ゆク崎ヲ∬<EFBDA6>蟾ア謳ュ Prometheus \+ Grafana<EFBFBD>檎サエ謚、謌先悽螟ェ鬮倥?
|
||||
3. **謨ー謐ョ螟<EFBFBD>サス譏ッ蠎慕コ?*<2A>?
|
||||
* RDS 蠑蜷ッ閾ェ蜉ィ螟<EFBFBD>サス<EFBFBD>井ソ晉蕗7螟ゥ<EFBFBD>峨?
|
||||
* ECS 荳顔噪 Dify docker-compose.yaml 蜥?.env 譁<EFBFBD>サカ<EFBFBD>悟苅蠢<EFBFBD>惠譛ャ蝨ー謌?Git 遘∵怏莉灘コ灘、<E78198>サス荳莉ス縲<EFBDBD>CS 豐。莠<EFBDA1>庄莉・驥堺ケー<EFBDB9>碁<EFBFBD>鄂ョ譁<EFBDAE>サカ豐。莠<EFBDA1>ーア蠕鈴㍾驟阪?
|
||||
4. **蠑蜿第譜邇?*<2A>?
|
||||
* 蛻ゥ逕ィ ECS 蛛?*霍ウ譚ソ譛?*<2A>梧悽蝨ー逶エ霑?RDS 蠑蜿代ゆク崎ヲ∵ッ乗ャ。驛ス蜀吩サ」遐∝悉譟・謨ー謐ョ縲?
|
||||
**譛扈育サ楢ョ?*<2A>夊ソ吝・玲楔譫<E6A594>ョセ隶。蠕鈴撼蟶ク謇主ョ橸シ悟ョ悟<EFBDAE>蜿ッ莉・謾ッ謦台サ<E58FB0> 0 蛻?10 荳<>畑謌キ逧<EFBDB7>ァ<EFBFBD>ィ。縲りッキ驥咲せ隗」蜀ウ **"SAE 隶ソ髣ョ蜈ャ鄂<EFBDAC> (NAT)"** 霑吩クェ髣ョ鬚假シ悟叉蜿ッ蠑蟋矩Κ鄂イ縲
|
||||
1. **省钱黑科技**:
|
||||
* SAE 2.0 有**闲置计费**功能。开发环境(测试环境)务必开启,没人用时不收 CPU/内存 费。
|
||||
* RDS 购买**通用型** (2核4G) 即可,不要买独享型,够用很久。
|
||||
2. **不要自建监控**:
|
||||
* 直接用阿里云 **ARMS** (应用实时监控服务) 的免费额度或基础版。不要自己搭 Prometheus \+ Grafana,维护成本太高。
|
||||
3. **数据备份是底线**:
|
||||
* RDS 开启自动备份(保留7天)。
|
||||
* ECS 上的 Dify docker-compose.yaml 和 .env 文件,务必在本地或 Git 私有仓库备份一份。ECS 没了可以重买,配置文件没了就得重配。
|
||||
4. **开发效率**:
|
||||
* 利用 ECS 做**跳板机**,本地直连 RDS 开发。不要每次都写代码去查数据。
|
||||
|
||||
**最终结论**:这套架构设计得非常扎实,完全可以支撑从 0 到 10 万用户的规模。请重点解决 **"SAE 访问公网 (NAT)"** 这个问题,即可开始部署。
|
||||
Reference in New Issue
Block a user