From 17e1d232e8baa34aad659c1f447e3736e8172e90 Mon Sep 17 00:00:00 2001 From: wangfq Date: Thu, 11 Jun 2026 17:21:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20analyst=20?= =?UTF-8?q?=E8=A7=92=E8=89=B2=E2=80=94=E2=80=94=E4=BB=85=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=9F=A5=E8=AF=A2/=E4=B8=8B=E8=BD=BD+?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- edc-web/app/auth.py | 17 +++++++++++++++++ edc-web/app/routes/test_data.py | 4 ++++ edc-web/app/templates/base.html | 2 ++ edc-web/app/templates/users.html | 2 ++ edc_server | 2 +- 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/edc-web/app/auth.py b/edc-web/app/auth.py index 8d74806..969c2a7 100644 --- a/edc-web/app/auth.py +++ b/edc-web/app/auth.py @@ -42,6 +42,23 @@ def load_user(user_id): def init_auth(app): login_manager.init_app(app) + # analyst 角色:全局路由白名单拦截 + ANALYST_ALLOWED = { + "auth.login", "auth.logout", "auth.change_password", + "test_data.test_data_page", + "test_data.api_test_data", + "test_data.api_chart_data", + "test_data.api_export", + "test_data.api_delete", # 自身有 inline 角色检查 + } + + @app.before_request + def _restrict_analyst(): + if current_user.is_authenticated and current_user.role == "analyst": + ep = request.endpoint or "" + if ep not in ANALYST_ALLOWED and not ep.startswith("static"): + return "权限不足:当前角色为 analyst,仅可访问测试数据", 403 + # ─── 装饰器 ──────────────────────────────────────────────────────── diff --git a/edc-web/app/routes/test_data.py b/edc-web/app/routes/test_data.py index 70cb2cb..3cb8862 100644 --- a/edc-web/app/routes/test_data.py +++ b/edc-web/app/routes/test_data.py @@ -10,12 +10,14 @@ bp = Blueprint("test_data", __name__) @bp.route("/test-data") +@login_required def test_data_page(): """测试信息页""" return render_template("test_data.html") @bp.route("/api/test-data") +@login_required def api_test_data(): """分页查询测试数据""" page = request.args.get("page", 1, type=int) @@ -38,6 +40,7 @@ def api_test_data(): @bp.route("/api/test-data/chart") +@login_required def api_chart_data(): """返回图表所需全部数据(不分页)""" serial = request.args.get("serial", "", type=str) @@ -51,6 +54,7 @@ def api_chart_data(): return jsonify({"records": records, "total": len(records)}) @bp.route("/api/test-data/export") +@login_required def api_export(): """导出测试数据为 CSV""" serial = request.args.get("serial", "", type=str) diff --git a/edc-web/app/templates/base.html b/edc-web/app/templates/base.html index 25fc311..ea51848 100644 --- a/edc-web/app/templates/base.html +++ b/edc-web/app/templates/base.html @@ -8,7 +8,9 @@