From 732e343aeaa6ff8c31886a5ea5cc2e740932da1c Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Tue, 22 Aug 2017 23:49:48 -0400 Subject: [PATCH] Pushing new tests and freezegun (#360) --- development.txt | 1 + tests/test_user_facing.py | 114 +++++++++++++++++++++++++++++++++++++- tests/test_utils.py | 6 +- 3 files changed, 117 insertions(+), 4 deletions(-) diff --git a/development.txt b/development.txt index cfa20356..67d4c616 100644 --- a/development.txt +++ b/development.txt @@ -4,3 +4,4 @@ mock>=2.0.0 nose>=1.3.7 rednose>=1.1.1 pep8>=1.7.0 +freezegun>=0.3.9 diff --git a/tests/test_user_facing.py b/tests/test_user_facing.py index ca590097..23107467 100644 --- a/tests/test_user_facing.py +++ b/tests/test_user_facing.py @@ -1,10 +1,13 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -from tests.helpers import * from CTFd.models import Teams, Solves, WrongKeys -import json +from CTFd.utils import get_config, set_config from CTFd import utils +from tests.helpers import * +from freezegun import freeze_time +from mock import patch +import json def test_index(): @@ -553,3 +556,110 @@ def test_user_can_unlock_hint(): assert resp.get('hint') assert resp.get('chal') == chal_id destroy_ctfd(app) + + +@patch('smtplib.SMTP') +@freeze_time("2012-01-14 03:21:34") +def test_user_can_confirm_email(mock_smtp): + '''Test that a user is capable of confirming their email address''' + app = create_ctfd() + with app.app_context(): + # Set CTFd to only allow confirmed users and send emails + set_config('verify_emails', True) + set_config('mail_server', 'localhost') + set_config('mail_port', 25) + set_config('mail_username', 'username') + set_config('mail_password', 'password') + + register_user(app, name="user1", email="user@user.com") + + # Teams are not verified by default + team = Teams.query.filter_by(email='user@user.com').first() + assert team.verified == False + + client = login_as_user(app, name="user1", password="password") + + # smtp.sendmail was called + mock_smtp.return_value.sendmail.assert_called() + + with client.session_transaction() as sess: + data = { + "nonce": sess.get('nonce') + } + r = client.get('/challenges') + assert r.location == "http://localhost/confirm" # We got redirected to /confirm + + # Use precalculated confirmation secret + r = client.get('http://localhost/confirm/InVzZXJAdXNlci5jb20iLkFmS0dQZy5kLUJnVkgwaUhadzFHaXVENHczWTJCVVJwdWc%3D') + assert r.location == 'http://localhost/challenges' + + # The team is now verified + team = Teams.query.filter_by(email='user@user.com').first() + assert team.verified == True + + +@patch('smtplib.SMTP') +@freeze_time("2012-01-14 03:21:34") +def test_user_can_reset_password(mock_smtp): + '''Test that a user is capable of resetting their password''' + from email.mime.text import MIMEText + app = create_ctfd() + with app.app_context(): + # Set CTFd to send emails + set_config('mail_server', 'localhost') + set_config('mail_port', 25) + set_config('mail_username', 'username') + set_config('mail_password', 'password') + + # Create a user + register_user(app, name="user1", email="user@user.com") + + with app.test_client() as client: + r = client.get('/reset_password') + + # Build reset password data + with client.session_transaction() as sess: + data = { + 'nonce': sess.get('nonce'), + 'email': 'user@user.com' + } + + # Issue the password reset request + r = client.post('/reset_password', data=data) + + from_addr = get_config('mailfrom_addr') or app.config.get('MAILFROM_ADDR') + to_addr = 'user@user.com' + + # Build the email + msg = """ +Did you initiate a password reset? + +http://localhost/reset_password/InVzZXIxIi5BZktHUGcuTVhkTmZtOWU2U2xwSXZ1MlFwTjdwa3F5V3hR + +""" + email_msg = MIMEText(msg) + email_msg['Subject'] = "Message from CTFd" + email_msg['From'] = from_addr + email_msg['To'] = to_addr + + # Make sure that the reset password email is sent + mock_smtp.return_value.sendmail.assert_called_with(from_addr, [to_addr], email_msg.as_string()) + + # Get user's original password + team = Teams.query.filter_by(email="user@user.com").first() + team_password_saved = team.password + + # Build the POST data + with client.session_transaction() as sess: + data = { + 'nonce': sess.get('nonce'), + 'password': 'passwordtwo' + } + + # Do the password reset + r = client.get('/reset_password') + r = client.post('/reset_password/InVzZXIxIi5BZktHUGcuTVhkTmZtOWU2U2xwSXZ1MlFwTjdwa3F5V3hR', data=data) + + # Make sure that the user's password changed + team = Teams.query.filter_by(email="user@user.com").first() + assert team.password != team_password_saved diff --git a/tests/test_utils.py b/tests/test_utils.py index 78800bb2..751b033d 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,6 +5,7 @@ from tests.helpers import * from CTFd.models import ip2long, long2ip from CTFd.utils import get_config, set_config, override_template, sendmail, verify_email from CTFd.utils import base64encode, base64decode +from freezegun import freeze_time from mock import patch import json import six @@ -130,6 +131,7 @@ def test_sendmail_with_smtp(mock_smtp): @patch('smtplib.SMTP') +@freeze_time("2012-01-14 03:21:34") def test_verify_email(mock_smtp): """Does verify_email send emails""" from email.mime.text import MIMEText @@ -149,7 +151,7 @@ def test_verify_email(mock_smtp): # This is currently not actually validated msg = ("Please click the following link to confirm" " your email address for CTFd:" - " http://localhost/confirm/InVzZXJAdXNlci5jb20iLkRHbGFZUS5XUURfQzBub3pGZkFMRlIyeGxDS1BCMjZETlk%3D") + " http://localhost/confirm/InVzZXJAdXNlci5jb20iLkFmS0dQZy5kLUJnVkgwaUhadzFHaXVENHczWTJCVVJwdWc%3D") ctf_name = get_config('ctf_name') email_msg = MIMEText(msg) @@ -159,5 +161,5 @@ def test_verify_email(mock_smtp): # Need to freeze time to predict the value of the itsdangerous token. # For now just assert that sendmail was called. - mock_smtp.return_value.sendmail.assert_called() + mock_smtp.return_value.sendmail.assert_called_with(from_addr, [to_addr], email_msg.as_string()) destroy_ctfd(app)