Blame tests/test_pagure_flask_ui_login.py

Pierre-Yves Chibon 0b1c13
# -*- coding: utf-8 -*-
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
"""
Pierre-Yves Chibon 0b1c13
 (c) 2016 - Copyright Red Hat Inc
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
 Authors:
Pierre-Yves Chibon 0b1c13
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
farhaanbukhsh 96d198
   Farhaan Bukhsh <farhaan.bukhsh@gmail.com></farhaan.bukhsh@gmail.com>
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
"""
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
__requires__ = ['SQLAlchemy >= 0.8']
Pierre-Yves Chibon 0b1c13
import pkg_resources
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
import datetime
Pierre-Yves Chibon eac364
import hashlib
Pierre-Yves Chibon 0b1c13
import json
Pierre-Yves Chibon 0b1c13
import unittest
Pierre-Yves Chibon 0b1c13
import shutil
Pierre-Yves Chibon 0b1c13
import sys
Pierre-Yves Chibon 0b1c13
import tempfile
Pierre-Yves Chibon 0b1c13
import os
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 450dd6
import flask
Pierre-Yves Chibon 0b1c13
import pygit2
Pierre-Yves Chibon 33ff8d
from mock import patch, MagicMock
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
sys.path.insert(0, os.path.join(os.path.dirname(
Pierre-Yves Chibon 0b1c13
    os.path.abspath(__file__)), '..'))
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
import pagure.lib
Pierre-Yves Chibon 0b1c13
import tests
Pierre-Yves Chibon 0b1c13
from pagure.lib.repo import PagureRepo
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon b94671
import pagure.ui.login
Pierre-Yves Chibon b94671
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
class PagureFlaskLogintests(tests.Modeltests):
Pierre-Yves Chibon 0b1c13
    """ Tests for flask app controller of pagure """
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
    def setUp(self):
Pierre-Yves Chibon 0b1c13
        """ Set up the environnment, ran before every tests. """
Pierre-Yves Chibon 0b1c13
        super(PagureFlaskLogintests, self).setUp()
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
        pagure.APP.config['TESTING'] = True
Pierre-Yves Chibon 91c1b0
        pagure.APP.config['EMAIL_SEND'] = False
Pierre-Yves Chibon 250169
        pagure.APP.config['PAGURE_AUTH'] = 'local'
Pierre-Yves Chibon 0b1c13
        pagure.SESSION = self.session
Pierre-Yves Chibon 0b1c13
        pagure.ui.SESSION = self.session
Pierre-Yves Chibon 23b43c
        pagure.ui.app.SESSION = self.session
Pierre-Yves Chibon 0b1c13
        pagure.ui.login.SESSION = self.session
Pierre-Yves Chibon 9fae46
        pagure.ui.filters.SESSION = self.session
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
        self.app = pagure.APP.test_client()
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 33ff8d
    @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
Pierre-Yves Chibon b94671
    def test_new_user(self):
Pierre-Yves Chibon b94671
        """ Test the new_user endpoint. """
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Check before:
Pierre-Yves Chibon b94671
        items = pagure.lib.search_user(self.session)
Pierre-Yves Chibon b94671
        self.assertEqual(2, len(items))
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # First access the new user page
Pierre-Yves Chibon b94671
        output = self.app.get('/user/new')
Pierre-Yves Chibon b94671
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon b94671
        self.assertIn('<title>New user - Pagure</title>', output.data)
Pierre-Yves Chibon b94671
        self.assertIn(
Pierre-Yves Chibon b94671
            '<form action="/user/new" method="post">', output.data)</form>
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Create the form to send there
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # This has all the data needed
Pierre-Yves Chibon b94671
        data = {
Pierre-Yves Chibon b94671
            'user': 'foo',
Pierre-Yves Chibon b94671
            'fullname': 'user foo',
Pierre-Yves Chibon 5f96cd
            'email_address': 'foo@bar.com',
Pierre-Yves Chibon b94671
            'password': 'barpass',
Pierre-Yves Chibon b94671
            'confirm_password': 'barpass',
Pierre-Yves Chibon b94671
        }
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Submit this form  -  Doesn't work since there is no csrf token
Pierre-Yves Chibon b94671
        output = self.app.post('/user/new', data=data)
