Holger Frey
7 years ago
5 changed files with 183 additions and 19 deletions
@ -1,18 +0,0 @@ |
|||||||
from sqlalchemy import ( |
|
||||||
Column, |
|
||||||
Index, |
|
||||||
Integer, |
|
||||||
Text, |
|
||||||
) |
|
||||||
|
|
||||||
from .meta import Base |
|
||||||
|
|
||||||
|
|
||||||
class MyModel(Base): |
|
||||||
__tablename__ = 'models' |
|
||||||
id = Column(Integer, primary_key=True) |
|
||||||
name = Column(Text) |
|
||||||
value = Column(Integer) |
|
||||||
|
|
||||||
|
|
||||||
Index('my_index', MyModel.name, unique=True, mysql_length=255) |
|
@ -0,0 +1,92 @@ |
|||||||
|
''' User Account and Roles Models ''' |
||||||
|
|
||||||
|
import enum |
||||||
|
|
||||||
|
from datetime import datetime |
||||||
|
from sqlalchemy import ( |
||||||
|
Column, |
||||||
|
Date, |
||||||
|
Enum, |
||||||
|
Integer, |
||||||
|
Text, |
||||||
|
) |
||||||
|
|
||||||
|
from .meta import Base |
||||||
|
|
||||||
|
|
||||||
|
class Role(enum.Enum): |
||||||
|
''' roles of user accounts ''' |
||||||
|
|
||||||
|
#: new user, email address was not validated |
||||||
|
UNVALIDATED = 'unvalidated' |
||||||
|
|
||||||
|
#: new user, email address validated, not activated by admin |
||||||
|
NEW = 'new' |
||||||
|
|
||||||
|
#: standard user of the system, can place and view orders |
||||||
|
USER = 'user' |
||||||
|
|
||||||
|
#: privileged user of the system, can edit orders |
||||||
|
PURCHASER = 'purchaser' |
||||||
|
|
||||||
|
#: privileged user, can edit orders, users and consumables |
||||||
|
ADMIN = 'admin' |
||||||
|
|
||||||
|
#: a user that is no longer activated |
||||||
|
INACTIVE = 'inactive' |
||||||
|
|
||||||
|
@property |
||||||
|
def principal(self): |
||||||
|
''' returns the principal identifier of the role ''' |
||||||
|
return 'role:' + self.value.lower() |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
''' string representation ''' |
||||||
|
return self.value.capitalize() |
||||||
|
|
||||||
|
|
||||||
|
class User(Base): |
||||||
|
''' A user of the application ''' |
||||||
|
|
||||||
|
__tablename__ = 'users' |
||||||
|
|
||||||
|
#: primary key |
||||||
|
id = Column(Integer, primary_key=True) |
||||||
|
#: unique user name |
||||||
|
username = Column(Text, nullable=False, unique=True) |
||||||
|
#: hashed password, see ``ordr2.security`` |
||||||
|
password_hash = Column(Text, nullable=False) |
||||||
|
#: role of the user, see ``ordr2.models.users.Role`` |
||||||
|
role = Column(Enum(Role), nullable=False) |
||||||
|
|
||||||
|
first_name = Column(Text, nullable=False) |
||||||
|
last_name = Column(Text, nullable=False) |
||||||
|
email = Column(Text, nullable=False, unique=True) |
||||||
|
date_created = Column(Date, nullable=False, default=datetime.utcnow) |
||||||
|
|
||||||
|
@property |
||||||
|
def principal(self): |
||||||
|
''' returns the principal identifier for the user ''' |
||||||
|
return 'user:{}'.format(self.id) |
||||||
|
|
||||||
|
@property |
||||||
|
def role_principals(self): |
||||||
|
''' returns the principal identifiers for the user's role ''' |
||||||
|
principals = [self.role.principal] |
||||||
|
if self.role is Role.PURCHASER: |
||||||
|
# a purchaser is also a user |
||||||
|
principals.append(Role.USER.principal) |
||||||
|
elif self.role is Role.ADMIN: |
||||||
|
# an admin is also a purchaser and a user |
||||||
|
principals.append(Role.PURCHASER.principal) |
||||||
|
principals.append(Role.USER.principal) |
||||||
|
return principals |
||||||
|
|
||||||
|
@property |
||||||
|
def is_active(self): |
||||||
|
''' is true if the user has an active role ''' |
||||||
|
return self.role in (Role.USER, Role.PURCHASER, Role.ADMIN) |
||||||
|
|
||||||
|
def __str__(self): |
||||||
|
''' string representation ''' |
||||||
|
return str(self.username) |
@ -0,0 +1,89 @@ |
|||||||
|
''' Test package for ordr2.models.users ''' |
||||||
|
|
||||||
|
import pytest |
||||||
|
|
||||||
|
|
||||||
|
# tests for users.Role |
||||||
|
|
||||||
|
def test_role_principals(): |
||||||
|
''' test Role.principal, a caluclated property ''' |
||||||
|
from ordr2.models.users 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.users 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 users.User |
||||||
|
|
||||||
|
def test_user_principal(): |
||||||
|
''' test the user principal calculated property ''' |
||||||
|
from ordr2.models.users 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.users 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.users import User, Role |
||||||
|
|
||||||
|
role = Role[role_name] |
||||||
|
user = User(role=role) |
||||||
|
|
||||||
|
assert user.is_active == is_active |
||||||
|
|
||||||
|
|
||||||
|
def test_user_string_representation(): |
||||||
|
''' test the string representation of the user ''' |
||||||
|
from ordr2.models.users import User, Role |
||||||
|
|
||||||
|
user = User(username='FooBar') |
||||||
|
|
||||||
|
assert str(user) == 'FooBar' |
Reference in new issue