barker/barker/models/auth.py

154 lines
5.0 KiB
Python

import random
import string
import uuid
from hashlib import md5
from datetime import datetime
from sqlalchemy.schema import ForeignKey, Table
from sqlalchemy import Column, Boolean, Unicode, Integer, DateTime, UniqueConstraint
from sqlalchemy.orm import synonym, relationship
from barker.models.guidtype import GUID
from .meta import Base
def encrypt(val):
return md5(val.encode('utf-8') + "v2".encode('utf-8')).hexdigest()
class Client(Base):
__tablename__ = 'clients'
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
code = Column('code', Integer, unique=True, nullable=False)
name = Column('name', Unicode(255), unique=True, nullable=False)
enabled = Column('enabled', Boolean, nullable=False)
otp = Column('otp', Integer)
creation_date = Column('creation_date', DateTime(timezone=True), nullable=False)
login_history = relationship('LoginHistory', backref='client')
def __init__(self, code=None, name=None, enabled=False, otp=None, creation_date=None, id=None):
self.code = code
self.name = name
self.enabled = enabled
self.otp = otp
self.creation_date = datetime.utcnow() if creation_date is None else creation_date
self.id = id
@classmethod
def by_code(cls, code, dbsession):
if code is None:
return None
if not isinstance(code, int):
code = int(code)
return dbsession.query(cls).filter(cls.code == code).first()
@classmethod
def create(cls, dbsession):
client_code = random.randint(1000, 9999)
otp = random.randint(1000, 9999)
name = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6))
client = Client(client_code, name, False, otp)
dbsession.add(client)
return client
user_roles = Table(
'user_roles', Base.metadata,
Column('id', GUID(), primary_key=True, default=uuid.uuid4),
Column('user_id', GUID(), ForeignKey('users.id'), nullable=False),
Column('role_id', GUID(), ForeignKey('roles.id'), nullable=False),
UniqueConstraint('user_id', 'role_id')
)
role_permissions = Table(
'role_permissions', Base.metadata,
Column('id', GUID(), primary_key=True, default=uuid.uuid4),
Column('permission_id', GUID(), ForeignKey('permissions.id'), nullable=False),
Column('role_id', GUID(), ForeignKey('roles.id'), nullable=False),
UniqueConstraint('permission_id', 'role_id')
)
class User(Base):
__tablename__ = 'users'
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('name', Unicode(255), unique=True, nullable=False)
_password = Column('password', Unicode(60), nullable=False)
locked_out = Column('locked_out', Boolean, nullable=False)
roles = relationship("Role", secondary=user_roles, order_by="Role.name")
login_history = relationship('LoginHistory', backref='user')
def _get_password(self):
return self._password
def _set_password(self, password):
self._password = encrypt(password)
password = property(_get_password, _set_password)
password = synonym('_password', descriptor=password)
@property
def __name__(self):
return self.name
def __init__(self, name=None, password=None, locked_out=None, id=None):
self.name = name
self.password = password
self.locked_out = locked_out
self.id = id
@classmethod
def auth(cls, name, password, dbsession):
if password is None:
return False, None
user = dbsession.query(User).filter(User.name.ilike(name)).first()
if not user:
return False, None
if user.password != encrypt(password) or user.locked_out:
return False, None
else:
return True, user
class LoginHistory(Base):
__tablename__ = 'login_history'
__table_args__ = (UniqueConstraint('user_id', 'client_id', 'date'),)
id = Column('login_history_id', GUID(), primary_key=True, default=uuid.uuid4)
user_id = Column('user_id', GUID(), ForeignKey('users.id'), nullable=False)
client_id = Column('client_id', GUID(), ForeignKey('clients.id'), nullable=False)
date = Column('date', DateTime(timezone=True), nullable=False)
def __init__(self, user_id=None, client_id=None, date=None, id=None):
self.user_id = user_id
self.client_id = client_id
self.date = datetime.utcnow() if date is None else date
self.id = id
class Role(Base):
__tablename__ = 'roles'
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('name', Unicode(255), unique=True)
def __init__(self, name=None, id=None):
self.name = name
self.id = id
class Permission(Base):
__tablename__ = 'permissions'
id = Column('id', GUID(), primary_key=True, default=uuid.uuid4)
name = Column('name', Unicode(255), unique=True)
roles = relationship("Role", secondary=role_permissions, backref="permissions")
def __init__(self, name=None, id=None):
self.name = name
self.id = id