|
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 |
0b1c13 |
import pygit2
|
|
Pierre-Yves Chibon |
0b1c13 |
from mock import patch
|
|
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 |
6d8b89 |
|
|
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 |
0b1c13 |
|
|
Pierre-Yves Chibon |
0b1c13 |
self.app = pagure.APP.test_client()
|
|
Pierre-Yves Chibon |
0b1c13 |
|
|
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 |
9b9f29 |
'',
|
|
Pierre-Yves Chibon |
9b9f29 |
output.data)
|
|
Pierre-Yves Chibon |
9b9f29 |
self.assertIn(
|
|
Pierre-Yves Chibon |
9b9f29 |
'Could not set the session in the db, please report this error '
|
|
Pierre-Yves Chibon |
9b9f29 |
'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 |
eac364 |
'',
|
|
Pierre-Yves Chibon |
eac364 |
output.data)
|
|
Pierre-Yves Chibon |
eac364 |
self.assertIn(
|
|
Pierre-Yves Chibon |
eac364 |
'Could not set the session in the db, please report this error '
|
|
Pierre-Yves Chibon |
eac364 |
'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 |
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 |
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 |
d25b69 |
'',
|
|
Pierre-Yves Chibon |
d25b69 |
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(
|
|
Pierre-Yves Chibon |
d25b69 |
'log out',
|
|
Pierre-Yves Chibon |
d25b69 |
output.data)
|
|
Pierre-Yves Chibon |
d25b69 |
|
|
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)
|