From f0f82f2d5e73fe4b009383c297962a2decf1d7bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?James=20Sigur=C3=B0arson?= Date: Tue, 12 Jul 2016 14:24:19 +0000 Subject: [PATCH 1/3] added edit user and team pages --- app.py | 108 ++++++++++++++++++++++++++---------- ctftool | 8 +-- database.py | 3 +- requirements.txt | 1 + templates/base.html | 13 +++-- templates/register.html | 22 ++------ templates/team.html | 118 ++++++++++++++++++++++------------------ templates/user.html | 107 +++++++++++++++++++++++++++++------- utils/scoreboard.py | 3 +- utils/select.py | 42 ++++++++++++++ 10 files changed, 294 insertions(+), 131 deletions(-) create mode 100644 utils/select.py diff --git a/app.py b/app.py index 1637338..13089d8 100644 --- a/app.py +++ b/app.py @@ -5,7 +5,7 @@ from database import User, Team, TeamAccess, Challenge, ChallengeSolve, Challeng from datetime import datetime from peewee import fn -from utils import decorators, flag, cache, misc, captcha, email +from utils import decorators, flag, cache, misc, captcha, email, select import utils.scoreboard import config @@ -28,11 +28,12 @@ def make_info_available(): g.team = g.user.team g.team_restricts = g.team.restricts.split(",") except User.DoesNotExist: + session.pop("user_id") return render_template("login.html") @app.context_processor def scoreboard_variables(): - var = dict(config=config) + var = dict(config=config, select=select) if "user_id" in session: var["logged_in"] = True var["user"] = g.user @@ -141,6 +142,10 @@ def register(): except User.DoesNotExist: pass + if password != confirm_password: + flash("Password does not match confirmation") + return render_template("register.html") + if not (user_email and "." in user_email and "@" in user_email): flash("You must have a valid email!") return render_template("register.html") @@ -149,6 +154,18 @@ def register(): flash("You're lying") return render_template("register.html") + if not tshirt_size in select.TShirts: + flash("Invalid T-shirt size") + return render_template("register.html") + + if not background in select.BackgroundKeys: + flash("Invalid Background") + return render_template("register.html") + + if not country in select.CountryKeys: + flash("Invalid Background") + return render_template("register.html") + confirmation_key = misc.generate_confirmation_key() team=None @@ -177,6 +194,7 @@ def register(): email_confirmation_key=confirmation_key, team=team) user.setPassword(password) + user.save() print(confirmation_key) @@ -184,7 +202,7 @@ def register(): session["user_id"] = user.id flash("Registration finished") - return redirect(url_for('team_dashboard')) + return redirect(url_for('user_dashboard')) @app.route('/logout/') def logout(): @@ -220,45 +238,73 @@ def user_dashboard(): flash("You're changing your information too fast!") return redirect(url_for('user_dashboard')) - 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 + username = request.form["username"].strip() + user_email = request.form["email"].strip() + password = request.form["password"].strip() + confirm_password = request.form["confirm_password"].strip() + background = request.form["background"].strip() + country = request.form["country"].strip() - if len(team_name) > 50 or not team_name: - flash("You must have a team name!") + tshirt_size = request.form["tshirt_size"].strip() + gender = request.form["gender"].strip() + + if len(username) > 50 or not username: + flash("You must have a username!") + return redirect(url_for('user_dashboard')) + if g.user.username != username: + try: + user = User.get(User.username == username) + flash("This username is already in use!") + return redirect(url_for('user_dashboard')) + except User.DoesNotExist: + pass + + if not (user_email and "." in user_email and "@" in user_email): + flash("You must have a valid email!") return redirect(url_for('user_dashboard')) - if not (team_email and "." in team_email and "@" in team_email): - flash("You must have a valid team email!") + if not email.is_valid_email(user_email): + flash("You're lying") return redirect(url_for('user_dashboard')) - if not affiliation or len(affiliation) > 100: - affiliation = "No affiliation" + if not tshirt_size in select.TShirts: + flash("Invalid T-shirt size") + return redirect(url_for('user_dashboard')) - email_changed = (team_email != g.team.email) + if not background in select.BackgroundKeys: + flash("Invalid Background") + return redirect(url_for('user_dashboard')) - g.team.name = team_name - g.team.email = team_email - g.team.affiliation = affiliation - if not g.team.eligibility_locked: - g.team.eligible = team_elig + if not country in select.CountryKeys: + flash("Invalid Background") + return redirect(url_for('user_dashboard')) + + email_changed = (user_email != g.user.email) + + g.user.username = username + g.user.email = user_email + g.user.background = background + g.user.country = country + g.user.gender = gender + g.user.tshirt_size = tshirt_size g.redis.set("ul{}".format(session["user_id"]), str(datetime.now()), 120) - if email_changed: - if not email.is_valid_email(team_email): - flash("You're lying") + if password != "": + if password != confirm_password: + flash("Password does not match confirmation") return redirect(url_for('user_dashboard')) + g.user.setPassword(password) - g.team.email_confirmation_key = misc.generate_confirmation_key() - g.team.email_confirmed = False + if email_changed: + g.user.email_confirmation_key = misc.generate_confirmation_key() + g.user.email_confirmed = False - email.send_confirmation_email(team_email, g.team.email_confirmation_key, g.team.key) + email.send_confirmation_email(user_email, g.user.email_confirmation_key) flash("Changes saved. Please check your email for a new confirmation key.") else: flash("Changes saved.") - g.team.save() + g.user.save() return redirect(url_for('user_dashboard')) @@ -276,7 +322,7 @@ def team_dashboard(): return redirect(url_for('team_dashboard')) team_name = request.form["team_name"].strip() - affiliation = request.form["affiliation"].strip() + affiliation = request.form["team_affiliation"].strip() if len(team_name) > 50 or not team_name: flash("You must have a team name!") @@ -285,7 +331,13 @@ def team_dashboard(): if not affiliation or len(affiliation) > 100: affiliation = "No affiliation" - email_changed = (team_email != g.team.email) + if g.team_name != team_name: + try: + team = Team.get(Team.name == team_name) + flash("This team name is already in use!") + return redirect(url_for('team_dashboard')) + except Team.DoesNotExist: + pass g.team.name = team_name g.team.affiliation = affiliation diff --git a/ctftool b/ctftool index 64c4a39..bc11d42 100755 --- a/ctftool +++ b/ctftool @@ -149,15 +149,15 @@ def main(): subparser_problems = parser_problems.add_subparsers(help='Select one of the following actions') parser_problems_scan = subparser_problems.add_parser('scan', help='Scan a path for problems') - parser_problems_scan.add_argument("path", nargs=1, help="Directory for the path") + parser_problems_scan.add_argument("path", help="Directory for the path") parser_problems_scan.set_defaults(func=scan_challenges) parser_problems_generate = subparser_problems.add_parser('generate', help='Generate some dummy problems') - parser_problems_generate.add_argument("challenge_count", nargs=1, type=int, help="number of problems to generate") + parser_problems_generate.add_argument("challenge_count", type=int, help="number of problems to generate") parser_problems_generate.set_defaults(func=gen_challenges) parser_problems_add = subparser_problems.add_parser('add', help='add a problem') - parser_problems_add.add_argument("file", nargs=1, help="file to use") + parser_problems_add.add_argument("file", help="file to use") parser_problems_add.set_defaults(func=add_challenge) parser_problems_list = subparser_problems.add_parser('list', help='List problems in the database') @@ -187,7 +187,7 @@ def main(): subparser_users = parser_user.add_subparsers(help="Select one of the following actions") parser_users_generate = subparser_users.add_parser('generate', help='Generate some dummy teams') - parser_users_generate.add_argument("team_count", nargs=1, type=int, help="number of teams to generate") + parser_users_generate.add_argument("team_count", type=int, help="number of teams to generate") parser_users_generate.set_defaults(func=gen_team) parser_users_admin = subparser_users.add_parser('add-admin', help='Create a new administrator') diff --git a/database.py b/database.py index 734c4fe..546ba98 100644 --- a/database.py +++ b/database.py @@ -30,6 +30,7 @@ class User(BaseModel): email_confirmed = BooleanField(default=False) email_confirmation_key = CharField() password = CharField(null = True) + background = CharField() country = CharField() tshirt_size = CharField(null = True) gender = CharField(null = True) @@ -45,7 +46,7 @@ class User(BaseModel): return bcrypt.checkpw(pw.encode("utf-8"), self.password) def eligible(self): - return self.country == "Iceland" + return self.country == "ISL" class TeamAccess(BaseModel): team = ForeignKeyField(Team, related_name='accesses') diff --git a/requirements.txt b/requirements.txt index e677b88..7f2007b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ bcrypt redis pyyaml oath +pycountry diff --git a/templates/base.html b/templates/base.html index e898dfb..1f95c73 100644 --- a/templates/base.html +++ b/templates/base.html @@ -75,17 +75,18 @@
{% if logged_in %} -
  • -
    block
    -
    Logout
    + +
  • +
    track_changes
    +
    My Team
  • account_circle
    {{ user.username }}
  • -
  • -
    account_circle
    -
    {{ team.name }}
    +
  • +
    block
    +
    Logout
  • {% endif %} {% if not logged_in %} diff --git a/templates/register.html b/templates/register.html index 39d131b..1dea839 100644 --- a/templates/register.html +++ b/templates/register.html @@ -39,20 +39,13 @@
    @@ -60,19 +53,14 @@
    - + - +
    diff --git a/templates/team.html b/templates/team.html index c1c15ba..92589be 100644 --- a/templates/team.html +++ b/templates/team.html @@ -31,75 +31,87 @@ {% endblock %} {% block content %}

    {{ team.name }}

    - -

    Team information

    -

    Your score is currently {{ team_score }}. Go solve more challenges!

    -

    Your team email is {{ team.email }}, and you are affiliated with -{{ team.affiliation }}.

    -

    Your team is currently marked {{ "eligible" if team.eligible else "ineligible" }}.

    +
    +
    +
    +
    +
    + Team key: {{ team.key }} +

    Share this with your teammates, and keep it in a safe place.

    +
    +
    +
    +
    -

    Edit information

    -
    +

    Team information

    +

    Your score is currently {{ team_score }}. Go solve more challenges!

    +

    Your team email is {{ team.email }}, and you are affiliated with + {{ team.affiliation }}.

    +

    Your team is currently marked {{ "eligible" if team.eligible() else "ineligible" }}.

    +
    +
    +

    Edit information

    +
    - - + +
    - - + +


    - +
    -

    Score calculation

    -{% if team_solves.count() %} -
    Solved problems
    -
    -
    +

    Score calculation

    + {% if team_solves.count() %} +
    Solved problems
    +
    +
    - - - - - {% for solve in team_solves %} - - - - - - {% endfor %} - + + + + + {% for solve in team_solves %} + + + + + + {% endfor %} +
    NameCategoryTimeValue
    {{ solve.challenge.name }}{{ solve.challenge.category }}{{ solve.time }}{{ solve.challenge.points }}
    NameCategoryTimeValue
    {{ solve.challenge.name }}{{ solve.challenge.category }}{{ solve.time }}{{ solve.challenge.points }}
    +
    -
    -{% else %} -

    No problems have been solved.

    -{% endif %} -{% if team_adjustments.count() %} -
    Score adjustments
    -
    -
    + {% else %} +

    No problems have been solved.

    + {% endif %} + {% if team_adjustments.count() %} +
    Score adjustments
    +
    +
    - - - - - {% for adj in team_adjustments %} - - - - - {% endfor %} - + + + + + {% for adj in team_adjustments %} + + + + + {% endfor %} +
    ReasonValue
    {{ adj.reason }}{{ adj.value }}
    ReasonValue
    {{ adj.reason }}{{ adj.value }}
    +
    -
    -{% else %} -

    No score adjustments have been made.

    -{% endif %} + {% else %} +

    No score adjustments have been made.

    + {% endif %}
    {% endblock %} diff --git a/templates/user.html b/templates/user.html index 01eae81..b5db5e5 100644 --- a/templates/user.html +++ b/templates/user.html @@ -32,27 +32,94 @@ {% block content %}

    {{ user.username }}

    {% if not user.email_confirmed %} -
    -
    -
    -
    - Email unconfirmed -

    It looks like you haven't confirmed your email yet. Check the email you used for registration; - the system should have sent you an email confirmation key. Paste it below:

    -
    -
    - - -
    - - -
    -
    -
    -
    -
    +
    +
    +
    +
    + Email unconfirmed +

    It looks like you haven't confirmed your email yet. Check the email you used for registration; + the system should have sent you an email confirmation key. Paste it below:

    +
    +
    + + +
    + + +
    +
    +
    +
    +
    {% endif %} - +
    +

    Edit information

    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + + +
    +
    +
    +
    + + +
    +
    + {% if user.gender == 'M' %} + + + + + {% elif user.gender == 'F' %} + + + + + {% endif %} +
    +
    +
    +
    + +
    +
    + +
    +