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 67d1cc
from __future__ import unicode_literals, absolute_import
Aurélien Bompard 626417
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
Aurélien Bompard 626417
import six
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 930073
import pagure.lib.query
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
Clement Verna 109c4b
class PagureFlaskLogintests(tests.SimplePagureTest):
Pierre-Yves Chibon 0b1c13
    """ Tests for flask app controller of pagure """
Pierre-Yves Chibon 0b1c13
Pierre-Yves Chibon bcc20e
    def setUp(self):
Pierre-Yves Chibon bcc20e
        """ Create the application with PAGURE_AUTH being local. """
Pierre-Yves Chibon bcc20e
        super(PagureFlaskLogintests, self).setUp()
Pierre-Yves Chibon bcc20e
Pierre-Yves Chibon bcc20e
        app = pagure.flask_app.create_app({
Pierre-Yves Chibon bcc20e
            'DB_URL': self.dbpath,
Pierre-Yves Chibon bcc20e
            'PAGURE_AUTH': 'local'
Pierre-Yves Chibon bcc20e
        })
Pierre-Yves Chibon bcc20e
        # Remove the log handlers for the tests
Pierre-Yves Chibon bcc20e
        app.logger.handlers = []
Pierre-Yves Chibon bcc20e
Pierre-Yves Chibon bcc20e
        self.app = app.test_client()
Pierre-Yves Chibon bcc20e
Pierre-Yves Chibon bcc20e
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Pierre-Yves Chibon bcc20e
    def test_front_page(self):
Pierre-Yves Chibon bcc20e
        """ Test the front page. """
Pierre-Yves Chibon bcc20e
        # First access the front page
Pierre-Yves Chibon bcc20e
        output = self.app.get('/')
