admin.py 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. from flask import Blueprint, render_template, request
  2. from flask_login import login_required, current_user
  3. from functools import wraps
  4. from flask import abort
  5. admin_bp = Blueprint('admin', __name__)
  6. def admin_required(f):
  7. @wraps(f)
  8. def decorated_function(*args, **kwargs):
  9. if not current_user.is_authenticated or not current_user.is_admin:
  10. abort(403)
  11. return f(*args, **kwargs)
  12. return decorated_function
  13. @admin_bp.route('/')
  14. @admin_required
  15. def dashboard():
  16. return render_template('admin/dashboard.html')
  17. @admin_bp.route('/users', methods=['GET', 'POST'])
  18. @login_required
  19. @admin_required
  20. def user_search():
  21. from models import User
  22. users = []
  23. query = request.args.get('q', '')
  24. if query:
  25. # Fuzzy search for Discord or Minecraft username
  26. # utilizing ILIKE for case-insensitive search if supported, or just simple LIKE
  27. search_term = f"%{query}%"
  28. users = User.query.filter(
  29. (User.username.ilike(search_term)) |
  30. (User.minecraft_username.ilike(search_term))
  31. ).all()
  32. return render_template('admin/user_search.html', users=users, query=query)
  33. @admin_bp.route('/users/<int:user_id>')
  34. @login_required
  35. @admin_required
  36. def user_detail(user_id):
  37. from models import User, Ticket, TicketAssignment
  38. user = User.query.get_or_404(user_id)
  39. # Find relevant tickets
  40. relevant_tickets = Ticket.query.outerjoin(TicketAssignment).filter(
  41. (Ticket.user_id == user.id) | (TicketAssignment.user_id == user.id)
  42. ).all()
  43. return render_template('admin/user_detail.html', user=user, tickets=relevant_tickets)