feat: 增加 analyst 角色——仅测试数据查询/下载+修改密码
This commit is contained in:
@@ -42,6 +42,23 @@ def load_user(user_id):
|
|||||||
def init_auth(app):
|
def init_auth(app):
|
||||||
login_manager.init_app(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
|
||||||
|
|
||||||
|
|
||||||
# ─── 装饰器 ────────────────────────────────────────────────────────
|
# ─── 装饰器 ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,14 @@ bp = Blueprint("test_data", __name__)
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/test-data")
|
@bp.route("/test-data")
|
||||||
|
@login_required
|
||||||
def test_data_page():
|
def test_data_page():
|
||||||
"""测试信息页"""
|
"""测试信息页"""
|
||||||
return render_template("test_data.html")
|
return render_template("test_data.html")
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/api/test-data")
|
@bp.route("/api/test-data")
|
||||||
|
@login_required
|
||||||
def api_test_data():
|
def api_test_data():
|
||||||
"""分页查询测试数据"""
|
"""分页查询测试数据"""
|
||||||
page = request.args.get("page", 1, type=int)
|
page = request.args.get("page", 1, type=int)
|
||||||
@@ -38,6 +40,7 @@ def api_test_data():
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/api/test-data/chart")
|
@bp.route("/api/test-data/chart")
|
||||||
|
@login_required
|
||||||
def api_chart_data():
|
def api_chart_data():
|
||||||
"""返回图表所需全部数据(不分页)"""
|
"""返回图表所需全部数据(不分页)"""
|
||||||
serial = request.args.get("serial", "", type=str)
|
serial = request.args.get("serial", "", type=str)
|
||||||
@@ -51,6 +54,7 @@ def api_chart_data():
|
|||||||
return jsonify({"records": records, "total": len(records)})
|
return jsonify({"records": records, "total": len(records)})
|
||||||
|
|
||||||
@bp.route("/api/test-data/export")
|
@bp.route("/api/test-data/export")
|
||||||
|
@login_required
|
||||||
def api_export():
|
def api_export():
|
||||||
"""导出测试数据为 CSV"""
|
"""导出测试数据为 CSV"""
|
||||||
serial = request.args.get("serial", "", type=str)
|
serial = request.args.get("serial", "", type=str)
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="top-menu">
|
<nav class="top-menu">
|
||||||
|
{% if current_user.is_authenticated and current_user.role != 'analyst' %}
|
||||||
<a href="/" class="{% if request.path == '/' %}active{% endif %}">设备</a>
|
<a href="/" class="{% if request.path == '/' %}active{% endif %}">设备</a>
|
||||||
|
{% endif %}
|
||||||
<a href="/test-data" class="{% if request.path == '/test-data' %}active{% endif %}">测试信息</a>
|
<a href="/test-data" class="{% if request.path == '/test-data' %}active{% endif %}">测试信息</a>
|
||||||
{% if current_user.is_authenticated and current_user.role in ('admin', 'manager') %}
|
{% if current_user.is_authenticated and current_user.role in ('admin', 'manager') %}
|
||||||
<a href="/device-logs" class="{% if request.path == '/device-logs' %}active{% endif %}">设备日志</a>
|
<a href="/device-logs" class="{% if request.path == '/device-logs' %}active{% endif %}">设备日志</a>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
<label>角色:
|
<label>角色:
|
||||||
<select id="new-role" style="margin:0 8px;">
|
<select id="new-role" style="margin:0 8px;">
|
||||||
<option value="operator">operator</option>
|
<option value="operator">operator</option>
|
||||||
|
<option value="analyst">analyst</option>
|
||||||
<option value="manager">manager</option>
|
<option value="manager">manager</option>
|
||||||
<option value="admin">admin</option>
|
<option value="admin">admin</option>
|
||||||
</select>
|
</select>
|
||||||
@@ -52,6 +53,7 @@ async function loadUsers() {
|
|||||||
<td>
|
<td>
|
||||||
<select onchange="updateUser(${u.id}, this, 'role')" data-field="role">
|
<select onchange="updateUser(${u.id}, this, 'role')" data-field="role">
|
||||||
<option value="operator" ${u.role==='operator'?'selected':''}>operator</option>
|
<option value="operator" ${u.role==='operator'?'selected':''}>operator</option>
|
||||||
|
<option value="analyst" ${u.role==='analyst'?'selected':''}>analyst</option>
|
||||||
<option value="manager" ${u.role==='manager'?'selected':''}>manager</option>
|
<option value="manager" ${u.role==='manager'?'selected':''}>manager</option>
|
||||||
<option value="admin" ${u.role==='admin'?'selected':''}>admin</option>
|
<option value="admin" ${u.role==='admin'?'selected':''}>admin</option>
|
||||||
</select>
|
</select>
|
||||||
|
|||||||
Submodule edc_server updated: 25aafd57c8...3580f89552
Reference in New Issue
Block a user