parent
a36184f9dc
commit
d4dd155ed6
38
app.py
38
app.py
|
@ -86,10 +86,22 @@ def register():
|
|||
flash(message)
|
||||
return render_template("register.html")
|
||||
|
||||
team_name = request.form["team_name"]
|
||||
team_email = request.form["team_email"]
|
||||
team_name = request.form["team_name"].strip()
|
||||
team_email = request.form["team_email"].strip()
|
||||
team_elig = "team_eligibility" in request.form
|
||||
affiliation = request.form["affiliation"]
|
||||
affiliation = request.form["affiliation"].strip()
|
||||
|
||||
if len(team_name) > 50 or not team_name:
|
||||
flash("You must have a team name!")
|
||||
return render_template("register.html")
|
||||
|
||||
if not (team_email and "." in team_email and "@" in team_email):
|
||||
flash("You must have a valid team email!")
|
||||
return render_template("register.html")
|
||||
|
||||
if not affiliation:
|
||||
affiliation = "No affiliation"
|
||||
|
||||
team_key = misc.generate_team_key()
|
||||
confirmation_key = misc.generate_confirmation_key()
|
||||
|
||||
|
@ -141,12 +153,22 @@ def dashboard():
|
|||
flash("You're changing your information too fast!")
|
||||
return redirect(url_for('dashboard'))
|
||||
|
||||
g.redis.set("ul{}".format(session["team_id"]), str(datetime.now()), 120)
|
||||
team_name = request.form["team_name"]
|
||||
team_email = request.form["team_email"]
|
||||
affiliation = request.form["affiliation"]
|
||||
team_name = request.form["team_name"].strip()
|
||||
team_email = request.form["team_email"].strip()
|
||||
affiliation = request.form["affiliation"].strip()
|
||||
team_elig = "team_eligibility" in request.form
|
||||
|
||||
if len(team_name) > 50 or not team_name:
|
||||
flash("You must have a team name!")
|
||||
return render_template("dashboard.html")
|
||||
|
||||
if not (team_email and "." in team_email and "@" in team_email):
|
||||
flash("You must have a valid team email!")
|
||||
return render_template("dashboard.html")
|
||||
|
||||
if not affiliation:
|
||||
affiliation = "No affiliation"
|
||||
|
||||
email_changed = (team_email != g.team.email)
|
||||
|
||||
g.team.name = team_name
|
||||
|
@ -155,6 +177,8 @@ def dashboard():
|
|||
if not g.team.eligibility_locked:
|
||||
g.team.eligible = team_elig
|
||||
|
||||
g.redis.set("ul{}".format(session["team_id"]), str(datetime.now()), 120)
|
||||
|
||||
if email_changed:
|
||||
g.team.email_confirmation_key = misc.generate_confirmation_key()
|
||||
g.team.email_confirmed = False
|
||||
|
|
|
@ -3,7 +3,7 @@ from database import AdminUser, Team, Challenge, ChallengeSolve, ChallengeFailur
|
|||
import utils
|
||||
import utils.admin
|
||||
import utils.scoreboard
|
||||
from utils.decorators import admin_required
|
||||
from utils.decorators import admin_required, csrf_check
|
||||
from utils.notification import make_link
|
||||
from datetime import datetime
|
||||
admin = Blueprint("admin", "admin", url_prefix="/admin")
|
||||
|
@ -87,6 +87,23 @@ 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_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("/logout/")
|
||||
def admin_logout():
|
||||
del session["admin"]
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{% extends "admin/base.html" %}
|
||||
{% block content %}
|
||||
<h2>{{ team.name }}</h2>
|
||||
<p>This team is <strong>{{ "eligible" if team.eligible else "not eligible" }}</strong>.</p>
|
||||
<a href="{{ url_for('admin.admin_impersonate_team', tid=team.id, csrf=csrf_token()) }}">Impersonate team</a><br />
|
||||
<p>This team is <strong>{{ "eligible" if team.eligible else "not eligible" }}</strong>. Eligibility is <strong>{{ "locked" if team.eligibility_locked else "unlocked" }}</strong> (<a href="{{ url_for('admin.admin_toggle_eligibility_lock', tid=team.id, csrf=csrf_token()) }}">toggle</a>).</p>
|
||||
<p>This team's affiliation is <strong>{{ team.affiliation }}</strong></p>
|
||||
<h3>Email</h3>
|
||||
<p>This team's email is <strong>{{ team.email }} ({{ "confirmed" if team.email_confirmed else "unconfirmed" }})</strong>.</p>
|
||||
{% if not team.email_confirmed or 1 %}
|
||||
{% if not team.email_confirmed %}
|
||||
<p>This team's confirmation key is <code>{{ team.email_confirmation_key }}</code>.
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
<form method="POST">
|
||||
<div class="input-field">
|
||||
<label for="team-name">Team Name</label>
|
||||
<input required id="team-name" name="team_name" type="text" value="{{ team.name }}" />
|
||||
<input required maxlength="50" id="team-name" name="team_name" type="text" value="{{ team.name }}" />
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<label for="team-email">Team Email</label>
|
||||
|
|
|
@ -11,7 +11,7 @@ contain a "team key", which is used to log in.</p>
|
|||
team members.</strong></p>
|
||||
<form method="POST">
|
||||
<div class="input-field">
|
||||
<input required id="team-name" name="team_name" type="text" />
|
||||
<input required maxlength="50" id="team-name" name="team_name" type="text" />
|
||||
<label for="team-name">Team Name</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
|
@ -19,7 +19,7 @@ team members.</strong></p>
|
|||
<label for="team-email">Team Email</label>
|
||||
</div>
|
||||
<div class="input-field">
|
||||
<input required id="affiliation" name="affiliation" type="text" />
|
||||
<input id="affiliation" name="affiliation" type="text" />
|
||||
<label for="affiliation">Affiliation</label>
|
||||
</div>
|
||||
<p>{{ config.eligibility }}</p>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import config
|
||||
from flask import session, redirect, url_for, flash, g
|
||||
from flask import session, redirect, url_for, flash, g, abort
|
||||
from functools import wraps
|
||||
|
||||
def login_required(f):
|
||||
|
@ -40,3 +40,19 @@ def admin_required(f):
|
|||
return redirect(url_for("admin.admin_login"))
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
||||
def csrf_check(f):
|
||||
@wraps(f)
|
||||
def decorated(*args, **kwargs):
|
||||
if "csrf" not in kwargs:
|
||||
abort(403)
|
||||
return
|
||||
|
||||
if kwargs["csrf"] != session["_csrf_token"]:
|
||||
abort(403)
|
||||
return
|
||||
|
||||
del kwargs["csrf"]
|
||||
|
||||
return f(*args, **kwargs)
|
||||
return decorated
|
||||
|
|
Loading…
Reference in New Issue