from flask import Blueprint, render_template, request from flask_login import login_required, current_user from functools import wraps from flask import abort admin_bp = Blueprint('admin', __name__) def admin_required(f): @wraps(f) def decorated_function(*args, **kwargs): if not current_user.is_authenticated or not current_user.is_admin: abort(403) return f(*args, **kwargs) return decorated_function @admin_bp.route('/') @admin_required def dashboard(): return render_template('admin/dashboard.html') @admin_bp.route('/users', methods=['GET', 'POST']) @login_required @admin_required def user_search(): from models import User users = [] query = request.args.get('q', '') if query: # Fuzzy search for Discord or Minecraft username # utilizing ILIKE for case-insensitive search if supported, or just simple LIKE search_term = f"%{query}%" users = User.query.filter( (User.username.ilike(search_term)) | (User.minecraft_username.ilike(search_term)) ).all() return render_template('admin/user_search.html', users=users, query=query) @admin_bp.route('/users/') @login_required @admin_required def user_detail(user_id): from models import User, Ticket, TicketAssignment user = User.query.get_or_404(user_id) # Find relevant tickets relevant_tickets = Ticket.query.outerjoin(TicketAssignment).filter( (Ticket.user_id == user.id) | (TicketAssignment.user_id == user.id) ).all() return render_template('admin/user_detail.html', user=user, tickets=relevant_tickets)