Pierre-Yves Chibon bcc20e
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon bcc20e
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
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 930073
        items = pagure.lib.query.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)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon b94671
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output.get_data(as_text=True))</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)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon b94671
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon b94671
Aurélien Bompard 626417
        csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon b94671
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output.get_data(as_text=True))</form>
Aurélien Bompard 626417
        self.assertIn('Username already taken.', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('Email address already taken.', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon b94671
        self.assertIn(
Pierre-Yves Chibon b94671
            'User created, please check your email to activate the account',
Aurélien Bompard 626417
            output.get_data(as_text=True))
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b94671
        # Check after:
Pierre-Yves Chibon 930073
        items = pagure.lib.query.search_user(self.session)
Farhaan Bukhsh ecae95
        self.assertEqual(3, len(items))
Pierre-Yves Chibon b94671
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Clement Verna 5be1f7
    @patch.dict('pagure.config.config', {'CHECK_SESSION_IP': False})
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon a4c666
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon a4c666
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Aurélien Bompard 626417
        self.assertIn('Insufficient information provided', output.get_data(as_text=True))
Pierre-Yves Chibon a4c666
Aurélien Bompard 626417
        csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon a4c666
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Aurélien Bompard 626417
        self.assertIn('Username or password invalid.', output.get_data(as_text=True))
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 930073
        items = pagure.lib.query.search_user(self.session)
Farhaan Bukhsh ecae95
        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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon a4c666
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon a4c666
        self.assertIn(
Pierre-Yves Chibon a4c666
            'Invalid user, did you confirm the creation with the url '
Aurélien Bompard 626417
            'provided by email?', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
farhaanbukhsh fa9239
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Aurélien Bompard 626417
        self.assertIn('Username or password invalid.', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
farhaanbukhsh 66f5d8
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
farhaanbukhsh 66f5d8
        self.assertIn(
farhaanbukhsh 66f5d8
            'Invalid user, did you confirm the creation with the url '
Aurélien Bompard 626417
            'provided by email?', output.get_data(as_text=True))
farhaanbukhsh fa9239
Pierre-Yves Chibon 9b9f29
        # Confirm the user so that we can log in
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.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 b130e5
        self.session.commit()
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 9b9f29
        # Check the user
Pierre-Yves Chibon 930073
        item = pagure.lib.query.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)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output_text)
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 d5b214
        if hasattr(flask, '__version__'):
Pierre-Yves Chibon d5b214
            flask_v = tuple(int(el) for el in flask.__version__.split('.'))
Aurélien Bompard 13bcde
            if flask_v < (0, 12, 0):
Pierre-Yves Chibon d5b214
                self.assertIn(
Ryan Lerch ca4b80
                    '
Aurélien Bompard 626417
                    'href="/login/?next=http://localhost/">', output_text)
Pierre-Yves Chibon d5b214
                self.assertIn(
Pierre-Yves Chibon d5b214
                    'Could not set the session in the db, please report '
Aurélien Bompard 626417
                    'this error to an admin', output_text)
Pierre-Yves Chibon d5b214
            else:
Pierre-Yves Chibon d5b214
                self.assertIn(
Pierre-Yves Chibon d5b214
                    '
Pierre-Yves Chibon 29b1ab
                    'href="/logout/?next=http://localhost/dashboard/projects">', output_text)
Pierre-Yves Chibon 9b9f29
Pierre-Yves Chibon 7cc953
        # Make the password invalid
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 7cc953
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 29b1ab
        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 b130e5
        self.session.commit()
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 7cc953
        # Check the password
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 7cc953
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 29b1ab
        self.assertFalse(item.password.startswith('$2$'))
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon 7cc953
        # Try login again
Pierre-Yves Chibon b130e5
        output = self.app.post(
Pierre-Yves Chibon b130e5
            '/dologin', data=data, follow_redirects=True,
Pierre-Yves Chibon b130e5
            environ_base={'REMOTE_ADDR': '127.0.0.1'})
Pierre-Yves Chibon 7cc953
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 7cc953
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Aurélien Bompard 626417
        self.assertIn('Username or password of invalid format.', output.get_data(as_text=True))
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon b130e5
        # Check the password is still not of a known version
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon eac364
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 29b1ab
        self.assertFalse(item.password.startswith('$1$'))
Pierre-Yves Chibon 29b1ab
        self.assertFalse(item.password.startswith('$2$'))
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # V1 password
Pierre-Yves Chibon eac364
        password = '%s%s' % ('barpass', None)
Aurélien Bompard 619e2a
        if isinstance(password, six.text_type):
Aurélien Bompard 626417
            password = password.encode('utf-8')
Aurélien Bompard 626417
        password = hashlib.sha512(password).hexdigest().encode("utf-8")
Pierre-Yves Chibon eac364
        item.token = None
Aurélien Bompard 626417
        item.password = b'$1$' + password
Pierre-Yves Chibon eac364
        self.session.add(item)
Pierre-Yves Chibon b130e5
        self.session.commit()
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # Check the password
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon eac364
        self.assertEqual(item.user, 'foouser')
Aurélien Bompard 626417
        self.assertTrue(item.password.startswith(b'$1$'))
Pierre-Yves Chibon eac364
Pierre-Yves Chibon eac364
        # Log in with a v1 password
Clement Verna 5be1f7
        output = self.app.post('/dologin', data=data, follow_redirects=True,
Clement Verna 5be1f7
                               environ_base={'REMOTE_ADDR': '127.0.0.1'})
Pierre-Yves Chibon eac364
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output_text)
Aurélien Bompard 626417
        self.assertIn('Welcome foouser', output_text)
Aurélien Bompard 626417
        self.assertIn('Activity', output_text)
Pierre-Yves Chibon 450dd6
Pierre-Yves Chibon b130e5
        # Check the password got upgraded to version 2
Aurélien Bompard 13bcde
        self.session.commit()
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon b130e5
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 29b1ab
        self.assertTrue(item.password.startswith('$2$'))
Pierre-Yves Chibon b130e5
Aurélien Bompard d90ed4
        # We have set the REMOTE_ADDR in the request, so this works with all
Aurélien Bompard d90ed4
        # versions of Flask.
Aurélien Bompard d90ed4
        self.assertIn(
Aurélien Bompard d90ed4
            '
Ryan Lerch 336cd6
            'href="/logout/?next=http://localhost/dashboard/projects">', output_text)
Pierre-Yves Chibon 7cc953
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Pierre-Yves Chibon 1baa7f
    @patch.dict('pagure.config.config', {'CHECK_SESSION_IP': False})
Pierre-Yves Chibon 1baa7f
    def test_do_login_and_redirect(self):
Pierre-Yves Chibon 1baa7f
        """ Test the do_login endpoint with a non-default redirect. """
Pierre-Yves Chibon 1baa7f
        # This has all the data needed
Pierre-Yves Chibon 1baa7f
        data = {
Pierre-Yves Chibon 1baa7f
            'username': 'foouser',
Pierre-Yves Chibon 1baa7f
            'password': 'barpass',
Pierre-Yves Chibon 1baa7f
            'csrf_token': self.get_csrf(url='/login/'),
Pierre-Yves Chibon 1baa7f
            'next_url': 'http://localhost/test/',
Pierre-Yves Chibon 1baa7f
        }
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Create a local user
Pierre-Yves Chibon 1baa7f
        self.test_new_user()
Pierre-Yves Chibon 1baa7f
        self.session.commit()
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Confirm the user so that we can log in
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 1baa7f
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 1baa7f
        self.assertNotEqual(item.token, None)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Remove the token
Pierre-Yves Chibon 1baa7f
        item.token = None
Pierre-Yves Chibon 1baa7f
        self.session.add(item)
Pierre-Yves Chibon 1baa7f
        self.session.commit()
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Check the user
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 1baa7f
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 1baa7f
        self.assertEqual(item.token, None)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Add a test project to the user
Pierre-Yves Chibon 74da3a
        tests.create_projects(self.session, user_id=3)
Pierre-Yves Chibon 1baa7f
        tests.create_projects_git(os.path.join(self.path, 'repos'))
Pierre-Yves Chibon 1baa7f
        output = self.app.get('/test')
Pierre-Yves Chibon 1baa7f
        output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 1baa7f
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 1baa7f
        self.assertIn(
Pierre-Yves Chibon 1baa7f
            '<title>Overview - test - Pagure</title>', output_text)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Login and redirect to the test project
Pierre-Yves Chibon 1baa7f
        output = self.app.post(
Pierre-Yves Chibon 1baa7f
            '/dologin', data=data, follow_redirects=True,
Pierre-Yves Chibon 1baa7f
            environ_base={'REMOTE_ADDR': '127.0.0.1'})
Pierre-Yves Chibon 1baa7f
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 1baa7f
        output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 1baa7f
        self.assertIn(
Pierre-Yves Chibon 1baa7f
            '<title>Overview - test - Pagure</title>', output_text)
Pierre-Yves Chibon 1baa7f
        self.assertIn(
Pierre-Yves Chibon 1baa7f
            '
Pierre-Yves Chibon 1baa7f
            'href="/logout/?next=http://localhost/test/">', output_text)
Pierre-Yves Chibon 1baa7f
        self.assertIn(
Pierre-Yves Chibon 1baa7f
            'Settings', output_text)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Pierre-Yves Chibon 1baa7f
    @patch.dict('pagure.config.config', {'CHECK_SESSION_IP': False})
Pierre-Yves Chibon 1baa7f
    def test_has_settings(self):
Pierre-Yves Chibon 1baa7f
        """ Test that user can see the Settings button when they are logged
Pierre-Yves Chibon 1baa7f
        in. """
Pierre-Yves Chibon 1baa7f
        # Create a local user
Pierre-Yves Chibon 1baa7f
        self.test_new_user()
Pierre-Yves Chibon 1baa7f
        self.session.commit()
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Remove the token
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 1baa7f
        item.token = None
Pierre-Yves Chibon 1baa7f
        self.session.add(item)
Pierre-Yves Chibon 1baa7f
        self.session.commit()
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Check the user
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 1baa7f
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 1baa7f
        self.assertEqual(item.token, None)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Add a test project to the user
Pierre-Yves Chibon 1baa7f
        tests.create_projects(self.session)
Pierre-Yves Chibon 1baa7f
        tests.create_projects_git(os.path.join(self.path, 'repos'))
Pierre-Yves Chibon 1baa7f
        output = self.app.get('/test')
Pierre-Yves Chibon 1baa7f
        output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 1baa7f
        self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 1baa7f
        self.assertIn(
Pierre-Yves Chibon 1baa7f
            '<title>Overview - test - Pagure</title>', output_text)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
        # Login and redirect to the test project
Pierre-Yves Chibon 1baa7f
        user = tests.FakeUser(username='pingou')
Pierre-Yves Chibon 1baa7f
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon 1baa7f
            output = self.app.get('/test')
Pierre-Yves Chibon 1baa7f
            self.assertEqual(output.status_code, 200)
Pierre-Yves Chibon 1baa7f
            output_text = output.get_data(as_text=True)
Pierre-Yves Chibon 1baa7f
            self.assertIn(
Pierre-Yves Chibon 1baa7f
                '<title>Overview - test - Pagure</title>', output_text)
Pierre-Yves Chibon 1baa7f
            self.assertIn(
Pierre-Yves Chibon 1baa7f
                'Settings',
Pierre-Yves Chibon 1baa7f
                output_text)
Pierre-Yves Chibon 1baa7f
Pierre-Yves Chibon 1baa7f
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Farhaan Bukhsh ecae95
    @patch('pagure.lib.notify.send_email', MagicMock(return_value=True))
Farhaan Bukhsh ecae95
    def test_non_ascii_password(self):
Farhaan Bukhsh ecae95
        """ Test login and create user functionality when the password is
Farhaan Bukhsh ecae95
            non-ascii.
Farhaan Bukhsh ecae95
        """
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Check before:
Pierre-Yves Chibon 930073
        items = pagure.lib.query.search_user(self.session)
Farhaan Bukhsh ecae95
        self.assertEqual(2, len(items))
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # First access the new user page
Farhaan Bukhsh ecae95
        output = self.app.get('/user/new')
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output_text)</form>
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Create the form to send there
Farhaan Bukhsh ecae95
        # This has all the data needed
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        data = {
Farhaan Bukhsh ecae95
            'user': 'foo',
Farhaan Bukhsh ecae95
            'fullname': 'user foo',
Farhaan Bukhsh ecae95
            'email_address': 'foo@bar.com',
Farhaan Bukhsh ecae95
            'password': 'ö',
Farhaan Bukhsh ecae95
            'confirm_password': 'ö',
Farhaan Bukhsh ecae95
        }
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit this form  -  Doesn't work since there is no csrf token
Farhaan Bukhsh ecae95
        output = self.app.post('/user/new', data=data)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output_text)</form>
