refactor: P6 API v1 版本化
- src/routes/v1.py:注册中心,148 条路由全部挂 /api/v1 - application/views/__init__.py:自动发现改为 register_v1 显式注册 - 登录白名单更新为 /api/v1/login 等(.env 与 .env.example) - build_full_url:内部调度调用自动加 /api/v1 前缀 【联动】ui/ 前端需将 API 调用前缀改为 /api/v1(随 ui/ 迁移处理) 【验收】148 路由全 /api/v1;白名单放行(/api/v1/login 表单校验); 鉴权拦截 401;build_full_url 验证;12 passed Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
4b0b28105c
commit
4d74b31431
+3
-3
@@ -76,9 +76,9 @@ INTERNAL_API_KEY=<必填>
|
||||
INTERNAL_ALLOWED_IPS=127.0.0.1
|
||||
|
||||
# 登录白名单(以下路径跳过登录校验)
|
||||
LOGIN_WHITELIST_EXACT=/login,/captcha,/favicon.ico
|
||||
LOGIN_WHITELIST_PREFIX=/job/sendSms,/public,/static,/api/webhook
|
||||
LOGIN_WHITELIST_WILDCARD=/job/*/send*,/api/v1/*/public*
|
||||
LOGIN_WHITELIST_EXACT=/api/v1/login,/api/v1/captcha,/favicon.ico
|
||||
LOGIN_WHITELIST_PREFIX=/api/v1/job/sendSms,/public,/static,/api/webhook
|
||||
LOGIN_WHITELIST_WILDCARD=/api/v1/job/*/send*,/api/v1/*/public*
|
||||
LOGIN_WHITELIST_DEBUG=True
|
||||
LOGIN_WHITELIST_LOG_ACCESS=True
|
||||
|
||||
|
||||
@@ -102,36 +102,16 @@ _blueprint_modules = [
|
||||
|
||||
def register_blueprint(app):
|
||||
"""
|
||||
自动导入所有视图模块并注册蓝图到Flask应用实例
|
||||
注册 API v1 路由到 Flask 应用实例
|
||||
|
||||
功能说明:
|
||||
遍历 _blueprint_modules 列表,动态导入每个视图模块,
|
||||
自动发现模块中的 Blueprint 实例并注册到应用。
|
||||
此函数在应用启动时调用(通常位于 create_app 工厂函数中)。
|
||||
所有业务蓝图统一挂载到 /api/v1 前缀(见 src/routes/v1.py)。
|
||||
原自动发现机制已由 routes/v1.py 的显式注册取代。
|
||||
|
||||
Args:
|
||||
app: Flask应用实例
|
||||
|
||||
Returns:
|
||||
Flask: 注册完成后的Flask应用实例
|
||||
|
||||
Example:
|
||||
# 在应用工厂函数中调用
|
||||
def create_app():
|
||||
app = Flask(__name__)
|
||||
# ... 其他配置 ...
|
||||
register_blueprint(app)
|
||||
return app
|
||||
"""
|
||||
registered = set()
|
||||
for module_name in _blueprint_modules:
|
||||
mod = importlib.import_module(f'application.views.{module_name}')
|
||||
for attr_name in dir(mod):
|
||||
attr = getattr(mod, attr_name)
|
||||
if isinstance(attr, Blueprint):
|
||||
# 合并模块的 shim 会重复导出同一批 Blueprint,按名去重
|
||||
if attr.name in registered:
|
||||
continue
|
||||
app.register_blueprint(attr)
|
||||
registered.add(attr.name)
|
||||
return app
|
||||
from src.routes.v1 import register_v1
|
||||
return register_v1(app)
|
||||
|
||||
@@ -132,6 +132,9 @@ def build_full_url(url: str) -> str:
|
||||
|
||||
# 相对路径,拼接站点域名
|
||||
if url.startswith("/"):
|
||||
# 内部 API 调用统一挂到 /api/v1(P6 API 版本化)
|
||||
if not url.startswith("/api/"):
|
||||
url = f"/api/v1{url}"
|
||||
url = f"{FLASK_SITE_DOMAIN}{url}"
|
||||
|
||||
return url
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
"""路由注册中心包。"""
|
||||
@@ -0,0 +1,61 @@
|
||||
"""
|
||||
API v1 路由注册中心
|
||||
=============================================================
|
||||
|
||||
所有业务蓝图统一挂载到 /api/v1 前缀下:
|
||||
- 模块内蓝图保持各自的 url_prefix(如 /user、/role)
|
||||
- 整体前缀由 v1 父蓝图提供 → /api/v1/user/page 等
|
||||
|
||||
联动说明:
|
||||
- 登录白名单需改为 /api/v1/login 等(见 config/auth.py 与 .env)
|
||||
- 内部 HTTP 调用(定时任务)需追加 /api/v1
|
||||
"""
|
||||
|
||||
from flask import Blueprint
|
||||
|
||||
from src.modules.auth.router import login_blue, index_blue
|
||||
from src.modules.association.role_menu.router import role_menu_blue
|
||||
from src.modules.association.user_role.router import user_role_blue
|
||||
from src.modules.city.router import city_blue
|
||||
from src.modules.cms.article.router import article_blue
|
||||
from src.modules.cms.category.router import category_blue
|
||||
from src.modules.cms.link.router import link_blue
|
||||
from src.modules.configuration.router import config_blue, config_item_blue
|
||||
from src.modules.dictionary.router import dict_blue, dict_item_blue
|
||||
from src.modules.file_template.router import file_template_blue
|
||||
from src.modules.job.router import job_blue
|
||||
from src.modules.log.router import login_log_blue, operation_log_blue
|
||||
from src.modules.notice.router import notice_blue
|
||||
from src.modules.param.router import param_blue
|
||||
from src.modules.system.dept.router import dept_blue
|
||||
from src.modules.system.level.router import level_blue
|
||||
from src.modules.system.menu.router import menu_blue
|
||||
from src.modules.system.position.router import position_blue
|
||||
from src.modules.system.role.router import role_blue
|
||||
from src.modules.system.user.router import user_blue
|
||||
from src.modules.upload.router import upload_blue
|
||||
|
||||
# 全部业务蓝图(按领域分组排序)
|
||||
BLUEPRINTS = [
|
||||
login_blue, index_blue,
|
||||
user_blue, role_blue, menu_blue, dept_blue, position_blue, level_blue,
|
||||
user_role_blue, role_menu_blue,
|
||||
dict_blue, dict_item_blue, config_blue, config_item_blue,
|
||||
param_blue, notice_blue, category_blue, article_blue, link_blue,
|
||||
upload_blue, file_template_blue, login_log_blue, operation_log_blue,
|
||||
city_blue, job_blue,
|
||||
]
|
||||
|
||||
|
||||
def register_v1(app):
|
||||
"""
|
||||
注册 API v1 路由(所有业务蓝图挂载到 /api/v1)。
|
||||
|
||||
Args:
|
||||
app: Flask 应用实例
|
||||
"""
|
||||
v1 = Blueprint('v1', __name__, url_prefix='/api/v1')
|
||||
for blue in BLUEPRINTS:
|
||||
v1.register_blueprint(blue)
|
||||
app.register_blueprint(v1)
|
||||
return app
|
||||
+1
-1
@@ -356,7 +356,7 @@ from src.core.database import db # 统一 db 单例
|
||||
| **P3 模块搬迁** | 按 §2.5 顺序逐组迁移 23 个模块(models→forms→services→views),每批打 shim + 验证 | 已验收:22 模型→19 模块 models.py;23 表单→schema.py;29 服务→service.py(含 executor/scheduler_service/mail_service/sms_service);26 视图→router.py(login+index 合并入 auth)。应用启动、25 蓝图无重复注册(views/__init__.py 已加去重)、pytest 5 passed、接口冒烟(登录校验/鉴权 401)正常 | 中(已完成) |
|
||||
| **P4 服务层改造** | 26 个服务文件改「入参数据/出参数据」;router 取参包 R;引入 base_service/base_repository + BizError | **✅ 全部完成(21 模块)**:P4a 地基、P4b position 标杆(含单测)、P4c 六个批次(notice/param/link/level、article/category/file_template、dept/city、role/menu/user_role/role_menu、log/dictionary/configuration、job/auth/user)。每模块 flake8 零告警 + 应用启动 + 运行时验证。**合并模块已修复重名函数覆盖/双 import 块/路由导入 bug**。注:level 的 Excel import/export 仍返回 R(暂保留,后续统一改造) | 高(全部完成) |
|
||||
| **P5 DI 注入** | core/permission.py + op_log 接口化;app 工厂注入 menu 服务 | **✅ 已完成**:PermissionProvider 协议 + check_permission 去 menu 依赖;core/middleware.py 整合全部中间件;factory 注入 MenuPermissionProvider + record_operation_log;src/core 零 application 引用;权限/日志行为一致;flake8 零告警 | 中(已完成) |
|
||||
| **P6 API v1** | routes/v1.py + `/api/v1`;白名单/内部调用/前端前缀同步 | 全部接口路径 `curl /api/v1/...` 通过;`/login` 白名单放行 | 中 |
|
||||
| **P6 API v1** | routes/v1.py + `/api/v1`;白名单/内部调用/前端前缀同步 | **✅ 已完成**:148 条路由全部挂 /api/v1;白名单已更新(/api/v1/login 等);build_full_url 内部调用自动加前缀;冒烟验证通过。**前端联动**:ui/ 需将 API 调用前缀改为 /api/v1(待 ui/ 迁移时一并处理) | 中(已完成) |
|
||||
| **P7 切尾** | 删除 application/extensions/utils;`src/wsgi.py`;gunicorn.conf 指向 src.wsgi;更新 CLAUDE.md | `gunicorn -c gunicorn.conf.py src.wsgi:app` 启动;全量回归 | 高 |
|
||||
| **P8 测试+文档** | tests/ 全量落地;CHANGELOG / CONTRIBUTING / API 文档 | `pytest` 通过;覆盖率报告 | 低 |
|
||||
| **P9 运维** | Docker 修复(§2.7)+ CI/CD(lint→type-check→pytest→build) | `docker-compose up -d` 健康检查通过 | 低 |
|
||||
|
||||
Reference in New Issue
Block a user