from flask import Blueprint, request, jsonify from flask_jwt_extended import jwt_required, get_jwt_identity from datetime import datetime, timedelta from sqlalchemy import func from models import db, TodoItem, TodoAuditLog, TodoMailLog, TodoImportJob from utils.logger import get_logger admin_bp = Blueprint('admin', __name__) logger = get_logger(__name__) # Admin users (in production, this should be in database or config) ADMIN_USERS = ['admin', 'administrator'] def is_admin(identity): """Check if user is admin""" return identity.lower() in ADMIN_USERS @admin_bp.route('/stats', methods=['GET']) @jwt_required() def get_stats(): """Get system statistics""" try: identity = get_jwt_identity() if not is_admin(identity): return jsonify({'error': 'Admin access required'}), 403 # Get date range days = request.args.get('days', 30, type=int) start_date = datetime.utcnow() - timedelta(days=days) # Todo statistics todo_stats = db.session.query( func.count(TodoItem.id).label('total'), func.sum(func.if_(TodoItem.status == 'NEW', 1, 0)).label('new'), func.sum(func.if_(TodoItem.status == 'DOING', 1, 0)).label('doing'), func.sum(func.if_(TodoItem.status == 'BLOCKED', 1, 0)).label('blocked'), func.sum(func.if_(TodoItem.status == 'DONE', 1, 0)).label('done') ).filter(TodoItem.created_at >= start_date).first() # User activity active_users = db.session.query( func.count(func.distinct(TodoAuditLog.actor_ad)) ).filter(TodoAuditLog.created_at >= start_date).scalar() # Email statistics email_stats = db.session.query( func.count(TodoMailLog.id).label('total'), func.sum(func.if_(TodoMailLog.status == 'SENT', 1, 0)).label('sent'), func.sum(func.if_(TodoMailLog.status == 'FAILED', 1, 0)).label('failed') ).filter(TodoMailLog.created_at >= start_date).first() # Import statistics import_stats = db.session.query( func.count(TodoImportJob.id).label('total'), func.sum(func.if_(TodoImportJob.status == 'COMPLETED', 1, 0)).label('completed'), func.sum(func.if_(TodoImportJob.status == 'FAILED', 1, 0)).label('failed') ).filter(TodoImportJob.created_at >= start_date).first() return jsonify({ 'period_days': days, 'todos': { 'total': todo_stats.total or 0, 'new': todo_stats.new or 0, 'doing': todo_stats.doing or 0, 'blocked': todo_stats.blocked or 0, 'done': todo_stats.done or 0 }, 'users': { 'active': active_users or 0 }, 'emails': { 'total': email_stats.total or 0, 'sent': email_stats.sent or 0, 'failed': email_stats.failed or 0 }, 'imports': { 'total': import_stats.total or 0, 'completed': import_stats.completed or 0, 'failed': import_stats.failed or 0 } }), 200 except Exception as e: logger.error(f"Error fetching stats: {str(e)}") return jsonify({'error': 'Failed to fetch statistics'}), 500 @admin_bp.route('/audit-logs', methods=['GET']) @jwt_required() def get_audit_logs(): """Get audit logs""" try: identity = get_jwt_identity() if not is_admin(identity): return jsonify({'error': 'Admin access required'}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 50, type=int) actor = request.args.get('actor') action = request.args.get('action') todo_id = request.args.get('todo_id') query = TodoAuditLog.query if actor: query = query.filter(TodoAuditLog.actor_ad == actor) if action: query = query.filter(TodoAuditLog.action == action) if todo_id: query = query.filter(TodoAuditLog.todo_id == todo_id) query = query.order_by(TodoAuditLog.created_at.desc()) pagination = query.paginate(page=page, per_page=per_page, error_out=False) logs = [] for log in pagination.items: logs.append({ 'id': log.id, 'actor_ad': log.actor_ad, 'todo_id': log.todo_id, 'action': log.action, 'detail': log.detail, 'created_at': log.created_at.isoformat() }) return jsonify({ 'logs': logs, 'total': pagination.total, 'page': page, 'per_page': per_page, 'pages': pagination.pages }), 200 except Exception as e: logger.error(f"Error fetching audit logs: {str(e)}") return jsonify({'error': 'Failed to fetch audit logs'}), 500 @admin_bp.route('/mail-logs', methods=['GET']) @jwt_required() def get_mail_logs(): """Get mail logs""" try: identity = get_jwt_identity() if not is_admin(identity): return jsonify({'error': 'Admin access required'}), 403 page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 50, type=int) status = request.args.get('status') type_ = request.args.get('type') query = TodoMailLog.query if status: query = query.filter(TodoMailLog.status == status) if type_: query = query.filter(TodoMailLog.type == type_) query = query.order_by(TodoMailLog.created_at.desc()) pagination = query.paginate(page=page, per_page=per_page, error_out=False) logs = [] for log in pagination.items: logs.append({ 'id': log.id, 'todo_id': log.todo_id, 'type': log.type, 'triggered_by_ad': log.triggered_by_ad, 'recipients': log.recipients, 'subject': log.subject, 'status': log.status, 'error_text': log.error_text, 'created_at': log.created_at.isoformat(), 'sent_at': log.sent_at.isoformat() if log.sent_at else None }) return jsonify({ 'logs': logs, 'total': pagination.total, 'page': page, 'per_page': per_page, 'pages': pagination.pages }), 200 except Exception as e: logger.error(f"Error fetching mail logs: {str(e)}") return jsonify({'error': 'Failed to fetch mail logs'}), 500