wcs/tests/test_register.py

281 lines
9.2 KiB
Python

# -*- coding: utf-8 -*-
import pytest
import hashlib
import re
import shutil
from quixote import cleanup
from wcs.qommon import force_str
from wcs.qommon.http_request import HTTPRequest
from wcs.qommon.ident.password_accounts import PasswordAccount
from utilities import get_app, create_temporary_pub, clean_temporary_pub
def pytest_generate_tests(metafunc):
if 'pub' in metafunc.fixturenames:
metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
@pytest.fixture
def pub(request):
pub = create_temporary_pub(sql_mode=(request.param == 'sql'))
req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
pub.set_app_dir(req)
pub.cfg['misc'] = {'charset': 'utf-8'}
pub.cfg['identification'] = {'methods': ['password']}
pub.cfg['identities'] = {'creation': 'self'}
pub.write_cfg()
return pub
def teardown_module(module):
clean_temporary_pub()
def test_no_user_registration(pub):
# makes sure the page is not published unless configured
app = get_app(pub)
pub.cfg['identification'] = {'methods': ['password']}
pub.cfg['identities'] = {'creation': 'admin'}
pub.write_cfg()
app.get('/register/', status=404)
pub.cfg['identities'] = {'creation': 'self'}
pub.write_cfg()
def test_link_on_login_page(pub):
app = get_app(pub)
page = app.get('/login/')
assert '/register/' in page.text
def test_no_password(pub):
app = get_app(pub)
page = app.get('/register/')
register_form = page.forms[0]
assert 'username' in register_form.fields
assert 'password' not in register_form.fields
def test_user_registration_mismatch(pub):
pub.cfg['passwords'] = {'generate': False}
pub.write_cfg()
app = get_app(pub)
page = app.get('/register/')
register_form = page.forms[0]
register_form['username'] = 'foo'
register_form['password$pwd1'] = 'bar'
register_form['password$pwd2'] = 'baz'
resp = register_form.submit()
assert 'Passwords do not match' in resp.text
def do_user_registration(pub, username='foo', password='bar'):
initial_user_count = pub.user_class.count()
initial_account_count = PasswordAccount.count()
app = get_app(pub)
page = app.get('/register/')
register_form = page.forms[0]
register_form['username'] = username
if password is not None:
register_form['password$pwd1'] = password
register_form['password$pwd2'] = password
resp = register_form.submit()
assert resp.status_int == 302
assert resp.location == 'http://example.net/login/'
assert pub.user_class.count() == initial_user_count + 1
assert PasswordAccount.count() == initial_account_count + 1
account = PasswordAccount.get(username)
user = account.get_user()
if password is not None:
user2 = PasswordAccount.get_with_credentials(username, password)
assert user.id == user2.id
def test_user_registration(pub):
pub.user_class.wipe()
PasswordAccount.wipe()
pub.cfg['passwords'] = {'generate': False}
pub.write_cfg()
do_user_registration(pub)
account = PasswordAccount.get('foo')
assert account.password == 'bar' # check it's in clear text
def test_user_password_hashing(pub):
pub.user_class.wipe()
PasswordAccount.wipe()
pub.cfg['passwords'] = {'generate': False, 'hashing_algo': 'sha256'}
pub.write_cfg()
do_user_registration(pub)
account = PasswordAccount.get('foo')
assert account.password == hashlib.sha256(b'bar').hexdigest()
def test_user_password_accents(pub):
pub.user_class.wipe()
PasswordAccount.wipe()
pub.cfg['passwords'] = {'generate': False, 'hashing_algo': None}
pub.write_cfg()
password = force_str(u'fooë')
do_user_registration(pub, password=password)
account = PasswordAccount.get('foo')
assert account.password == password
def test_admin_notification(pub, emails):
pub.cfg['identities'] = {'creation': 'self', 'notify-on-register': True}
pub.write_cfg()
pub.user_class.wipe()
PasswordAccount.wipe()
user = pub.user_class(name='admin')
user.is_admin = True
user.email = 'admin@localhost'
user.store()
pub.cfg['passwords'] = {'generate': False}
pub.write_cfg()
do_user_registration(pub)
assert emails.get('New Registration')
assert emails.get('New Registration').get('email_rcpt') == ['admin@localhost']
def test_user_notification(pub, emails):
pub.cfg['identities'] = {'creation': 'self', 'notify-on-register': False,
'email-as-username': True}
pub.write_cfg()
pub.user_class.wipe()
PasswordAccount.wipe()
user = pub.user_class(name='admin')
user.is_admin = True
user.email = 'admin@localhost'
user.store()
pub.cfg['passwords'] = {'generate': True}
pub.write_cfg()
do_user_registration(pub, username='foo@localhost', password=None)
account = PasswordAccount.get('foo@localhost')
assert emails.get('Welcome to example.net')
assert emails.get('Welcome to example.net').get('to') == 'foo@localhost'
assert account.password in emails.get('Welcome to example.net').get('payload')
def test_user_login(pub):
pub.cfg['identities'] = {'creation': 'self', 'notify-on-register': False}
pub.user_class.wipe()
PasswordAccount.wipe()
pub.cfg['passwords'] = {'generate': False, 'hashing_algo': 'sha256'}
pub.write_cfg()
do_user_registration(pub)
# wrong password
app = get_app(pub)
resp = app.get('/login/')
resp.forms[0]['username'] = 'foo'
resp.forms[0]['password'] = 'foo'
resp = resp.forms[0].submit()
assert 'Invalid credentials' in resp.text
# correct passwod
app = get_app(pub)
resp = app.get('/login/')
resp.forms[0]['username'] = 'foo'
resp.forms[0]['password'] = 'bar'
resp = resp.forms[0].submit()
assert resp.location == 'http://example.net/'
def test_forgotten(pub, emails):
pub.cfg['identities'] = {'creation': 'self', 'notify-on-register': False}
pub.user_class.wipe()
PasswordAccount.wipe()
pub.cfg['passwords'] = {'generate': False, 'hashing_algo': 'sha256'}
pub.write_cfg()
do_user_registration(pub)
user_id = pub.user_class.select()[0].id
app = get_app(pub)
resp = app.get('/login/')
assert '/ident/password/forgotten' in resp.text
resp = app.get('/ident/password/forgotten')
resp.forms[0]['username'] = 'bar' # this account doesn't exist
resp = resp.forms[0].submit()
assert 'There is no user with that name or it has no email contact.'
resp = app.get('/ident/password/forgotten')
resp.forms[0]['username'] = 'foo' # this account doesn't have an email
resp = resp.forms[0].submit()
assert 'There is no user with that name or it has no email contact.'
user = pub.user_class.get(user_id)
user.email = 'foo@localhost'
user.store()
resp = app.get('/ident/password/forgotten')
resp.forms[0]['username'] = 'foo'
resp = resp.forms[0].submit()
assert 'A token for changing your password has been emailed to you.' in resp.text
assert emails.get('Change Password Request')
assert emails.get('Change Password Request')['to'] == 'foo@localhost'
body = emails.get('Change Password Request')['payload']
confirm_urls = re.findall(r'http://.*\w', body)
assert 'a=cfmpw' in confirm_urls[0]
assert 'a=cxlpw' in confirm_urls[1]
# cancel request
resp = app.get(confirm_urls[1])
assert 'Your request has been cancelled' in resp.text
resp = app.get(confirm_urls[1])
assert 'The token you submitted does not exist' in resp.text
# new forgotten request
resp = app.get('/ident/password/forgotten')
resp.forms[0]['username'] = 'foo'
resp = resp.forms[0].submit()
assert 'A token for changing your password has been emailed to you.' in resp.text
body = emails.get('Change Password Request')['payload']
confirm_urls = re.findall(r'http://.*\w', body)
assert 'a=cfmpw' in confirm_urls[0]
assert 'a=cxlpw' in confirm_urls[1]
resp = app.get(confirm_urls[0])
assert 'New password sent by email' in resp.text
assert emails.get('Your new password')
# check new password is working
new_password = re.findall('password: (.*)\n', emails.get('Your new password')['payload'])[0]
resp = app.get('/login/')
resp.forms[0]['username'] = 'foo'
resp.forms[0]['password'] = new_password
resp = resp.forms[0].submit()
assert resp.status_int == 302
# check forgotten page when user can choose the password
pub.cfg['passwords'] = {'generate': False, 'can_change': True}
pub.write_cfg()
resp = app.get('/ident/password/forgotten')
resp.forms[0]['username'] = 'foo'
resp = resp.forms[0].submit()
assert 'A token for changing your password has been emailed to you.' in resp.text
body = emails.get('Change Password Request')['payload']
confirm_urls = re.findall(r'http://.*\w', body)
assert 'a=cfmpw' in confirm_urls[0]
assert 'a=cxlpw' in confirm_urls[1]
resp = app.get(confirm_urls[0])
resp.forms[0]['new_password$pwd1'] = 'foo'
resp.forms[0]['new_password$pwd2'] = 'foo'
resp = resp.forms[0].submit()
assert resp.status_int == 302
# check new password is working
resp = app.get('/login/')
resp.forms[0]['username'] = 'foo'
resp.forms[0]['password'] = 'foo'
resp = resp.forms[0].submit()
assert resp.status_int == 302