安全修复:加固CSRF与凭证保护并修复越权风险
This commit is contained in:
@@ -355,9 +355,6 @@ def admin_logout():
|
||||
session.pop("admin_id", None)
|
||||
session.pop("admin_username", None)
|
||||
session.pop("admin_reauth_until", None)
|
||||
session.pop("_user_id", None)
|
||||
session.pop("_fresh", None)
|
||||
session.pop("_id", None)
|
||||
return jsonify({"success": True})
|
||||
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ def get_email_settings_api():
|
||||
return jsonify(settings)
|
||||
except Exception as e:
|
||||
logger.error(f"获取邮件设置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "获取邮件设置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/email/settings", methods=["POST"])
|
||||
@@ -48,7 +48,7 @@ def update_email_settings_api():
|
||||
return jsonify({"success": True})
|
||||
except Exception as e:
|
||||
logger.error(f"更新邮件设置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "更新邮件设置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs", methods=["GET"])
|
||||
@@ -60,7 +60,7 @@ def get_smtp_configs_api():
|
||||
return jsonify(configs)
|
||||
except Exception as e:
|
||||
logger.error(f"获取SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "获取SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs", methods=["POST"])
|
||||
@@ -78,7 +78,7 @@ def create_smtp_config_api():
|
||||
return jsonify({"success": True, "id": config_id})
|
||||
except Exception as e:
|
||||
logger.error(f"创建SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "创建SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/<int:config_id>", methods=["GET"])
|
||||
@@ -92,7 +92,7 @@ def get_smtp_config_api(config_id):
|
||||
return jsonify(config_data)
|
||||
except Exception as e:
|
||||
logger.error(f"获取SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "获取SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/<int:config_id>", methods=["PUT"])
|
||||
@@ -106,7 +106,7 @@ def update_smtp_config_api(config_id):
|
||||
return jsonify({"error": "更新失败"}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"更新SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "更新SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/<int:config_id>", methods=["DELETE"])
|
||||
@@ -119,7 +119,7 @@ def delete_smtp_config_api(config_id):
|
||||
return jsonify({"error": "删除失败"}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"删除SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "删除SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/<int:config_id>/test", methods=["POST"])
|
||||
@@ -140,7 +140,7 @@ def test_smtp_config_api(config_id):
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
logger.error(f"测试SMTP配置失败: {e}")
|
||||
return jsonify({"success": False, "error": str(e)}), 500
|
||||
return jsonify({"success": False, "error": "测试SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/<int:config_id>/primary", methods=["POST"])
|
||||
@@ -153,7 +153,7 @@ def set_primary_smtp_config_api(config_id):
|
||||
return jsonify({"error": "设置失败"}), 400
|
||||
except Exception as e:
|
||||
logger.error(f"设置主SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "设置主SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/smtp/configs/primary/clear", methods=["POST"])
|
||||
@@ -165,7 +165,7 @@ def clear_primary_smtp_config_api():
|
||||
return jsonify({"success": True})
|
||||
except Exception as e:
|
||||
logger.error(f"取消主SMTP配置失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "取消主SMTP配置失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/email/stats", methods=["GET"])
|
||||
@@ -177,7 +177,7 @@ def get_email_stats_api():
|
||||
return jsonify(stats)
|
||||
except Exception as e:
|
||||
logger.error(f"获取邮件统计失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "获取邮件统计失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/email/logs", methods=["GET"])
|
||||
@@ -195,7 +195,7 @@ def get_email_logs_api():
|
||||
return jsonify(result)
|
||||
except Exception as e:
|
||||
logger.error(f"获取邮件日志失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "获取邮件日志失败"}), 500
|
||||
|
||||
|
||||
@admin_api_bp.route("/email/logs/cleanup", methods=["POST"])
|
||||
@@ -211,4 +211,4 @@ def cleanup_email_logs_api():
|
||||
return jsonify({"success": True, "deleted": deleted})
|
||||
except Exception as e:
|
||||
logger.error(f"清理邮件日志失败: {e}")
|
||||
return jsonify({"error": str(e)}), 500
|
||||
return jsonify({"error": "清理邮件日志失败"}), 500
|
||||
|
||||
@@ -80,7 +80,7 @@ def update_system_config_api():
|
||||
if schedule_time is not None:
|
||||
import re
|
||||
|
||||
if not re.match(r"^([01]\\d|2[0-3]):([0-5]\\d)$", schedule_time):
|
||||
if not re.match(r"^([01]\d|2[0-3]):([0-5]\d)$", schedule_time):
|
||||
return jsonify({"error": "时间格式错误,应为 HH:MM"}), 400
|
||||
|
||||
if schedule_browse_type is not None:
|
||||
|
||||
@@ -13,20 +13,52 @@ from services.state import safe_clear_user_logs, safe_remove_user_accounts
|
||||
# ==================== 用户管理/统计(管理员) ====================
|
||||
|
||||
|
||||
def _parse_optional_pagination(default_limit: int = 50, max_limit: int = 500) -> tuple[int | None, int]:
|
||||
limit_raw = request.args.get("limit")
|
||||
offset_raw = request.args.get("offset")
|
||||
if (limit_raw is None) and (offset_raw is None):
|
||||
return None, 0
|
||||
|
||||
try:
|
||||
limit = int(limit_raw if limit_raw is not None else default_limit)
|
||||
except (TypeError, ValueError):
|
||||
limit = default_limit
|
||||
limit = max(1, min(limit, max_limit))
|
||||
|
||||
try:
|
||||
offset = int(offset_raw if offset_raw is not None else 0)
|
||||
except (TypeError, ValueError):
|
||||
offset = 0
|
||||
offset = max(0, offset)
|
||||
return limit, offset
|
||||
|
||||
|
||||
@admin_api_bp.route("/users", methods=["GET"])
|
||||
@admin_required
|
||||
def get_all_users():
|
||||
"""获取所有用户"""
|
||||
users = database.get_all_users()
|
||||
return jsonify(users)
|
||||
limit, offset = _parse_optional_pagination()
|
||||
if limit is None:
|
||||
users = database.get_all_users()
|
||||
return jsonify(users)
|
||||
|
||||
users = database.get_all_users(limit=limit, offset=offset)
|
||||
total = database.get_users_count()
|
||||
return jsonify({"items": users, "total": total, "limit": limit, "offset": offset})
|
||||
|
||||
|
||||
@admin_api_bp.route("/users/pending", methods=["GET"])
|
||||
@admin_required
|
||||
def get_pending_users():
|
||||
"""获取待审核用户"""
|
||||
users = database.get_pending_users()
|
||||
return jsonify(users)
|
||||
limit, offset = _parse_optional_pagination(default_limit=30, max_limit=200)
|
||||
if limit is None:
|
||||
users = database.get_pending_users()
|
||||
return jsonify(users)
|
||||
|
||||
users = database.get_pending_users(limit=limit, offset=offset)
|
||||
total = database.get_users_count(status="pending")
|
||||
return jsonify({"items": users, "total": total, "limit": limit, "offset": offset})
|
||||
|
||||
|
||||
@admin_api_bp.route("/users/<int:user_id>/approve", methods=["POST"])
|
||||
|
||||
Reference in New Issue
Block a user