Registration works now

master
Glitch 2016-07-11 23:57:43 +00:00
parent 8808f80c27
commit a424031ad9
6 changed files with 42 additions and 147 deletions

30
app.py
View File

@ -22,8 +22,11 @@ logging.basicConfig(level=logging.DEBUG)
@app.before_request
def make_info_available():
if "user_id" in session:
g.user = User.get(User.id == session["user_id"])
g.user_restricts = g.user.restricts.split(",")
try:
g.user = User.get(User.id == session["user_id"])
g.user_restricts = g.user.restricts.split(",")
except User.DoesNotExist:
return render_template("login.html")
@app.context_processor
def scoreboard_variables():
@ -31,7 +34,9 @@ def scoreboard_variables():
if "user_id" in session:
var["logged_in"] = True
var["user"] = g.user
var["notifications"] = Notification.select().where(Notification.user == g.user)
# TODO should this apply to users or teams?
# var["notifications"] = Notification.select().where(Notification.user == g.user)
var["notifications"] = []
else:
var["logged_in"] = False
var["notifications"] = []
@ -137,6 +142,8 @@ def register():
user = User.create(username=username, email=user_email,
eligible=eligible, affiliation=affiliation,
country=country, tshirt_size=tshirt_size,
gender=gender,
email_confirmation_key=confirmation_key)
user.setPassword(password)
@ -165,19 +172,20 @@ def confirm_email():
flash("Incorrect confirmation key.")
return redirect(url_for('dashboard'))
@app.route('/team/', methods=["GET", "POST"])
@app.route('/user/', methods=["GET", "POST"])
@decorators.login_required
def dashboard():
if request.method == "GET":
team_solves = ChallengeSolve.select(ChallengeSolve, Challenge).join(Challenge).where(ChallengeSolve.team == g.team)
team_adjustments = ScoreAdjustment.select().where(ScoreAdjustment.team == g.team)
team_score = sum([i.challenge.points for i in team_solves] + [i.value for i in team_adjustments])
# team_solves = ChallengeSolve.select(ChallengeSolve, Challenge).join(Challenge).where(ChallengeSolve.team == g.team)
# team_adjustments = ScoreAdjustment.select().where(ScoreAdjustment.team == g.team)
# team_score = sum([i.challenge.points for i in team_solves] + [i.value for i in team_adjustments])
first_login = False
if g.team.first_login:
if g.user.first_login:
first_login = True
g.team.first_login = False
g.team.save()
return render_template("dashboard.html", team_solves=team_solves, team_adjustments=team_adjustments, team_score=team_score, first_login=first_login)
g.user.first_login = False
g.user.save()
# return render_template("dashboard.html", team_solves=team_solves, team_adjustments=team_adjustments, team_score=team_score, first_login=first_login)
return render_template("dashboard.html", first_login=first_login)
elif request.method == "POST":
if g.redis.get("ul{}".format(session["user_id"])):

View File

@ -16,7 +16,7 @@ import yaml
import argparse
import logging
tables = [Team, TeamAccess, Challenge, ChallengeSolve, ChallengeFailure, NewsItem, TroubleTicket, TicketComment, Notification, ScoreAdjustment, AdminUser]
tables = [User, Team, TeamAccess, Challenge, ChallengeSolve, ChallengeFailure, NewsItem, TroubleTicket, TicketComment, Notification, ScoreAdjustment, AdminUser]
def create_tables(args):
[i.create_table() for i in tables]

View File

@ -11,19 +11,21 @@ class User(BaseModel):
email = CharField()
email_confirmed = BooleanField(default=False)
email_confirmation_key = CharField()
password = CharField()
password = CharField(null = True)
affiliation = CharField()
country = CharField()
eligible = BooleanField()
tshirt_size = CharField()
gender = CharField()
tshirt_size = CharField(null = True)
gender = CharField(null = True)
first_login = BooleanField(default=True)
restricts = TextField(default="")
def setPassword(self, pw):
self.password = bcrypt.hashpw(pw, bcrypt.gensalt())
self.password = bcrypt.hashpw(pw.encode("utf-8"), bcrypt.gensalt())
return
def checkPassword(self, pw):
return bcrypt.checkpw(pw, self.password)
return bcrypt.checkpw(pw.encode("utf-8"), self.password)
class Team(BaseModel):
name = CharField()

