ColdCore/modules/admin.py

142 lines
5.9 KiB
Python
Raw Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

from flask import Blueprint, render_template, request, session, redirect, url_for, flash
from database import AdminUser, Team, Challenge, ChallengeSolve, ChallengeFailure, ScoreAdjustment, TroubleTicket, TicketComment, Notification
import utils
import utils.admin
import utils.scoreboard
from utils.decorators import admin_required, csrf_check
from utils.notification import make_link
from datetime import datetime
from config import secret
admin = Blueprint("admin", "admin", url_prefix="/admin")
@admin.route("/")
def admin_root():
if "admin" in session:
return redirect(url_for(".admin_dashboard"))
else:
return redirect(url_for(".admin_login"))
@admin.route("/login/", methods=["GET", "POST"])
def admin_login():
if request.method == "GET":
return render_template("admin/login.html")
elif request.method == "POST":
username = request.form["username"]
password = request.form["password"]
two = request.form["two"]
if getattr(secret, "admin_username", False):
if username == secret.admin_username and password == secret.admin_password:
session["admin"] = username
return redirect(url_for(".admin_dashboard"))
else:
try:
user = AdminUser.get(AdminUser.username == username)
result = utils.admin.verify_password(user, password)
result = result and utils.admin.verify_otp(user, two)
if result:
session["admin"] = user.username
return redirect(url_for(".admin_dashboard"))
except AdminUser.DoesNotExist:
pass
flash("Y̸̤̗͍̘ͅo͙̠͈͎͎͙̟u̺ ̘̘̘̹̩̹h͔̟̟̗͠a̠͈v͍̻̮̗̬̬̣e̟̫̼̹̠͕ ̠̳͖͡ma͈̱͟d̙͍̀ͅe̵͕̙̯̟̟̞̳ ͉͚̙a̡̱̮̫̰̰ ̜̙̝̭͚t̜̙͚̗͇ͅͅe͉r҉r̸͎̝̞̙̦̹i͏̙b̶̜̟̭͕l̗̰̰̠̳̝̕e͎̥ ̸m̰̯̮̲̘̻͍̀is̜̲̮͍͔̘͕͟t̟͈̮a̙̤͎̠ķ̝̺͇̩e̷͍̤̠͖̣͈.̺̩̦̻.")
return render_template("admin/login.html")
@admin.route("/dashboard/")
@admin_required
def admin_dashboard():
teams = Team.select()
solves = ChallengeSolve.select(ChallengeSolve, Challenge).join(Challenge)
adjustments = ScoreAdjustment.select()
scoredata = utils.scoreboard.get_all_scores(teams, solves, adjustments)
lastsolvedata = utils.scoreboard.get_last_solves(teams, solves)
tickets = list(TroubleTicket.select().where(TroubleTicket.active == True))
return render_template("admin/dashboard.html", teams=teams, scoredata=scoredata, lastsolvedata=lastsolvedata, tickets=tickets)
@admin.route("/tickets/")
@admin_required
def admin_tickets():
tickets = list(TroubleTicket.select(TroubleTicket, Team).join(Team).order_by(TroubleTicket.id.desc()))
return render_template("admin/tickets.html", tickets=tickets)
@admin.route("/tickets/<int:ticket>/")
@admin_required
def admin_ticket_detail(ticket):
ticket = TroubleTicket.get(TroubleTicket.id == ticket)
comments = list(TicketComment.select().where(TicketComment.ticket == ticket).order_by(TicketComment.time))
return render_template("admin/ticket_detail.html", ticket=ticket, comments=comments)
@admin.route("/tickets/<int:ticket>/comment/", methods=["POST"])
@admin_required
def admin_ticket_comment(ticket):
ticket = TroubleTicket.get(TroubleTicket.id == ticket)
if request.form["comment"]:
TicketComment.create(ticket=ticket, comment_by=session["admin"], comment=request.form["comment"], time=datetime.now())
Notification.create(team=ticket.team, notification="A response has been added for {}.".format(make_link("ticket #{}".format(ticket.id), url_for("team_ticket_detail", ticket=ticket.id))))
flash("Comment added.")
if ticket.active and "resolved" in request.form:
ticket.active = False
ticket.save()
Notification.create(team=ticket.team, notification="{} has been marked resolved.".format(make_link("Ticket #{}".format(ticket.id), url_for("team_ticket_detail", ticket=ticket.id))))
flash("Ticket closed.")
elif not ticket.active and "resolved" not in request.form:
ticket.active = True
ticket.save()
Notification.create(team=ticket.team, notification="{} has been reopened.".format(make_link("Ticket #{}".format(ticket.id), url_for("team_ticket_detail", ticket=ticket.id))))
flash("Ticket reopened.")
return redirect(url_for(".admin_ticket_detail", ticket=ticket.id))
@admin.route("/team/<int:tid>/")
@admin_required
def admin_show_team(tid):
team = Team.get(Team.id == tid)
return render_template("admin/team.html", team=team)
@admin.route("/team/<int:tid>/<csrf>/impersonate/")
@csrf_check
@admin_required
def admin_impersonate_team(tid):
session["team_id"] = tid
return redirect(url_for("scoreboard"))
@admin.route("/team/<int:tid>/<csrf>/toggle_eligibility/")
@csrf_check
@admin_required
def admin_toggle_eligibility(tid):
team = Team.get(Team.id == tid)
team.eligible = not team.eligible
team.save()
flash("Eligibility set to {}".format(team.eligible))
return redirect(url_for(".admin_show_team", tid=tid))
@admin.route("/team/<int:tid>/<csrf>/toggle_eligibility_lock/")
@csrf_check
@admin_required
def admin_toggle_eligibility_lock(tid):
team = Team.get(Team.id == tid)
team.eligibility_locked = not team.eligibility_locked
team.save()
flash("Eligibility lock set to {}".format(team.eligibility_locked))
return redirect(url_for(".admin_show_team", tid=tid))
@admin.route("/team/<int:tid>/adjust_score/", methods=["POST"])
@admin_required
def admin_score_adjust(tid):
value = int(request.form["value"])
reason = request.form["reason"]
team = Team.get(Team.id == tid)
ScoreAdjustment.create(team=team, value=value, reason=reason)
flash("Score adjusted.")
return redirect(url_for(".admin_show_team", tid=tid))
@admin.route("/logout/")
def admin_logout():
del session["admin"]
return redirect(url_for('.admin_login'))