Files
aiagent/saars/backend/app/api/admin_api.py
2026-03-07 09:01:00 +08:00

85 lines
2.6 KiB
Python

"""
Admin REST API: user management, chat audit, system stats (RBAC-protected).
"""
from flask import Blueprint, request, jsonify
from flask_jwt_extended import jwt_required, get_jwt_identity, get_jwt
from app import db
from app.models.user import User, Role
from app.models.chat import Conversation, Message
admin_api_bp = Blueprint("admin_api", __name__)
def admin_required(fn):
"""Require admin role (role name 'admin')."""
from functools import wraps
@wraps(fn)
def wrapper(*args, **kwargs):
identity = get_jwt_identity()
user = User.query.get(identity)
if not user or not user.role_id:
return jsonify({"error": "Forbidden"}), 403
role = Role.query.get(user.role_id)
if not role or role.name != "admin":
return jsonify({"error": "Admin required"}), 403
return fn(*args, **kwargs)
return wrapper
@admin_api_bp.route("/users", methods=["GET"])
@jwt_required()
@admin_required
def list_users():
skip = request.args.get("skip", 0, type=int)
limit = min(request.args.get("limit", 20, type=int), 100)
users = User.query.order_by(User.created_at.desc()).offset(skip).limit(limit).all()
return jsonify({"items": [u.to_dict() for u in users]})
@admin_api_bp.route("/users/<user_id>", methods=["PATCH"])
@jwt_required()
@admin_required
def update_user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({"error": "User not found"}), 404
data = request.get_json() or {}
if "is_active" in data:
user.is_active = bool(data["is_active"])
db.session.commit()
return jsonify(user.to_dict())
@admin_api_bp.route("/conversations", methods=["GET"])
@jwt_required()
@admin_required
def list_all_conversations():
skip = request.args.get("skip", 0, type=int)
limit = min(request.args.get("limit", 20, type=int), 100)
convs = Conversation.query.order_by(Conversation.last_message_at.desc()).offset(skip).limit(limit).all()
return jsonify({
"items": [
{
"id": c.id,
"user_id": c.user_id,
"title": c.title,
"last_message_at": c.last_message_at.isoformat() if c.last_message_at else None,
}
for c in convs
]
})
@admin_api_bp.route("/stats", methods=["GET"])
@jwt_required()
@admin_required
def system_stats():
user_count = User.query.count()
conv_count = Conversation.query.count()
msg_count = Message.query.count()
return jsonify({
"users": user_count,
"conversations": conv_count,
"messages": msg_count,
})