Browse Source

added first draft of user model

master
Holger Frey 7 years ago
parent
commit
fdf0208c89
  1. 2
      ordr2/models/__init__.py
  2. 18
      ordr2/models/mymodel.py
  3. 92
      ordr2/models/users.py
  4. 1
      tests/models/__init__.py
  5. 89
      tests/models/users.py

2
ordr2/models/__init__.py

@ -11,7 +11,7 @@ import zope.sqlalchemy @@ -11,7 +11,7 @@ import zope.sqlalchemy
# import or define all models here to ensure they are attached to the
# Base.metadata prior to any initialization routines
from .mymodel import MyModel # flake8: noqa
from .users import User, Role # flake8: noqa
# run configure_mappers after defining all of the models to ensure
# all relationships can be setup

18
ordr2/models/mymodel.py

@ -1,18 +0,0 @@ @@ -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)

92
ordr2/models/users.py

@ -0,0 +1,92 @@ @@ -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)

1
tests/models/__init__.py

@ -0,0 +1 @@ @@ -0,0 +1 @@
''' Test package for ordr2.models '''

89
tests/models/users.py

@ -0,0 +1,89 @@ @@ -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'