You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
5.5 KiB
186 lines
5.5 KiB
''' 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
|
|
|