Merge remote branch 'remotes/aaronw/feature410_markdown_bio'
[mediagoblin.git] / mediagoblin / tests / test_auth.py
index 7a46a1ff9a470530013ce21a8cd37542473547d5..ad9dd35b4906f993884b1b9c59ab0feeb42017a9 100644 (file)
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import urlparse
 
-from mediagoblin.auth import lib as auth_lib
-
-from mediagoblin.tests.tools import get_test_app
+from nose.tools import assert_equal
 
-from mediagoblin import globals as mgoblin_globals
+from mediagoblin.auth import lib as auth_lib
+from mediagoblin.tests.tools import setup_fresh_app
+from mediagoblin import mg_globals
 from mediagoblin import util
 
 
@@ -64,10 +65,11 @@ def test_bcrypt_gen_password_hash():
         'notthepassword', hashed_pw, '3><7R45417')
 
 
-def test_register_views():
-    util.clear_test_template_context()
-    test_app = get_test_app()
-
+@setup_fresh_app
+def test_register_views(test_app):
+    """
+    Massive test function that all our registration-related views all work.
+    """
     # Test doing a simple GET on the page
     # -----------------------------------
 
@@ -75,7 +77,7 @@ def test_register_views():
     # Make sure it rendered with the appropriate template
     assert util.TEMPLATE_TEST_CONTEXT.has_key(
         'mediagoblin/auth/register.html')
-    
+
     # Try to register without providing anything, should error
     # --------------------------------------------------------
 
@@ -135,17 +137,213 @@ def test_register_views():
         u'Passwords must match.']
 
     ## At this point there should be no users in the database ;)
-    assert not mgoblin_globals.database.User.find().count()
+    assert not mg_globals.database.User.find().count()
 
     # Successful register
     # -------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/register/', {
+            'username': 'happygirl',
+            'password': 'iamsohappy',
+            'confirm_password': 'iamsohappy',
+            'email': 'happygrrl@example.org'})
+    response.follow()
+
     ## Did we redirect to the proper page?  Use the right template?
+    assert_equal(
+        urlparse.urlsplit(response.location)[2],
+        '/auth/register/success/')
+    assert util.TEMPLATE_TEST_CONTEXT.has_key(
+        'mediagoblin/auth/register_success.html')
+
     ## Make sure user is in place
