Files
abot/admin/dashboard/blueprints/group_plugin_config.py

128 lines
5.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
import json
from datetime import datetime
from flask import Blueprint, current_app, jsonify, render_template, request
from .auth import login_required
group_plugin_config_bp = Blueprint("group_plugin_config", __name__, url_prefix="/group_plugin_config")
# 群级插件配置白名单:
# 当前业务阶段仅开放“群成员变更监控”,其余插件统一在后端拦截,
# 防止前端被绕过后写入不受控配置。
ALLOWED_PLUGIN_NAMES = {"群成员变更监控"}
def _normalize_datetime_text(value):
if value is None:
return value
if isinstance(value, datetime):
return value.strftime("%Y-%m-%d %H:%M:%S")
text = str(value)
if "T" in text:
return text.replace("T", " ")[:19]
return text
def _is_plugin_allowed(plugin_name: str) -> bool:
"""检查插件名是否在群级配置白名单内。"""
return str(plugin_name or "").strip() in ALLOWED_PLUGIN_NAMES
@group_plugin_config_bp.route("/")
@login_required
def page_group_plugin_config():
return render_template("group_plugin_config.html")
@group_plugin_config_bp.route("/api/list", methods=["GET"])
@login_required
def api_list_group_plugin_config():
server = current_app.dashboard_server
service = server.group_plugin_config_service
group_id = str(request.args.get("group_id", "") or "").strip()
plugin_name = str(request.args.get("plugin_name", "") or "").strip()
# 列表接口默认仅返回白名单插件,避免管理端仍出现其它插件配置。
# 若传入了非白名单插件名,直接返回空列表。
if plugin_name and not _is_plugin_allowed(plugin_name):
return jsonify({"success": True, "data": []})
if not plugin_name:
# service.list_configs 当前仅支持单个 plugin_name 过滤参数,
# 这里通过遍历白名单并聚合,确保结果严格受控。
rows = []
for allowed_name in sorted(ALLOWED_PLUGIN_NAMES):
rows.extend(service.list_configs(group_id=group_id, plugin_name=allowed_name))
else:
rows = service.list_configs(group_id=group_id, plugin_name=plugin_name)
for row in rows:
row["created_at"] = _normalize_datetime_text(row.get("created_at"))
row["updated_at"] = _normalize_datetime_text(row.get("updated_at"))
return jsonify({"success": True, "data": rows})
@group_plugin_config_bp.route("/api/plugins", methods=["GET"])
@login_required
def api_list_plugins():
# 插件下拉框只暴露白名单,前端无需自行过滤。
return jsonify({"success": True, "data": sorted(ALLOWED_PLUGIN_NAMES)})
@group_plugin_config_bp.route("/api/upsert", methods=["POST"])
@login_required
def api_upsert_group_plugin_config():
server = current_app.dashboard_server
service = server.group_plugin_config_service
payload = request.get_json(silent=True) or {}
group_id = str(payload.get("group_id") or "").strip()
plugin_name = str(payload.get("plugin_name") or "").strip()
config_key = str(payload.get("config_key") or "default").strip() or "default"
enabled = bool(payload.get("enabled", True))
config_data = payload.get("config_json")
updated_by = str(payload.get("updated_by") or "dashboard").strip() or "dashboard"
if not group_id or not plugin_name:
return jsonify({"success": False, "message": "group_id 或 plugin_name 不能为空"}), 400
if not _is_plugin_allowed(plugin_name):
return jsonify({"success": False, "message": f"当前仅允许配置:{','.join(sorted(ALLOWED_PLUGIN_NAMES))}"}), 400
if isinstance(config_data, str):
try:
config_data = json.loads(config_data)
except Exception:
return jsonify({"success": False, "message": "config_json 不是合法 JSON"}), 400
if not isinstance(config_data, dict):
return jsonify({"success": False, "message": "config_json 必须是对象"}), 400
ok = service.upsert_config(
group_id=group_id,
plugin_name=plugin_name,
config_key=config_key,
config_data=config_data,
enabled=enabled,
updated_by=updated_by,
)
if not ok:
return jsonify({"success": False, "message": "保存失败"}), 500
return jsonify({"success": True, "message": "保存成功MySQL + Redis已刷新"})
@group_plugin_config_bp.route("/api/delete", methods=["POST"])
@login_required
def api_delete_group_plugin_config():
server = current_app.dashboard_server
service = server.group_plugin_config_service
payload = request.get_json(silent=True) or {}
group_id = str(payload.get("group_id") or "").strip()
plugin_name = str(payload.get("plugin_name") or "").strip()
config_key = str(payload.get("config_key") or "default").strip() or "default"
if not group_id or not plugin_name:
return jsonify({"success": False, "message": "group_id 或 plugin_name 不能为空"}), 400
if not _is_plugin_allowed(plugin_name):
return jsonify({"success": False, "message": f"当前仅允许配置:{','.join(sorted(ALLOWED_PLUGIN_NAMES))}"}), 400
ok = service.delete_config(group_id=group_id, plugin_name=plugin_name, config_key=config_key)
if not ok:
return jsonify({"success": False, "message": "删除失败"}), 500
return jsonify({"success": True, "message": "删除成功MySQL + Redis已同步"})