brewman/brewman/models/auth.py

148 lines
4.8 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, Session
from sqlalchemy.dialects.postgresql import UUID
from .meta import Base
def encrypt(val):
return md5(val.encode("utf-8") + "Salt".encode("utf-8")).hexdigest()
class Client(Base):
__tablename__ = "auth_clients"
id = Column("client_id", UUID(as_uuid=True), 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 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_role = Table(
"user_roles",
Base.metadata,
Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4),
Column("user_id", UUID(as_uuid=True), ForeignKey("auth_users.id")),
Column("role_id", UUID(as_uuid=True), ForeignKey("auth_roles.id")),
)
role_permission = Table(
"role_permissions",
Base.metadata,
Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4),
Column("permission_id", UUID(as_uuid=True), ForeignKey("auth_permissions.id")),
Column("role_id", UUID(as_uuid=True), ForeignKey("auth_roles.id")),
)
class User(Base):
__tablename__ = "auth_users"
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column("username", Unicode(255), unique=True)
_password = Column("password", Unicode(60))
locked_out = Column("disabled", Boolean)
roles = relationship("Role", secondary=user_role)
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, db) -> any:
if password is None:
return None
user = db.query(User).filter(User.name.ilike(name)).first()
if not user:
return None
if user.password != encrypt(password) or user.locked_out:
return None
else:
return user
class LoginHistory(Base):
__tablename__ = "auth_login_history"
__table_args__ = (UniqueConstraint("user_id", "client_id", "date"),)
id = Column("login_history_id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
user_id = Column("user_id", UUID(as_uuid=True), ForeignKey("auth_users.id"), nullable=False)
client_id = Column("client_id", UUID(as_uuid=True), ForeignKey("auth_clients.client_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__ = "auth_roles"
id = Column("id", UUID(as_uuid=True), 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__ = "auth_permissions"
id = Column("id", UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column("name", Unicode(255), unique=True)
roles = relationship("Role", secondary=role_permission, backref="permissions")
def __init__(self, name=None, id_=None):
self.name = name
self.id = id_