View File

@ -34,7 +34,7 @@
<ul class="right hide-on-med-and-down">
{% if logged_in %}
<li><a href="{{ url_for('logout') }}">Logout</a></li>
<li><a href="{{ url_for('dashboard') }}">{{ team.name }}</a></li>
<li><a href="{{ url_for('dashboard') }}">{{ user.username }}</a></li>
{% endif %}
{% if not logged_in %}
{% if config.registration %}
@ -81,7 +81,7 @@
</a></li>
<li><a href="{{ url_for('dashboard') }}">
<div class="side-icon"><i class="material-icons teal-text">account_circle</i></div>
<div class="side-text">{{ team.name }}</div>
<div class="side-text">{{ user.username }}</div>
</a></li>
{% endif %}
{% if not logged_in %}

View File

@ -1,5 +1,5 @@
{% extends "base.html" %}
{% block title %}Team Dashboard{% endblock %}
{% block title %}Dashboard{% endblock %}
{% block head %}
<style type="text/css">
section:not(first-child) {
@ -30,21 +30,8 @@
</style>
{% endblock %}
{% block content %}
<h2>{{ team.name }}</h2>
<section>
<div class="row">
<div class="col s12">
<div class="card blue darken-1">
<div class="card-content white-text">
<span class="card-title">Team key: <code>{{ team.key }}</code></span>
<p>Share this with your teammates, and keep it in a safe place. <strong>You need your team key
in order to log in.</strong> If you lose it, an organizer can send it to your team email,
which is shown below.</p>
</div>
</div>
</div>
</div>
{% if not team.email_confirmed %}
<h2>{{ user.username }}</h2>
{% if not user.email_confirmed %}
<div class="row">
<div class="col s12">
<div class="card red darken-2">
@ -65,119 +52,16 @@
</div>
</div>
{% endif %}
<h4>Team information</h4>
<p>Your score is currently {{ team_score }}. <a href="{{ url_for('challenges') }}">Go solve more challenges!</a></p>
<p>Your team email is <code>{{ team.email }}</code>, and you are affiliated with
{{ team.affiliation }}.</p>
<p>Your team is currently marked {{ "eligible" if team.eligible else "ineligible" }}.</p>
</section>
<section>
<h4>Edit information</h4>
<form method="POST">
<div class="input-field">
<label for="team-name">Team Name</label>
<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>
<input required id="team-email" name="team_email" type="email" value="{{ team.email }}" />
</div>
<div class="input-field">
<label for="affiliation">Affiliation</label>
<input required maxlength="100" id="affiliation" name="affiliation" type="text" value="{{ team.affiliation }}" />
</div>
{% if not team.eligibility_locked %}
<p>{{ config.eligibility }}</p>
<p>If you do not meet these requirements, you are still welcome to play, but you
will not be eligible for prizes. By checking the "Eligibility Certification"
checkbox below, you are certifying that you meet the prize eligibility
requirement. We may request appropriate documentation to verify your eligibility
status before sending you prizes.</p>
<input id="team-eligibility" name="team_eligibility" type="checkbox"{% if team.eligible %} checked="checked"{% endif %}/>
<label for="team-eligibility">Eligibility Certification</label>
{% endif %}
<input name="_csrf_token" type="hidden" value="{{ csrf_token() }}" />
<br /><br />
<button class="btn waves-effect waves-light" type="submit">Update team</button>
</form>
</section>
<section>
<h4>Score calculation</h4>
{% if team_solves.count() %}
<h5>Solved problems</h5>
<div class="row">
<div class="col s10 offset-s1">
<table>
<thead>
<tr><th>Name</th><th>Category</th><th>Time</th><th>Value</th></tr>
</thead>
<tbody>
{% for solve in team_solves %}
<tr>
<td>{{ solve.challenge.name }}</td>
<td>{{ solve.challenge.category }}</td>
<td><abbr class="time" title="{{ solve.time }}">{{ solve.time }}</abbr></td>
<td>{{ solve.challenge.points }}</td>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<p>No problems have been solved.</p>
{% endif %}
{% if team_adjustments.count() %}
<h5>Score adjustments</h5>
<div class="row">
<div class="col s10 offset-s1">
<table>
<thead>
<tr><th>Reason</th><th>Value</th></tr>
</thead>
<tbody>
{% for adj in team_adjustments %}
<tr>
<td>{{ adj.reason }}</td>
<td>{{ adj.value }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
{% else %}
<p>No score adjustments have been made.</p>
{% endif %}
</section>
{% if config.resumes and team.eligible %}
<section>
<h4>Resume Submissions</h4>
<p>Sponsors will have access to resumes submitted to our database. They may contact competitors about internship opportunities.</p>
<p>Feel free to submit up to 5 resume PDFs per team. These will be associated with your team by your team name and a representation of your team key, so keep it professional.</p>
<form method="POST" action="{{ config.resume_server }}">
<input name="team_name" type="hidden" value="{{ team.name }}"/>
<input name="team_key" type="hidden" value="{{ team.key[:12] }}"/>
<button class="btn waves-effect waves-light" type="submit">Add Resume</button>
</form>
</section>
{% endif %}
<br><br>
<div id="firstlogin" class="modal">
<div class="modal-content">
<h4>Welcome to {{ config.ctf_name }}!</h4>
<p>Hi, {{ team.name }}! Welcome to {{ config.ctf_name }}, {{ config.tagline }}.</p>
<p>First off, please check the email you signed up with. You must confirm your account to solve problems. If needed, you can change the Team Email or resend confirmation on this page.</p>
<p>Your Team Key will be under Login Information. It was also sent to your team email. This is the only way to log in, so distribute it to your team members.</p>
<p>Once that's done, we recommend you read the Rules and FAQ. Then, do some Practice to warm up for the competition, submit team members' resumes to the Resume Database for sponsors to contact about resume opportunities, or join the Chat to meet your fellow competitors and ask questions. The competition will begin soon enough, but in the meanwhile, explore the site!</p>
<p>Hi, {{ user.username }}! Welcome to {{ config.ctf_name }}, {{ config.tagline }}.</p>
<p>First off, please check the email you signed up with. You must confirm your account to solve problems. If needed, you can change your Email or resend confirmation on this page.</p>
<p>We recommend you read the Rules and FAQ. Then, do some Practice to warm up for the competition, join the Chat to meet your fellow competitors and ask questions. The competition will begin soon enough, but in the meanwhile, explore the site!</p>
</div>
<div class="modal-footer">
<a href="#!" class="modal-action modal-close waves-effect waves-green btn-flat">Dismiss</a>

View File

@ -4,7 +4,9 @@ import requests
def send_email(to, subject, text):
return requests.post("{}/messages".format(config.secret.mailgun_url), {"from": config.mail_from, "to": to, "subject": subject, "text": text}, auth=("api", config.secret.mailgun_key))
def send_confirmation_email(team_email, confirmation_key, team_key):
# TODO Make a confirmation link
def send_confirmation_email(team_email, confirmation_key):
send_email(team_email, "Welcome to {}!".format(config.ctf_name),
"""Hello, and thanks for registering for {}! Before you can start solving problems,
you must confirm your email by entering this code into the team dashboard:
@ -15,8 +17,7 @@ Once you've done that, your account will be enabled, and you will be able to acc
the challenges. If you have any trouble, feel free to contact an organizer!
If you didn't register an account, then you can disregard this email.
In case you lose it, your team key is: {}""".format(config.ctf_name, confirmation_key, team_key))
""".format(config.ctf_name, confirmation_key))
def is_valid_email(email):
return not email.strip().lower().endswith(config.disallowed_domain)