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") + "v2".encode("utf-8")).hexdigest() class Client(Base): __tablename__ = "clients" id = Column("id", Integer, primary_key=True) 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) def __init__(self, id_=None, name=None, enabled=False, otp=None, creation_date=None): self.id = id_ self.name = name self.enabled = enabled self.otp = otp self.creation_date = creation_date or datetime.utcnow() @classmethod def by_id(cls, id_: int, db: Session): if id_ is None: return None if not isinstance(id_, int): id_ = int(id_) return db.query(cls).filter(cls.id == id_).first() @classmethod def create(cls, db: Session): 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) db.add(client) return client user_roles = 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("users.id"), nullable=False), Column("role_id", UUID(as_uuid=True), ForeignKey("roles.id"), nullable=False), UniqueConstraint("user_id", "role_id"), ) role_permissions = 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("permissions.id"), nullable=False), Column("role_id", UUID(as_uuid=True), ForeignKey("roles.id"), nullable=False), UniqueConstraint("permission_id", "role_id"), ) class User(Base): __tablename__ = "users" id = Column("id", UUID(as_uuid=True), 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") 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: Session): 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 Role(Base): __tablename__ = "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__ = "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_permissions, backref="permissions") def __init__(self, name=None, id_=None): self.name = name self.id = id_