Pierre-Yves Chibon b94671
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon b94671
        self.assertIn('<title>New user - Pagure</title>', output.data)
Pierre-Yves Chibon b94671
        self.assertIn(
Pierre-Yves Chibon b94671
            '<form action="/user/new" method="post">', output.data)</form>
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        csrf_token = output.data.split(
farhaanbukhsh 19ad5f
            'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Submit the form with the csrf token
Pierre-Yves Chibon b94671
        data['csrf_token'] = csrf_token
Pierre-Yves Chibon b94671
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Pierre-Yves Chibon b94671
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon b94671
        self.assertIn('<title>New user - Pagure</title>', output.data)
Pierre-Yves Chibon b94671
        self.assertIn(
Pierre-Yves Chibon b94671
            '<form action="/user/new" method="post">', output.data)</form>
Pierre-Yves Chibon b94671
        self.assertIn('Username already taken.', output.data)
Pierre-Yves Chibon b94671
Pierre-Yves Chibon 5f96cd
        # Submit the form with another username
Pierre-Yves Chibon b94671
        data['user'] = 'foouser'
Pierre-Yves Chibon b94671
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Pierre-Yves Chibon b94671
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 5f96cd
        self.assertIn('<title>New user - Pagure</title>', output.data)
Pierre-Yves Chibon 5f96cd
        self.assertIn('Email address already taken.', output.data)
Pierre-Yves Chibon 5f96cd
Pierre-Yves Chibon 5f96cd
        # Submit the form with proper data
Pierre-Yves Chibon 5f96cd
        data['email_address'] = 'foo@example.com'
Pierre-Yves Chibon 5f96cd
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Pierre-Yves Chibon 5f96cd
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon b94671
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon b94671
        self.assertIn(
Pierre-Yves Chibon b94671
            'User created, please check your email to activate the account',
Pierre-Yves Chibon b94671
            output.data)
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Check after:
Pierre-Yves Chibon b94671
        items = pagure.lib.search_user(self.session)
Pierre-Yves Chibon b94671
        self.assertEqual(3, len(items))
Pierre-Yves Chibon b94671
Pierre-Yves Chibon a4c666
    def test_do_login(self):
Pierre-Yves Chibon a4c666
        """ Test the do_login endpoint. """
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        output = self.app.get('/login/')
Pierre-Yves Chibon a4c666
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon a4c666
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            '<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        # This has all the data needed
Pierre-Yves Chibon a4c666
        data = {
Pierre-Yves Chibon a4c666
            'username': 'foouser',
Pierre-Yves Chibon a4c666
            'password': 'barpass',
Pierre-Yves Chibon a4c666
        }
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        # Submit this form  -  Doesn't work since there is no csrf token
Pierre-Yves Chibon a4c666
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon a4c666
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon a4c666
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            '<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon a4c666
        self.assertIn('Insufficient information provided', output.data)
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        csrf_token = output.data.split(
farhaanbukhsh 19ad5f
            'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        # Submit the form with the csrf token  -  but invalid user
Pierre-Yves Chibon a4c666
        data['csrf_token'] = csrf_token
Pierre-Yves Chibon a4c666
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon a4c666
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon a4c666
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            '<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon a4c666
        self.assertIn('Username or password invalid.', output.data)
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        # Create a local user
Pierre-Yves Chibon a4c666
        self.test_new_user()
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon a4c666
        items = pagure.lib.search_user(self.session)
Pierre-Yves Chibon a4c666
        self.assertEqual(3, len(items))
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon 3deace
        # Submit the form with the csrf token  -  but user not confirmed
Pierre-Yves Chibon a4c666
        data['csrf_token'] = csrf_token
Pierre-Yves Chibon a4c666
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon a4c666
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon a4c666
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            '<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            'Invalid user, did you confirm the creation with the url '
Pierre-Yves Chibon a4c666
            'provided by email?', output.data)
Pierre-Yves Chibon a4c666
Pierre-Yves Chibon 3deace
        # User in the DB, csrf provided  -  but wrong password submitted
farhaanbukhsh fa9239
        data['password'] = 'password'
farhaanbukhsh fa9239
        output = self.app.post('/dologin', data=data, follow_redirects=True)
farhaanbukhsh fa9239
        self.assertEqual(output.status_code, 200)
farhaanbukhsh fa9239
        self.assertIn('<title>Login - Pagure</title>', output.data)
farhaanbukhsh fa9239
        self.assertIn(
farhaanbukhsh fa9239
            '<form action="/dologin" method="post">', output.data)</form>
farhaanbukhsh fa9239
        self.assertIn('Username or password invalid.', output.data)
farhaanbukhsh fa9239
farhaanbukhsh 66f5d8
        # When account is not confirmed i.e user_obj != None
farhaanbukhsh 66f5d8
        data['password'] = 'barpass'
farhaanbukhsh 66f5d8
        output = self.app.post('/dologin', data=data, follow_redirects=True)
farhaanbukhsh 66f5d8
        self.assertEqual(output.status_code, 200)
farhaanbukhsh 66f5d8
        self.assertIn('<title>Login - Pagure</title>', output.data)
farhaanbukhsh 66f5d8
        self.assertIn(
farhaanbukhsh 66f5d8
            '<form action="/dologin" method="post">', output.data)</form>
farhaanbukhsh 66f5d8
        self.assertIn(
farhaanbukhsh 66f5d8
            'Invalid user, did you confirm the creation with the url '
farhaanbukhsh 66f5d8
            'provided by email?', output.data)
farhaanbukhsh fa9239
farhaanbukhsh e8867b
        # Wrong password submitted
farhaanbukhsh e8867b
        data['password'] = 'password'
farhaanbukhsh e8867b
        output = self.app.post('/dologin', data=data, follow_redirects=True)
farhaanbukhsh e8867b
        self.assertEqual(output.status_code, 200)
farhaanbukhsh e8867b
        self.assertIn('<title>Login - Pagure</title>', output.data)
farhaanbukhsh e8867b
        self.assertIn(
farhaanbukhsh e8867b
            '<form action="/dologin" method="post">', output.data)</form>
farhaanbukhsh e8867b
        self.assertIn('Username or password invalid.', output.data)
farhaanbukhsh e8867b
farhaanbukhsh bbbe44
        # When account is not confirmed i.e user_obj != None
farhaanbukhsh bbbe44
        data['password'] = 'barpass'
farhaanbukhsh bbbe44
        output = self.app.post('/dologin', data=data, follow_redirects=True)
farhaanbukhsh bbbe44
        self.assertEqual(output.status_code, 200)
farhaanbukhsh bbbe44
        self.assertIn('<title>Login - Pagure</title>', output.data)
farhaanbukhsh bbbe44
        self.assertIn(
farhaanbukhsh bbbe44
            '<form action="/dologin" method="post">', output.data)</form>
farhaanbukhsh bbbe44
        self.assertIn(
farhaanbukhsh bbbe44
            'Invalid user, did you confirm the creation with the url '
farhaanbukhsh bbbe44
            'provided by email?', output.data)
farhaanbukhsh e8867b
Pierre-Yves Chibon 9b9f29
        # Confirm the user so that we can log in
Pierre-Yves Chibon 9b9f29
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 9b9f29
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 9b9f29
        self.assertNotEqual(item.token, None)
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 9b9f29
        # Remove the token
Pierre-Yves Chibon 9b9f29
        item.token = None
Pierre-Yves Chibon 9b9f29
        self.session.add(item)
Pierre-Yves Chibon 9b9f29
        self.session.commit
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 9b9f29
        # Check the user
Pierre-Yves Chibon 9b9f29
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 9b9f29
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 9b9f29
        self.assertEqual(item.token, None)
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 9b9f29
        # Login but cannot save the session to the DB due to the missing IP
Pierre-Yves Chibon 9b9f29
        # address in the flask request
Pierre-Yves Chibon 9b9f29
        data['password'] = 'barpass'
Pierre-Yves Chibon 9b9f29
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon 9b9f29
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 9b9f29
        self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon 9b9f29
        self.assertIn(
Pierre-Yves Chibon d5929b
            '
Pierre-Yves Chibon d5929b
            'href="/login/?next=http://localhost/">', output.data)
Pierre-Yves Chibon 450dd6
Pierre-Yves Chibon 450dd6
        # I'm not sure if the change was in flask or werkzeug, but in older
Pierre-Yves Chibon 450dd6
        # version flask.request.remote_addr was returning None, while it
Pierre-Yves Chibon 450dd6
        # now returns 127.0.0.1 making our logic pass where it used to
Pierre-Yves Chibon 450dd6
        # partly fail
Pierre-Yves Chibon 450dd6
        if hasattr(flask, '__version__') and \
Pierre-Yves Chibon 450dd6
                tuple(flask.__version__.split('.')) <= (0,12,0):
Pierre-Yves Chibon 450dd6
            self.assertIn(
Pierre-Yves Chibon 450dd6
                'Could not set the session in the db, please report '
Pierre-Yves Chibon 450dd6
                'this error to an admin', output.data)
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 7cc953
        # Make the password invalid
Pierre-Yves Chibon 7cc953
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 7cc953
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 7cc953
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 7cc953
        # Remove the $2$
Pierre-Yves Chibon 7cc953
        item.password = item.password[3:]
Pierre-Yves Chibon 7cc953
        self.session.add(item)
Pierre-Yves Chibon 7cc953
        self.session.commit
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 7cc953
        # Check the password
Pierre-Yves Chibon 7cc953
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 7cc953
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 7cc953
        self.assertFalse(item.password.startswith('$2$'))
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 7cc953
        # Try login again
Pierre-Yves Chibon 7cc953
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon 7cc953
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 7cc953
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon 7cc953
        self.assertIn(
Pierre-Yves Chibon 7cc953
            '<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon 7cc953
        self.assertIn('Username or password of invalid format.', output.data)
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon eac364
        # Make the password be version 1
Pierre-Yves Chibon eac364
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon eac364
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon eac364
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # V1 password
Pierre-Yves Chibon eac364
        password = '%s%s' % ('barpass', None)
Pierre-Yves Chibon eac364
        password = hashlib.sha512(password).hexdigest()
Pierre-Yves Chibon eac364
        item.token = None
Pierre-Yves Chibon eac364
        item.password = '$1$%s' % password
Pierre-Yves Chibon eac364
        self.session.add(item)
Pierre-Yves Chibon eac364
        self.session.commit
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # Check the password
Pierre-Yves Chibon eac364
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon eac364
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon eac364
        self.assertTrue(item.password.startswith('$1$'))
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # Log in with a v1 password
Pierre-Yves Chibon eac364
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Pierre-Yves Chibon eac364
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon eac364
        self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon eac364
        self.assertIn(
Pierre-Yves Chibon d5929b
            '
Pierre-Yves Chibon d5929b
            'href="/login/?next=http://localhost/">', output.data)
Pierre-Yves Chibon 450dd6
Pierre-Yves Chibon 450dd6
        # I'm not sure if the change was in flask or werkzeug, but in older
Pierre-Yves Chibon 450dd6
        # version flask.request.remote_addr was returning None, while it
Pierre-Yves Chibon 450dd6
        # now returns 127.0.0.1 making our logic pass where it used to
Pierre-Yves Chibon 450dd6
        # partly fail
Pierre-Yves Chibon 450dd6
        if hasattr(flask, '__version__') and \
Pierre-Yves Chibon 450dd6
                tuple(flask.__version__.split('.')) <= (0,12,0):
Pierre-Yves Chibon 450dd6
            self.assertIn(
Pierre-Yves Chibon 450dd6
                'Could not set the session in the db, please report '
Pierre-Yves Chibon 450dd6
                'this error to an admin', output.data)
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 10fbdf
    def test_confirm_user(self):
Pierre-Yves Chibon 10fbdf
        """ Test the confirm_user endpoint. """
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon 10fbdf
        output = self.app.get('/confirm/foo', follow_redirects=True)
Pierre-Yves Chibon 10fbdf
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 10fbdf
        self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon 10fbdf
        self.assertIn(
Pierre-Yves Chibon 10fbdf
            'No user associated with this token.', output.data)
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon 10fbdf
        # Create a local user
Pierre-Yves Chibon 10fbdf
        self.test_new_user()
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon 10fbdf
        items = pagure.lib.search_user(self.session)
Pierre-Yves Chibon 10fbdf
        self.assertEqual(3, len(items))
Pierre-Yves Chibon 10fbdf
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 10fbdf
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 10fbdf
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon 10fbdf
        self.assertNotEqual(item.token, None)
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon 10fbdf
        output = self.app.get(
Pierre-Yves Chibon 10fbdf
            '/confirm/%s' % item.token, follow_redirects=True)
Pierre-Yves Chibon 10fbdf
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 10fbdf
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon 10fbdf
        self.assertIn(
Pierre-Yves Chibon 10fbdf
            'Email confirmed, account activated', output.data)
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon 33ff8d
    @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
Pierre-Yves Chibon db170c
    def test_lost_password(self):
Pierre-Yves Chibon db170c
        """ Test the lost_password endpoint. """
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        output = self.app.get('/password/lost')
Pierre-Yves Chibon db170c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon db170c
        self.assertIn('<title>Lost password - Pagure</title>', output.data)
Pierre-Yves Chibon db170c
        self.assertIn(
Pierre-Yves Chibon db170c
            '<form action="/password/lost" method="post">', output.data)</form>
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        # Prepare the data to send
Pierre-Yves Chibon db170c
        data = {
Pierre-Yves Chibon db170c
            'username': 'foouser',
Pierre-Yves Chibon db170c
        }
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        # Missing CSRF
Pierre-Yves Chibon db170c
        output = self.app.post('/password/lost', data=data)
Pierre-Yves Chibon db170c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon db170c
        self.assertIn('<title>Lost password - Pagure</title>', output.data)
Pierre-Yves Chibon db170c
        self.assertIn(
Pierre-Yves Chibon db170c
            '<form action="/password/lost" method="post">', output.data)</form>
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        csrf_token = output.data.split(
farhaanbukhsh 19ad5f
            'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        # With the CSRF  -  But invalid user
Pierre-Yves Chibon db170c
        data['csrf_token'] = csrf_token
Pierre-Yves Chibon db170c
        output = self.app.post(
Pierre-Yves Chibon db170c
            '/password/lost', data=data, follow_redirects=True)
Pierre-Yves Chibon db170c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon db170c
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon db170c
        self.assertIn('Username invalid.', output.data)
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        # With the CSRF and a valid user
Pierre-Yves Chibon db170c
        data['username'] = 'foo'
Pierre-Yves Chibon db170c
        output = self.app.post(
Pierre-Yves Chibon db170c
            '/password/lost', data=data, follow_redirects=True)
Pierre-Yves Chibon db170c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon db170c
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon db170c
        self.assertIn(
Pierre-Yves Chibon db170c
            'Check your email to finish changing your password', output.data)
Pierre-Yves Chibon db170c
Pierre-Yves Chibon db170c
        # With the CSRF and a valid user  -  but too quick after the last one
Pierre-Yves Chibon db170c
        data['username'] = 'foo'
Pierre-Yves Chibon db170c
        output = self.app.post(
Pierre-Yves Chibon db170c
            '/password/lost', data=data, follow_redirects=True)
Pierre-Yves Chibon db170c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon db170c
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon db170c
        self.assertIn(
Pierre-Yves Chibon db170c
            'An email was sent to you less than 3 minutes ago, did you '
Pierre-Yves Chibon db170c
            'check your spam folder? Otherwise, try again after some time.',
Pierre-Yves Chibon db170c
            output.data)
Pierre-Yves Chibon db170c
Pierre-Yves Chibon 33ff8d
    @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
Pierre-Yves Chibon c3ff39
    def test_reset_password(self):
Pierre-Yves Chibon c3ff39
        """ Test the reset_password endpoint. """
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        output = self.app.get('/password/reset/foo', follow_redirects=True)
Pierre-Yves Chibon c3ff39
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon c3ff39
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon c3ff39
        self.assertIn('No user associated with this token.', output.data)
Pierre-Yves Chibon c3ff39
        self.assertIn('<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        self.test_lost_password()
Pierre-Yves Chibon c3ff39
        self.test_new_user()
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        # Check the password
Pierre-Yves Chibon c3ff39
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon c3ff39
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon c3ff39
        self.assertNotEqual(item.token, None)
Pierre-Yves Chibon c3ff39
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        old_password = item.password
Pierre-Yves Chibon c3ff39
        token = item.token
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        output = self.app.get(
Pierre-Yves Chibon c3ff39
            '/password/reset/%s' % token, follow_redirects=True)
Pierre-Yves Chibon c3ff39
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon c3ff39
        self.assertIn('<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon c3ff39
        self.assertIn(
Pierre-Yves Chibon c3ff39
            '
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        data = {
Pierre-Yves Chibon c3ff39
            'password': 'passwd',
Pierre-Yves Chibon c3ff39
            'confirm_password': 'passwd',
Pierre-Yves Chibon c3ff39
        }
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        # Missing CSRF
Pierre-Yves Chibon c3ff39
        output = self.app.post(
Pierre-Yves Chibon c3ff39
            '/password/reset/%s' % token, data=data, follow_redirects=True)
Pierre-Yves Chibon c3ff39
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon c3ff39
        self.assertIn('<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon c3ff39
        self.assertIn(
Pierre-Yves Chibon c3ff39
            '
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        csrf_token = output.data.split(
farhaanbukhsh 19ad5f
            'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon c3ff39
        # With CSRF
Pierre-Yves Chibon c3ff39
        data['csrf_token'] = csrf_token
Pierre-Yves Chibon c3ff39
        output = self.app.post(
Pierre-Yves Chibon c3ff39
            '/password/reset/%s' % token, data=data, follow_redirects=True)
Pierre-Yves Chibon c3ff39
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon c3ff39
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon c3ff39
        self.assertIn('Password changed', output.data)
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon 23b43c
    def test_change_password(self):
Pierre-Yves Chibon 23b43c
        """ Test the change_password endpoint. """
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        # Not logged in, redirects
Pierre-Yves Chibon 23b43c
        output = self.app.get('/password/change', follow_redirects=True)
Pierre-Yves Chibon 23b43c
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 23b43c
        self.assertIn('<title>Login - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
        self.assertIn('<form action="/dologin" method="post">', output.data)</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        user = tests.FakeUser()
Pierre-Yves Chibon 23b43c
        with tests.user_set(pagure.APP, user):
Pierre-Yves Chibon 23b43c
            output = self.app.get('/password/change')
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 404)
Pierre-Yves Chibon 23b43c
            self.assertIn('User not found', output.data)
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon 23b43c
        with tests.user_set(pagure.APP, user):
Pierre-Yves Chibon 23b43c
            output = self.app.get('/password/change')
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
farhaanbukhsh 19ad5f
            self.assertIn(
farhaanbukhsh 19ad5f
                '<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                '<form action="/password/change" method="post">', output.data)</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            data = {
Pierre-Yves Chibon 23b43c
                'old_password': 'foo',
Pierre-Yves Chibon 23b43c
                'password': 'foo',
Pierre-Yves Chibon 23b43c
                'confirm_password': 'foo',
Pierre-Yves Chibon 23b43c
            }
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            # No CSRF token
Pierre-Yves Chibon 23b43c
            output = self.app.post('/password/change', data=data)
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
farhaanbukhsh 19ad5f
            self.assertIn(
farhaanbukhsh 19ad5f
                '<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                '<form action="/password/change" method="post">', output.data)</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            csrf_token = output.data.split(
Pierre-Yves Chibon 23b43c
                'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            # With CSRF  -  Invalid password format
Pierre-Yves Chibon 23b43c
            data['csrf_token'] = csrf_token
Pierre-Yves Chibon 23b43c
            output = self.app.post(
Pierre-Yves Chibon 23b43c
                '/password/change', data=data, follow_redirects=True)
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 23b43c
            self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                'Could not update your password, either user or password '
Pierre-Yves Chibon 23b43c
                'could not be checked', output.data)
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        self.test_new_user()
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        # Remove token of foouser
Pierre-Yves Chibon 23b43c
        item = pagure.lib.search_user(self.session, username='foouser')
Pierre-Yves Chibon 23b43c
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 23b43c
        self.assertNotEqual(item.token, None)
Pierre-Yves Chibon 23b43c
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon 23b43c
        item.token = None
Pierre-Yves Chibon 23b43c
        self.session.add(item)
Pierre-Yves Chibon 23b43c
        self.session.commit()
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        user = tests.FakeUser(username='foouser')
Pierre-Yves Chibon 23b43c
        with tests.user_set(pagure.APP, user):
Pierre-Yves Chibon 23b43c
            output = self.app.get('/password/change')
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
farhaanbukhsh 19ad5f
            self.assertIn(
farhaanbukhsh 19ad5f
                '<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                '<form action="/password/change" method="post">', output.data)</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            data = {
Pierre-Yves Chibon 23b43c
                'old_password': 'foo',
Pierre-Yves Chibon 23b43c
                'password': 'foo',
Pierre-Yves Chibon 23b43c
                'confirm_password': 'foo',
Pierre-Yves Chibon 23b43c
            }
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            # No CSRF token
Pierre-Yves Chibon 23b43c
            output = self.app.post('/password/change', data=data)
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
farhaanbukhsh 19ad5f
            self.assertIn(
farhaanbukhsh 19ad5f
                '<title>Change password - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                '<form action="/password/change" method="post">', output.data)</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            csrf_token = output.data.split(
Pierre-Yves Chibon 23b43c
                'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            # With CSRF  -  Incorrect password
Pierre-Yves Chibon 23b43c
            data['csrf_token'] = csrf_token
Pierre-Yves Chibon 23b43c
            output = self.app.post(
Pierre-Yves Chibon 23b43c
                '/password/change', data=data, follow_redirects=True)
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 23b43c
            self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                'Could not update your password, either user or password '
Pierre-Yves Chibon 23b43c
                'could not be checked', output.data)
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
            # With CSRF  -  Correct password
Pierre-Yves Chibon 23b43c
            data['old_password'] = 'barpass'
Pierre-Yves Chibon 23b43c
            output = self.app.post(
Pierre-Yves Chibon 23b43c
                '/password/change', data=data, follow_redirects=True)
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 23b43c
            self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon 23b43c
            self.assertIn('Password changed', output.data)
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon d25b69
    def test_logout(self):
Pierre-Yves Chibon d25b69
        """ Test the auth_logout endpoint for local login. """
Pierre-Yves Chibon d25b69
Pierre-Yves Chibon d25b69
        output = self.app.get('/logout/', follow_redirects=True)
Pierre-Yves Chibon d25b69
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon d25b69
        self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon d25b69
        self.assertNotIn('You have been logged out', output.data)
Pierre-Yves Chibon d25b69
        self.assertIn(
Pierre-Yves Chibon d5929b
            '
Pierre-Yves Chibon d5929b
            'href="/login/?next=http://localhost/">', output.data)
Pierre-Yves Chibon d25b69
Pierre-Yves Chibon d25b69
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon d25b69
        with tests.user_set(pagure.APP, user):
Pierre-Yves Chibon d25b69
            output = self.app.get('/logout/', follow_redirects=True)
Pierre-Yves Chibon d25b69
            self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon d25b69
            self.assertIn('<title>Home - Pagure</title>', output.data)
Pierre-Yves Chibon d25b69
            self.assertIn('You have been logged out', output.data)
Pierre-Yves Chibon d25b69
            # Due to the way the tests are running we do not actually
Pierre-Yves Chibon d25b69
            # log out
Pierre-Yves Chibon d25b69
            self.assertIn(
Farhaan Bukhsh 49a6a1
                'Log Out',
Pierre-Yves Chibon d25b69
                output.data)
Pierre-Yves Chibon d25b69
Pedro Lima 951fd7
    def test_settings_admin_session_timedout(self):
Pedro Lima 951fd7
        """ Test the admin_session_timedout with settings endpoint. """
Pedro Lima 951fd7
        lifetime = pagure.APP.config.get('ADMIN_SESSION_LIFETIME',
Pedro Lima 951fd7
                                         datetime.timedelta(minutes=15))
Pedro Lima 951fd7
        td1 = datetime.timedelta(minutes=1)
Pedro Lima 951fd7
        # session already expired
Pedro Lima 951fd7
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon 480388
        user.login_time = datetime.datetime.utcnow() - lifetime - td1
Pedro Lima 951fd7
        with tests.user_set(pagure.APP, user):
Pedro Lima 951fd7
            # not following the redirect because user_set contextmanager
Pedro Lima 951fd7
            # will run again for the login page and set back the user
Pedro Lima 951fd7
            # which results in a loop, since admin_session_timedout will
Pedro Lima 951fd7
            # redirect again for the login page
Pedro Lima 951fd7
            output = self.app.get('/settings/')
Pedro Lima 951fd7
            self.assertEqual(output.status_code, 302)
Pedro Lima 951fd7
            self.assertIn('http://localhost/login/', output.location)
Pedro Lima 951fd7
        # session did not expire
Pierre-Yves Chibon 480388
        user.login_time = datetime.datetime.utcnow() - lifetime + td1
Pedro Lima 951fd7
        with tests.user_set(pagure.APP, user):
Pedro Lima 951fd7
            output = self.app.get('/settings/')
Pedro Lima 951fd7
            self.assertEqual(output.status_code, 200)
Pedro Lima 951fd7
Pedro Lima 951fd7
    @patch('flask.flash')
Pedro Lima 951fd7
    @patch('flask.g')
Pedro Lima 951fd7
    def test_admin_session_timedout(self, g, flash):
Pedro Lima 951fd7
        """ Test the call to admin_session_timedout. """
Pedro Lima 951fd7
        lifetime = pagure.APP.config.get('ADMIN_SESSION_LIFETIME',
Pedro Lima 951fd7
                                         datetime.timedelta(minutes=15))
Pedro Lima 951fd7
        td1 = datetime.timedelta(minutes=1)
Pedro Lima 951fd7
        # session already expired
Pedro Lima 951fd7
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon 480388
        user.login_time = datetime.datetime.utcnow() - lifetime - td1
Pedro Lima 951fd7
        g.fas_user = user
Pedro Lima 951fd7
        self.assertTrue(pagure.admin_session_timedout())
Pedro Lima 951fd7
        # session did not expire
Pierre-Yves Chibon 480388
        user.login_time = datetime.datetime.utcnow() - lifetime + td1
Pedro Lima 951fd7
        g.fas_user = user
Pedro Lima 951fd7
        self.assertFalse(pagure.admin_session_timedout())
Pedro Lima 951fd7
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon 0b1c13
if __name__ == '__main__':
Pierre-Yves Chibon 0b1c13
    SUITE = unittest.TestLoader().loadTestsFromTestCase(PagureFlaskLogintests)
Pierre-Yves Chibon 0b1c13
    unittest.TextTestRunner(verbosity=2).run(SUITE)