Send confirmation emails on register and add button to resend email (#298)

* Fixes #293
* Adding get_config/set_config test
This commit is contained in:
Kevin Chung
2017-07-01 01:37:08 -04:00
committed by GitHub
parent f1e339c3dc
commit 95245d2ab5
3 changed files with 65 additions and 19 deletions

View File

@@ -18,8 +18,11 @@ auth = Blueprint('auth', __name__)
@auth.route('/confirm/<data>', methods=['GET']) @auth.route('/confirm/<data>', methods=['GET'])
def confirm_user(data=None): def confirm_user(data=None):
if not utils.get_config('verify_emails'): if not utils.get_config('verify_emails'):
# If the CTF doesn't care about confirming email addresses then redierct to challenges
return redirect(url_for('challenges.challenges_view')) return redirect(url_for('challenges.challenges_view'))
if data and request.method == "GET": # User is confirming email account
# User is confirming email account
if data and request.method == "GET":
try: try:
s = Signer(app.config['SECRET_KEY']) s = Signer(app.config['SECRET_KEY'])
email = s.unsign(urllib.unquote_plus(data.decode('base64'))) email = s.unsign(urllib.unquote_plus(data.decode('base64')))
@@ -36,15 +39,28 @@ def confirm_user(data=None):
if utils.authed(): if utils.authed():
return redirect(url_for('challenges.challenges_view')) return redirect(url_for('challenges.challenges_view'))
return redirect(url_for('auth.login')) return redirect(url_for('auth.login'))
if not data and request.method == "GET": # User has been directed to the confirm page because his account is not verified
if not utils.authed(): # User is trying to start or restart the confirmation flow
return redirect(url_for('auth.login')) if not utils.authed():
team = Teams.query.filter_by(id=session['id']).first_or_404() return redirect(url_for('auth.login'))
if team.verified:
return redirect(url_for('views.profile')) team = Teams.query.filter_by(id=session['id']).first_or_404()
else:
utils.verify_email(team.email) if data is None:
return render_template('confirm.html', team=team) if request.method == "POST":
# User wants to resend their confirmation email
if team.verified:
return redirect(url_for('views.profile'))
else:
utils.verify_email(team.email)
return render_template('confirm.html', team=team, infos=['Your confirmation email has been resent!'])
elif request.method == "GET":
# User has been directed to the confirm page
team = Teams.query.filter_by(id=session['id']).first_or_404()
if team.verified:
# If user is already verified, redirect to their profile
return redirect(url_for('views.profile'))
return render_template('confirm.html', team=team)
@auth.route('/reset_password', methods=['POST', 'GET']) @auth.route('/reset_password', methods=['POST', 'GET'])
@@ -136,6 +152,9 @@ def register():
logger.warn("[{0}] {1} registered (UNCONFIRMED) with {2}".format(time.strftime("%m/%d/%Y %X"), logger.warn("[{0}] {1} registered (UNCONFIRMED) with {2}".format(time.strftime("%m/%d/%Y %X"),
request.form['name'].encode('utf-8'), request.form['name'].encode('utf-8'),
request.form['email'].encode('utf-8'))) request.form['email'].encode('utf-8')))
utils.verify_email(team.email)
return redirect(url_for('auth.confirm_user')) return redirect(url_for('auth.confirm_user'))
else: # Don't care about confirming users else: # Don't care about confirming users
if utils.can_send_mail(): # We want to notify the user that they have registered. if utils.can_send_mail(): # We want to notify the user that they have registered.

View File

@@ -2,10 +2,6 @@
{% block stylesheets %} {% block stylesheets %}
<style> <style>
#login-container {
padding-left: 60px;
padding-right: 60px;
}
.done-row { .done-row {
padding-top: 15px; padding-top: 15px;
@@ -22,7 +18,15 @@
</div> </div>
<div class="container main-container"> <div class="container main-container">
<div class="row"> <div class="row">
<div id="login-container" class="col-md-6 col-md-offset-3"> <div id="confirm-container" class="col-md-6 col-md-offset-3">
{% for info in infos %}
<div class="alert alert-info alert-dismissable" role="alert">
<span class="sr-only"></span>
{{ info }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>
</div>
{% endfor %}
{% for error in errors %} {% for error in errors %}
<div class="alert alert-danger alert-dismissable" role="alert"> <div class="alert alert-danger alert-dismissable" role="alert">
<span class="sr-only">Error:</span> <span class="sr-only">Error:</span>
@@ -35,9 +39,22 @@
We've sent a confirmation email to {{ team.email }} We've sent a confirmation email to {{ team.email }}
</h3> </h3>
<h3 class="text-center"> <br>
Please click the link in that email to confirm your account and access the rest of the CTF.
</h3> <h4 class="text-center">
Please click the link in that email to confirm your account.
</h4>
<form method="POST">
<h4 class="text-center">
Need to resend the confirmation email?
</h4>
<div class="col-md-12 text-center">
<button type="submit" id="submit" tabindex="5" class="btn btn-md btn-theme btn-outlined">Resend</button>
</div>
<input type="hidden" name="nonce" value="{{ nonce }}">
</form>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -3,10 +3,20 @@
from tests.helpers import * from tests.helpers import *
from CTFd.models import ip2long, long2ip from CTFd.models import ip2long, long2ip
from CTFd.utils import override_template from CTFd.utils import get_config, set_config, override_template
import json import json
def test_get_config_and_set_config():
"""Does get_config and set_config work properly"""
app = create_ctfd()
with app.app_context():
assert get_config('setup') == True
config = set_config('TEST_CONFIG_ENTRY', 'test_config_entry')
assert config.value == 'test_config_entry'
assert get_config('TEST_CONFIG_ENTRY') == 'test_config_entry'
def test_ip2long_ipv4(): def test_ip2long_ipv4():
"""Does ip2long work properly for ipv4 addresses""" """Does ip2long work properly for ipv4 addresses"""
assert ip2long('127.0.0.1') == 2130706433 assert ip2long('127.0.0.1') == 2130706433