''' Test package for ordr2.models.account ''' import pytest from datetime import datetime, timedelta from pyramid.testing import DummyRequest from .. import get_user, app_config # tests for account.Role def test_role_principals(): ''' test Role.principal, a caluclated property ''' from ordr2.models.account import Role assert Role.UNVALIDATED.principal == 'role:unvalidated' assert Role.NEW.principal == 'role:new' assert Role.USER.principal == 'role:user' assert Role.PURCHASER.principal == 'role:purchaser' assert Role.ADMIN.principal == 'role:admin' assert Role.INACTIVE.principal == 'role:inactive' def test_role_str(): ''' test the string representation of roles ''' from ordr2.models.account import Role assert str(Role.UNVALIDATED) == 'Unvalidated' assert str(Role.NEW) == 'New' assert str(Role.USER) == 'User' assert str(Role.PURCHASER) == 'Purchaser' assert str(Role.ADMIN) == 'Admin' assert str(Role.INACTIVE) == 'Inactive' # tests for account.User def test_user_principal(): ''' test the user principal calculated property ''' from ordr2.models.account import User user = User(id=3) assert user.principal == 'user:3' @pytest.mark.parametrize( 'role_name, principals', [ ('UNVALIDATED', ['role:unvalidated']), ('NEW', ['role:new']), ('USER', ['role:user']), ('PURCHASER', ['role:purchaser', 'role:user']), ('ADMIN', ['role:admin', 'role:purchaser', 'role:user']), ('INACTIVE', ['role:inactive']) ] ) def test_user_role_principals(role_name, principals): ''' test the user's role principals calculated property ''' from ordr2.models.account import User, Role role = Role[role_name] user = User(role=role) assert user.role_principals == principals @pytest.mark.parametrize( 'role_name, is_active', [ ('UNVALIDATED', False), ('NEW', False), ('USER', True), ('PURCHASER', True), ('ADMIN', True), ('INACTIVE', False) ] ) def test_user_is_active(role_name, is_active): ''' test if is_active returns correct value based on the user's role ''' from ordr2.models.account import User, Role role = Role[role_name] user = User(role=role) assert user.is_active == is_active def test_user_set_password(): ''' test password hash generation ''' from ordr2.models.account import User, passlib_context passlib_context.update(schemes=['argon2', 'bcrypt']) user = User(password_hash=None) password = 'Fish Slapping Dance' user.set_password(password) assert user.password_hash.startswith('$argon2') assert password not in user.password_hash def test_user_check_password_ok(): ''' test password check succeeds''' from ordr2.models.account import User, passlib_context passlib_context.update(schemes=['argon2', 'bcrypt'], deprecated='auto') user = User(password_hash=None) user.set_password('Fish Slapping Dance') assert user.check_password('Fish Slapping Dance') is True def test_user_check_password_fails(): ''' test password check fails ''' from ordr2.models.account import User, passlib_context passlib_context.update(schemes=['argon2', 'bcrypt'], deprecated='auto') user = User(password_hash=None) user.set_password('Fish Slapping Dance') assert user.check_password('Argument Clininc') is False def test_user_check_password_deprecated_hash(): ''' test password check updates deprecated hash with new algorithm ''' from ordr2.models.account import User from ordr2.security import passlib_context passlib_context.update(schemes=['argon2', 'bcrypt'], deprecated='auto') password = 'Fish Slapping Dance' bcrypt_hash = passlib_context.hash(password, scheme='bcrypt') user = User(password_hash=bcrypt_hash) assert user.check_password(password) assert user.password_hash != bcrypt_hash assert user.password_hash.startswith('$argon2') def test_user_string_representation(): ''' test the string representation of the user ''' from ordr2.models.account import User, Role user = User(username='FooBar') assert str(user) == 'FooBar' def test_user_issue_token(app_config): from ordr2.models.account import Token, TokenSubject request = DummyRequest() request.registry.settings['token_expiry.change_email'] = 10 user = get_user('user') payload = {'test-key': 'test-data'} token = user.issue_token(request, TokenSubject.CHANGE_EMAIL, payload) expected_expires = datetime.utcnow() + timedelta(minutes=10) # one second drift is still considered ok assert token.expires.timestamp() == pytest.approx( expected_expires.timestamp(), abs=1 ) assert token.owner == user assert token.payload == payload assert token.subject == TokenSubject.CHANGE_EMAIL def test_token_issue(app_config): from ordr2.models.account import Token, TokenSubject request = DummyRequest() request.registry.settings['token_expiry.change_email'] = 10 user = get_user('user') payload = {'test-key': 'test-data'} result = Token.issue(request, user, TokenSubject.CHANGE_EMAIL, payload) expected_expires = datetime.utcnow() + timedelta(minutes=10) # one second drift is still considered ok assert result.expires.timestamp() == pytest.approx( expected_expires.timestamp(), abs=1 ) assert len(result.hash) == 32 assert result.owner == user assert result.payload == payload assert result.subject == TokenSubject.CHANGE_EMAIL assert user.tokens[0] == result