android app
This commit is contained in:
84
saars/backend/app/api/admin_api.py
Normal file
84
saars/backend/app/api/admin_api.py
Normal file
@@ -0,0 +1,84 @@
|
||||
"""
|
||||
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,
|
||||
})
|
||||
Reference in New Issue
Block a user