This repository has been archived on 2024-05-31. You can view files and clone it, but cannot push or open issues or pull requests.
devicehub-teal/ereuse_devicehub/resources/user/models.py

156 lines
5.0 KiB
Python

import json
from uuid import uuid4
from citext import CIText
from flask import current_app as app
from flask_login import UserMixin
from sqlalchemy import BigInteger, Boolean, Column, Sequence
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy_utils import EmailType, PasswordType
from teal.db import IntEnum
from ereuse_devicehub.db import db
from ereuse_devicehub.resources.enums import SessionType
from ereuse_devicehub.resources.inventory.model import Inventory
from ereuse_devicehub.resources.models import STR_SIZE, Thing
class User(UserMixin, Thing):
__table_args__ = {'schema': 'common'}
id = Column(UUID(as_uuid=True), default=uuid4, primary_key=True)
email = Column(EmailType, nullable=False, unique=True)
password = Column(
PasswordType(
max_length=STR_SIZE,
onload=lambda **kwargs: dict(
schemes=app.config['PASSWORD_SCHEMES'], **kwargs
),
)
)
token = Column(UUID(as_uuid=True), default=uuid4, unique=True, nullable=False)
active = Column(Boolean, default=True, nullable=False)
phantom = Column(Boolean, default=False, nullable=False)
api_keys_dlt = Column(CIText(), nullable=True)
inventories = db.relationship(
Inventory,
backref=db.backref('users', lazy=True, collection_class=set),
secondary=lambda: UserInventory.__table__,
collection_class=set,
)
# todo set restriction that user has, at least, one active db
def __init__(
self, email, password=None, inventories=None, active=True, phantom=False
) -> None:
"""Creates an user.
:param email:
:param password:
:param inventories: A set of Inventory where the user has
access to. If none, the user is granted access to the current
inventory.
:param active: allow active and deactive one account without delete the account
:param phantom: it's util for identify the phantom accounts
create during the trade actions
"""
inventories = inventories or {Inventory.current}
super().__init__(
email=email,
password=password,
inventories=inventories,
active=active,
phantom=phantom,
)
def __repr__(self) -> str:
return '<User {0.email}>'.format(self)
@property
def type(self) -> str:
return self.__class__.__name__
@property
def individual(self):
"""The individual associated for this database, or None."""
return next(iter(self.individuals), None)
@property
def code(self):
"""Code of phantoms accounts"""
if not self.phantom:
return
return self.email.split('@')[0].split('_')[1]
@property
def is_active(self):
"""Alias because flask-login expects `is_active` attribute"""
return self.active
@property
def get_full_name(self):
# TODO(@slamora) create first_name & last_name fields???
# needs to be discussed related to Agent <--> User concepts
return self.email
def check_password(self, password):
# take advantage of SQL Alchemy PasswordType to verify password
return self.password == password
def set_new_dlt_keys(self, password):
if 'trublo' not in app.blueprints.keys():
return
from ereuseapi.methods import register_user
from modules.trublo.utils import encrypt
api_dlt = app.config.get('API_DLT')
data = register_user(api_dlt)
data = json.dumps(data)
self.api_keys_dlt = encrypt(password, data)
def get_dlt_keys(self, password):
if 'trublo' not in app.blueprints.keys():
return {}
from modules.trublo.utils import decrypt
data = decrypt(password, self.api_keys_dlt)
return json.loads(data)
def reset_dlt_keys(self, password, data):
if 'trublo' not in app.blueprints.keys():
return
from modules.trublo.utils import encrypt
data = json.dumps(data)
self.api_keys_dlt = encrypt(password, data)
class UserInventory(db.Model):
"""Relationship between users and their inventories."""
__table_args__ = {'schema': 'common'}
user_id = db.Column(db.UUID(as_uuid=True), db.ForeignKey(User.id), primary_key=True)
inventory_id = db.Column(
db.Unicode(), db.ForeignKey(Inventory.id), primary_key=True
)
class Session(Thing):
__table_args__ = {'schema': 'common'}
id = Column(BigInteger, Sequence('device_seq'), primary_key=True)
expired = Column(BigInteger, default=0)
token = Column(UUID(as_uuid=True), default=uuid4, unique=True, nullable=False)
type = Column(IntEnum(SessionType), default=SessionType.Internal, nullable=False)
user_id = db.Column(db.UUID(as_uuid=True), db.ForeignKey(User.id))
user = db.relationship(
User,
backref=db.backref('sessions', lazy=True, collection_class=set),
collection_class=set,
)
def __str__(self) -> str:
return '{0.token}'.format(self)