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) @admin_bp.route('/settings/events', methods=['GET', 'POST']) @login_required @admin_required def event_settings(): from models import EventConfig from extensions import db, socketio if request.method == 'POST': # Update configs all_configs = EventConfig.query.all() for config in all_configs: # Checkbox: if present, it's 'on'. keys are event_name config.is_enabled = request.form.get(config.event_name) == 'on' db.session.commit() # Send update to plugin enabled_events = [c.event_name for c in EventConfig.query.filter_by(is_enabled=True).all()] socketio.emit('config_update', {'enabled_events': enabled_events}) # Flash message ideally, but we'll specificy return to page return render_template('admin/event_settings.html', configs=group_configs(EventConfig.query.all()), success=True) configs = EventConfig.query.all() if not configs: # Prompt user to restart/connect server if empty pass return render_template('admin/event_settings.html', configs=group_configs(configs)) def group_configs(configs): # Group by package grouped = {} for config in configs: pkg = config.package_name if pkg not in grouped: grouped[pkg] = [] grouped[pkg].append(config) # Sort keys return dict(sorted(grouped.items()))