Farhaan Bukhsh ecae95
Aurélien Bompard 626417
        csrf_token = output_text.split(
Farhaan Bukhsh ecae95
            'name="csrf_token" type="hidden" value="')[1].split('">')[0]
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit the form with the csrf token
Farhaan Bukhsh ecae95
        data['csrf_token'] = csrf_token
Farhaan Bukhsh ecae95
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/user/new" method="post">', output_text)</form>
Aurélien Bompard 626417
        self.assertIn('Username already taken.', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit the form with another username
Farhaan Bukhsh ecae95
        data['user'] = 'foobar'
Farhaan Bukhsh ecae95
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>New user - Pagure</title>', output_text)
Aurélien Bompard 626417
        self.assertIn('Email address already taken.', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit the form with proper data
Farhaan Bukhsh ecae95
        data['email_address'] = 'foobar@foobar.com'
Farhaan Bukhsh ecae95
        output = self.app.post('/user/new', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Farhaan Bukhsh ecae95
            'User created, please check your email to activate the account',
Aurélien Bompard 626417
            output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Check after:
Pierre-Yves Chibon 930073
        items = pagure.lib.query.search_user(self.session)
Farhaan Bukhsh ecae95
        self.assertEqual(3, len(items))
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Checking for the /login page
Farhaan Bukhsh ecae95
        output = self.app.get('/login/')
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # This has all the data needed
Farhaan Bukhsh ecae95
        data = {
Farhaan Bukhsh ecae95
            'username': 'foob_bar',
Farhaan Bukhsh ecae95
            'password': 'ö',
Farhaan Bukhsh ecae95
        }
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit this form  -  Doesn't work since there is no csrf token
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Aurélien Bompard 626417
        self.assertIn('Insufficient information provided', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit the form with the csrf token  -  but invalid user
Farhaan Bukhsh ecae95
        data['csrf_token'] = csrf_token
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Aurélien Bompard 626417
        self.assertIn('Username or password invalid.', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Submit the form with the csrf token  -  but user not confirmed
Farhaan Bukhsh ecae95
        data['username'] = "foobar"
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Farhaan Bukhsh ecae95
        self.assertIn(
Farhaan Bukhsh ecae95
            'Invalid user, did you confirm the creation with the url '
Aurélien Bompard 626417
            'provided by email?', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # User in the DB, csrf provided  -  but wrong password submitted
Farhaan Bukhsh ecae95
        data['password'] = 'öö'
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Aurélien Bompard 626417
        self.assertIn('Username or password invalid.', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # When account is not confirmed i.e user_obj != None
Farhaan Bukhsh ecae95
        data['password'] = 'ö'
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output_text)
Farhaan Bukhsh ecae95
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/dologin" method="post">', output_text)</form>
Farhaan Bukhsh ecae95
        self.assertIn(
Farhaan Bukhsh ecae95
            'Invalid user, did you confirm the creation with the url '
Aurélien Bompard 626417
            'provided by email?', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Confirm the user so that we can log in
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foobar')
Farhaan Bukhsh ecae95
        self.assertEqual(item.user, 'foobar')
Farhaan Bukhsh ecae95
        self.assertNotEqual(item.token, None)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Remove the token
Farhaan Bukhsh ecae95
        item.token = None
Farhaan Bukhsh ecae95
        self.session.add(item)
Farhaan Bukhsh ecae95
        self.session.commit()
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Login but cannot save the session to the DB due to the missing IP
Farhaan Bukhsh ecae95
        # address in the flask request
Farhaan Bukhsh ecae95
        data['password'] = 'ö'
Farhaan Bukhsh ecae95
        output = self.app.post('/dologin', data=data, follow_redirects=True)
Farhaan Bukhsh ecae95
        self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
        output_text = output.get_data(as_text=True)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output_text)
Pierre-Yves Chibon d5b214
Pierre-Yves Chibon d5b214
        # I'm not sure if the change was in flask or werkzeug, but in older
Pierre-Yves Chibon d5b214
        # version flask.request.remote_addr was returning None, while it
Pierre-Yves Chibon d5b214
        # now returns 127.0.0.1 making our logic pass where it used to
Pierre-Yves Chibon d5b214
        # partly fail
Pierre-Yves Chibon d5b214
        if hasattr(flask, '__version__'):
Pierre-Yves Chibon d5b214
            flask_v = tuple(int(el) for el in flask.__version__.split('.'))
Pierre-Yves Chibon d5b214
            if flask_v <= (0, 12, 0):
Pierre-Yves Chibon d5b214
                self.assertIn(
Ryan Lerch ca4b80
                    '
Aurélien Bompard 626417
                    'href="/login/?next=http://localhost/">', output_text)
Pierre-Yves Chibon d5b214
                self.assertIn(
Pierre-Yves Chibon d5b214
                    'Could not set the session in the db, please report '
Aurélien Bompard 626417
                    'this error to an admin', output_text)
Pierre-Yves Chibon d5b214
            else:
Pierre-Yves Chibon d5b214
                self.assertIn(
Pierre-Yves Chibon d5b214
                    '
Pierre-Yves Chibon 29b1ab
                    'href="/logout/?next=http://localhost/dashboard/projects">', output_text)
Farhaan Bukhsh ecae95
Farhaan Bukhsh ecae95
        # Check the user
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foobar')
Farhaan Bukhsh ecae95
        self.assertEqual(item.user, 'foobar')
Farhaan Bukhsh ecae95
        self.assertEqual(item.token, None)
Farhaan Bukhsh ecae95
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)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 10fbdf
        self.assertIn(
Aurélien Bompard 626417
            'No user associated with this token.', output.get_data(as_text=True))
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 930073
        items = pagure.lib.query.search_user(self.session)
Farhaan Bukhsh ecae95
        self.assertEqual(3, len(items))
Pierre-Yves Chibon 930073
        item = pagure.lib.query.search_user(self.session, username='foouser')
Pierre-Yves Chibon 10fbdf
        self.assertEqual(item.user, 'foouser')
Pierre-Yves Chibon 29b1ab
        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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 10fbdf
        self.assertIn(
Aurélien Bompard 626417
            'Email confirmed, account activated', output.get_data(as_text=True))
Pierre-Yves Chibon 10fbdf
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
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)
Aurélien Bompard 626417
        self.assertIn('<title>Lost password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon db170c
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/password/lost" method="post">', output.get_data(as_text=True))</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)
Aurélien Bompard 626417
        self.assertIn('<title>Lost password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon db170c
        self.assertIn(
Aurélien Bompard 626417
            '<form action="/password/lost" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon db170c
Aurélien Bompard 626417
        csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('Username invalid.', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon db170c
        self.assertIn(
Aurélien Bompard 626417
            'Check your email to finish changing your password', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
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.',
Aurélien Bompard 626417
            output.get_data(as_text=True))
Pierre-Yves Chibon db170c
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('No user associated with this token.', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('<form action="/dologin" method="post">', output.get_data(as_text=True))</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 930073
        item = pagure.lib.query.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 29b1ab
        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)
Aurélien Bompard 626417
        self.assertIn('<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon c3ff39
        self.assertIn(
Aurélien Bompard 626417
            '
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)
Aurélien Bompard 626417
        self.assertIn('<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon c3ff39
        self.assertIn(
Aurélien Bompard 626417
            '
Pierre-Yves Chibon c3ff39
Aurélien Bompard 626417
        csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('Password changed', output.get_data(as_text=True))
Pierre-Yves Chibon c3ff39
Pierre-Yves Chibon bcc20e
    @patch('pagure.ui.login._check_session_cookie', MagicMock(return_value=True))
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
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)
Aurélien Bompard 626417
        self.assertIn('<title>Login - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertIn('<form action="/dologin" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        user = tests.FakeUser()
Pierre-Yves Chibon b130e5
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon 23b43c
            output = self.app.get('/password/change')
Pierre-Yves Chibon 23b43c
            self.assertEqual(output.status_code, 404)
Aurélien Bompard 626417
            self.assertIn('User not found', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon 23b43c
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon b130e5
        with tests.user_set(self.app.application, 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(
Aurélien Bompard 626417
                '<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Aurélien Bompard 626417
                '<form action="/password/change" method="post">', output.get_data(as_text=True))</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(
Aurélien Bompard 626417
                '<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Aurélien Bompard 626417
                '<form action="/password/change" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon 23b43c
Aurélien Bompard 626417
            csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
            self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                'Could not update your password, either user or password '
Aurélien Bompard 626417
                'could not be checked', output.get_data(as_text=True))
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 930073
        item = pagure.lib.query.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 29b1ab
        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 b130e5
        with tests.user_set(self.app.application, 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(
Aurélien Bompard 626417
                '<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Aurélien Bompard 626417
                '<form action="/password/change" method="post">', output.get_data(as_text=True))</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(
Aurélien Bompard 626417
                '<title>Change password - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Aurélien Bompard 626417
                '<form action="/password/change" method="post">', output.get_data(as_text=True))</form>
Pierre-Yves Chibon 23b43c
Aurélien Bompard 626417
            csrf_token = output.get_data(as_text=True).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)
Aurélien Bompard 626417
            self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
            self.assertIn(
Pierre-Yves Chibon 23b43c
                'Could not update your password, either user or password '
Aurélien Bompard 626417
                'could not be checked', output.get_data(as_text=True))
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)
Aurélien Bompard 626417
            self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
            self.assertIn('Password changed', output.get_data(as_text=True))
Pierre-Yves Chibon 23b43c
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
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)
Aurélien Bompard 626417
        self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
        self.assertNotIn('You have been logged out', output.get_data(as_text=True))
Pierre-Yves Chibon d25b69
        self.assertIn(
Ryan Lerch ca4b80
            '
Aurélien Bompard 626417
            'href="/login/?next=http://localhost/">', output.get_data(as_text=True))
Pierre-Yves Chibon d25b69
Pierre-Yves Chibon d25b69
        user = tests.FakeUser(username='foo')
Pierre-Yves Chibon b130e5
        with tests.user_set(self.app.application, user):
Pierre-Yves Chibon d25b69
            output = self.app.get('/logout/', follow_redirects=True)
Pierre-Yves Chibon d25b69
            self.assertEqual(output.status_code, 200)
Aurélien Bompard 626417
            self.assertIn('<title>Home - Pagure</title>', output.get_data(as_text=True))
Aurélien Bompard 626417
            self.assertIn('You have been logged out', output.get_data(as_text=True))
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(
Ryan Lerch 336cd6
                '
Ryan Lerch 336cd6
                'http://localhost/dashboard/projects">Log Out',
Aurélien Bompard 626417
                output.get_data(as_text=True))
Pierre-Yves Chibon d25b69
Pierre-Yves Chibon b130e5
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Pedro Lima 951fd7
    def test_settings_admin_session_timedout(self):
Pedro Lima 951fd7
        """ Test the admin_session_timedout with settings endpoint. """
Pierre-Yves Chibon b130e5
        lifetime = pagure.config.config.get(
Pierre-Yves Chibon b130e5
            'ADMIN_SESSION_LIFETIME', 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
Pierre-Yves Chibon b130e5
        with tests.user_set(self.app.application, 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
Pierre-Yves Chibon b130e5
        with tests.user_set(self.app.application, 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')
Pierre-Yves Chibon b130e5
    @patch('flask.session')
Pierre-Yves Chibon b130e5
    def test_admin_session_timedout(self, session, g, flash):
Pedro Lima 951fd7
        """ Test the call to admin_session_timedout. """
Pierre-Yves Chibon b130e5
        lifetime = pagure.config.config.get(
Pierre-Yves Chibon b130e5
            'ADMIN_SESSION_LIFETIME', 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
Pierre-Yves Chibon b130e5
        self.assertTrue(pagure.flask_app.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
Pierre-Yves Chibon b130e5
        self.assertFalse(pagure.flask_app.admin_session_timedout())
Pedro Lima 951fd7
Patrick Uiterwijk ce6d6d
    @patch.dict('pagure.config.config', {'PAGURE_AUTH': 'local'})
Patrick Uiterwijk ce6d6d
    def test_force_logout(self):
Patrick Uiterwijk ce6d6d
        """ Test forcing logout. """
Patrick Uiterwijk ce6d6d
        user = tests.FakeUser(username='foo')
Patrick Uiterwijk ce6d6d
        with tests.user_set(self.app.application, user, keep_get_user=True):
Patrick Uiterwijk ce6d6d
            # Test that accessing settings works
Patrick Uiterwijk ce6d6d
            output = self.app.get('/settings')
Patrick Uiterwijk ce6d6d
            self.assertEqual(output.status_code, 200)
Patrick Uiterwijk ce6d6d
Patrick Uiterwijk ce6d6d
            # Now logout everywhere
Slavek Kabrda 2200ff
            data = {'csrf_token': self.get_csrf()}
Slavek Kabrda 2200ff
            output = self.app.post('/settings/forcelogout/', data=data)
Patrick Uiterwijk ce6d6d
            self.assertEqual(output.status_code, 302)
Patrick Uiterwijk ce6d6d
            self.assertEqual(output.headers['Location'],
Patrick Uiterwijk ce6d6d
                             'http://localhost/settings')
Patrick Uiterwijk ce6d6d
Patrick Uiterwijk ce6d6d
            # We should now get redirected to index, because our session became
Patrick Uiterwijk ce6d6d
            # invalid
Patrick Uiterwijk ce6d6d
            output = self.app.get('/settings')
Patrick Uiterwijk ce6d6d
            self.assertEqual(output.headers['Location'],
Patrick Uiterwijk ce6d6d
                             'http://localhost/')
Patrick Uiterwijk ce6d6d
Patrick Uiterwijk ce6d6d
            # After changing the login_time to now, the session should again be
Patrick Uiterwijk ce6d6d
            # valid
Patrick Uiterwijk ce6d6d
            user.login_time = datetime.datetime.utcnow()
Patrick Uiterwijk ce6d6d
            output = self.app.get('/')
Ryan Lerch 336cd6
            self.assertEqual(output.status_code, 302)
Patrick Uiterwijk ce6d6d
Patrick Uiterwijk ce6d6d
Pierre-Yves Chibon 0b1c13
if __name__ == '__main__':
Pierre-Yves Chibon 393f31
    unittest.main(verbosity=2)