-    ## Make sure we get email confirmation
-    ## Try logging in
-    
+    new_user = mg_globals.database.User.find_one(
+        {'username': 'happygirl'})
+    assert new_user
+    assert new_user['status'] == u'needs_email_verification'
+    assert new_user['email_verified'] == False
+
+    ## Make sure we get email confirmation, and try verifying
+    assert len(util.EMAIL_TEST_INBOX) == 1
+    message = util.EMAIL_TEST_INBOX.pop()
+    assert message['To'] == 'happygrrl@example.org'
+    email_context = util.TEMPLATE_TEST_CONTEXT[
+        'mediagoblin/auth/verification_email.txt']
+    assert email_context['verification_url'] in message.get_payload(decode=True)
+
+    path = urlparse.urlsplit(email_context['verification_url'])[2]
+    get_params = urlparse.urlsplit(email_context['verification_url'])[3]
+    assert path == u'/auth/verify_email/'
+    parsed_get_params = urlparse.parse_qs(get_params)
+
+    ### user should have these same parameters
+    assert parsed_get_params['userid'] == [
+        unicode(new_user['_id'])]
+    assert parsed_get_params['token'] == [
+        new_user['verification_key']]
+
+    ## Try verifying with bs verification key, shouldn't work
+    util.clear_test_template_context()
+    test_app.get(
+        "/auth/verify_email/?userid=%s&token=total_bs" % unicode(
+            new_user['_id']))
+    context = util.TEMPLATE_TEST_CONTEXT[
+        'mediagoblin/user_pages/user.html']
+    assert context['verification_successful'] == False
+    new_user = mg_globals.database.User.find_one(
+        {'username': 'happygirl'})
+    assert new_user
+    assert new_user['status'] == u'needs_email_verification'
+    assert new_user['email_verified'] == False
+
+    ## Verify the email activation works
+    util.clear_test_template_context()
+    test_app.get("%s?%s" % (path, get_params))
+    context = util.TEMPLATE_TEST_CONTEXT[
+        'mediagoblin/user_pages/user.html']
+    assert context['verification_successful'] == True
+    new_user = mg_globals.database.User.find_one(
+        {'username': 'happygirl'})
+    assert new_user
+    assert new_user['status'] == u'active'
+    assert new_user['email_verified'] == True
+
     # Uniqueness checks
     # -----------------
     ## We shouldn't be able to register with that user twice
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/register/', {
+            'username': 'happygirl',
+            'password': 'iamsohappy2',
+            'confirm_password': 'iamsohappy2',
+            'email': 'happygrrl2@example.org'})
+
+    context = util.TEMPLATE_TEST_CONTEXT[
+        'mediagoblin/auth/register.html']
+    form = context['register_form']
+    assert form.username.errors == [
+        u'Sorry, a user with that name already exists.']
+
+    ## TODO: Also check for double instances of an email address?
+
+
+@setup_fresh_app
+def test_authentication_views(test_app):
+    """
+    Test logging in and logging out
+    """
+    # Make a new user
+    test_user = mg_globals.database.User()
+    test_user['username'] = u'chris'
+    test_user['email'] = u'chris@example.com'
+    test_user['pw_hash'] = auth_lib.bcrypt_gen_password_hash('toast')
+    test_user.save()
+
+    # Get login
+    # ---------
+    test_app.get('/auth/login/')
+    assert util.TEMPLATE_TEST_CONTEXT.has_key(
+        'mediagoblin/auth/login.html')
+
+    # Failed login - blank form
+    # -------------------------
+    util.clear_test_template_context()
+    response = test_app.post('/auth/login/')
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+    form = context['login_form']
+    assert form.username.errors == [u'This field is required.']
+    assert form.password.errors == [u'This field is required.']
+
+    # Failed login - blank user
+    # -------------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'password': u'toast'})
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+    form = context['login_form']
+    assert form.username.errors == [u'This field is required.']
+
+    # Failed login - blank password
+    # -----------------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'username': u'chris'})
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+    form = context['login_form']
+    assert form.password.errors == [u'This field is required.']
+
+    # Failed login - bad user
+    # -----------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'username': u'steve',
+            'password': 'toast'})
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+    assert context['login_failed']
+
+    # Failed login - bad password
+    # ---------------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'username': u'chris',
+            'password': 'jam'})
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/auth/login.html']
+    assert context['login_failed']
+
+    # Successful login
+    # ----------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'username': u'chris',
+            'password': 'toast'})
+
+    # User should be redirected
+    response.follow()
+    assert_equal(
+        urlparse.urlsplit(response.location)[2],
+        '/')
+    assert util.TEMPLATE_TEST_CONTEXT.has_key(
+        'mediagoblin/root.html')
+
+    # Make sure user is in the session
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+    session = context['request'].session
+    assert session['user_id'] == unicode(test_user['_id'])
+
+    # Successful logout
+    # -----------------
+    util.clear_test_template_context()
+    response = test_app.get('/auth/logout/')
+
+    # Should be redirected to index page
+    response.follow()
+    assert_equal(
+        urlparse.urlsplit(response.location)[2],
+        '/')
+    assert util.TEMPLATE_TEST_CONTEXT.has_key(
+        'mediagoblin/root.html')
+
+    # Make sure the user is not in the session
+    context = util.TEMPLATE_TEST_CONTEXT['mediagoblin/root.html']
+    session = context['request'].session
+    assert session.has_key('user_id') == False
+
+    # User is redirected to custom URL if POST['next'] is set
+    # -------------------------------------------------------
+    util.clear_test_template_context()
+    response = test_app.post(
+        '/auth/login/', {
+            'username': u'chris',
+            'password': 'toast',
+            'next' : '/u/chris/'})
+    assert_equal(
+        urlparse.urlsplit(response.location)[2],
+        '/u/chris/')
 
-    ## Also check for double instances of an email address