Exemple #1
0
class Client(db.Model, OAuth2ClientMixin):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete='CASCADE'))
    user = db.relationship('User')

    #overide
    token_endpoint_auth_method = db.Column(db.String(48),
                                           default='client_secret_post')
    grant_type = db.Column(db.Text,
                           nullable=False,
                           default='client_credentials')
    client_id = db.Column(db.String(24), index=True, default=gen_salt(24))
    client_secret = db.Column(db.String(48), default=gen_salt(48))

    def signup_client(self, u):

        self.user_id = u.id
        self.client_name = u.username
        self.scope = u.role
        db.session.add(self)
        db.session.commit()

    def make_secret_response(self):
        return {
            'client_id': self.client_id,
            'client_secret': self.client_secret,
        }
Exemple #2
0
class ItemSimilarity(ResourceMixin, db.Model):
    #TODO use hybrid property
    __tablename__ = 'item_similarity'
    id = db.Column(db.Integer, primary_key=True)

    article_id1 = db.Column(db.Integer, nullable=False)
    article_id2 = db.Column(db.Integer, nullable=False)
    similarity_doc = db.Column(db.Float, nullable=False)

    def __init__(self, id1, id2, similarity_doc):
        self.article_id1 = id1
        self.article_id2 = id2
        self.similarity_doc = similarity_doc

    @classmethod
    def check_exist(cls, id1, id2):

        if cls.query \
        .filter(
            or_(
            and_(cls.article_id1 == id1 \
                ,cls.article_id2 == id2),
                and_(cls.article_id1 == id2 \
                    ,cls.article_id2 == id1)
            )
        ).first():
            return True
        else:
            return False

    @classmethod
    def delete_by_article_id(cls, article_id):
        delete_count = cls.query.filter(
            or_(cls.article_id1 == article_id,
                cls.article_id2 == article_id)).delete(
                    synchronize_session=False)
        db.session.commit()

        return True
Exemple #3
0
class Token(db.Model, OAuth2TokenMixin):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id', ondelete='CASCADE'))
    user = db.relationship('User')
Exemple #4
0
class User(ResourceMixin, db.Model, UserMixin):
    ROLE = OrderedDict([('member', 'Member'), ('admin', 'Admin')])

    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)

    # Authentication.
    role = db.Column(db.Enum(*ROLE, name='role_types', native_enum=False),
                     index=True,
                     nullable=False,
                     server_default='member')
    active = db.Column('is_active',
                       db.Boolean(),
                       nullable=False,
                       server_default='1')
    username = db.Column(db.String(24), index=True)
    email = db.Column(db.String(255),
                      unique=True,
                      index=True,
                      nullable=False,
                      server_default='')
    password = db.Column(db.String(128), nullable=False, server_default='')

    #relationship
    client = db.relationship('Client', backref='users', uselist=False)

    # Activity tracking.
    current_sign_in_on = db.Column(db.DateTime())
    last_sign_in_on = db.Column(db.DateTime())

    def __init__(self, email, password, username=None, role='member'):
        self.username = username
        if role in self.ROLE.keys():
            self.role = role
        else:
            raise BadRequest(
                description='Only accept admin or member in role parameter ')
        self.email = email
        self.password = User.encrypt_password(password)
        c = Client()
        c.signup_client(self)
        self.client = c

    @classmethod
    def find_by_identity(cls, identity):
        """
        Find a user by their e-mail or username.

        :param identity: Email or username
        :type identity: str
        :return: User instance
        """
        return User.query.filter((User.email == identity)
                                 | (User.username == identity)).first()

    @classmethod
    def find_by_uid(cls, uid):
        return User.query.filter(User.id == uid).first()

    @classmethod
    def encrypt_password(cls, plaintext_password):
        """
        Hash a plaintext string using PBKDF2. This is good enough according
        to the NIST (National Institute of Standards and Technology).

        In other words while bcrypt might be superior in practice, if you use
        PBKDF2 properly (which we are), then your passwords are safe.

        :param plaintext_password: Password in plain text
        :type plaintext_password: str
        :return: str
        """
        if plaintext_password:
            return generate_password_hash(plaintext_password)

        return None

    def is_active(self):
        """
        Return whether or not the user account is active, this satisfies
        Flask-Login by overwriting the default value.

        :return: bool
        """
        return self.active

    def authenticated(self, password):
        return check_password_hash(self.password, password)

    def update_activity_tracking(self, ip_address):
        """
        Update various fields on the user that's related to meta data on their
        account, such as the sign in count and ip address, etc..

        :param ip_address: IP address
        :type ip_address: str
        :return: SQLAlchemy commit results
        """
        self.sign_in_count += 1

        self.last_sign_in_on = self.current_sign_in_on
        self.last_sign_in_ip = self.current_sign_in_ip

        self.current_sign_in_on = tzware_datetime()

        return self.save()

    def get_user_id(self):
        return self.id
class ResourceMixin(object):
    # Keep track when records are created and updated.
    created_on = db.Column(db.DateTime(), default=tzware_datetime)
    updated_on = db.Column(db.DateTime(),
                           default=tzware_datetime,
                           onupdate=tzware_datetime)

    # @classmethod
    # def sort_by(cls, field, direction):
    #     """
    #     Validate the sort field and direction.

    #     :param field: Field name
    #     :type field: str
    #     :param direction: Direction
    #     :type direction: str
    #     :return: tuple
    #     """
    #     if field not in cls.__table__.columns:
    #         field = 'created_on'

    #     if direction not in ('asc', 'desc'):
    #         direction = 'asc'

    #     return field, direction

    @classmethod
    def get_bulk_action_ids(cls, scope, ids, omit_ids=[], query=''):
        """
        Determine which IDs are to be modified.

        :param scope: Affect all or only a subset of items
        :type scope: str
        :param ids: List of ids to be modified
        :type ids: list
        :param omit_ids: Remove 1 or more IDs from the list
        :type omit_ids: list
        :param query: Search query (if applicable)
        :type query: str
        :return: list
        """
        omit_ids = map(str, omit_ids)

        if scope == 'all_search_results':
            # Change the scope to go from selected ids to all search results.
            ids = cls.query.with_entities(cls.id).filter(cls.search(query))

            # SQLAlchemy returns back a list of tuples, we want a list of strs.
            ids = [str(item[0]) for item in ids]

        # Remove 1 or more items from the list, this could be useful in spots
        # where you may want to protect the current user from deleting themself
        # when bulk deleting user accounts.
        if omit_ids:
            ids = [id for id in ids if id not in omit_ids]

        return ids

    @classmethod
    def bulk_delete(cls, ids):
        """
        Delete 1 or more model instances.

        :param ids: List of ids to be deleted
        :type ids: list
        :return: Number of deleted instances
        """
        delete_count = cls.query.filter(
            cls.id.in_(ids)).delete(synchronize_session=False)
        db.session.commit()

        return delete_count

    def save(self):
        """
        Save a model instance.

        :return: Model instance
        """
        db.session.add(self)
        db.session.commit()

        return self

    def delete(self):
        """
        Delete a model instance.

        :return: db.session.commit()'s result
        """
        db.session.delete(self)
        return db.session.commit()

    def __str__(self):
        """
        Create a human readable version of a class instance.

        :return: self
        """
        obj_id = hex(id(self))
        columns = self.__table__.c.keys()

        values = ', '.join("%s=%r" % (n, getattr(self, n)) for n in columns)
        return '<%s %s(%s)>' % (obj_id, self.__class__.__name__, values)
Exemple #6
0
class Article(db.Model, ResourceMixin):
    __tablename__ = 'articles'
    id = db.Column(db.Integer, primary_key=True, index=True)
    title = db.Column(db.String(100), nullable=False, unique=True)
    content = db.Column(db.Text(collation='utf8mb4_bin'))
    ask = db.Column(db.Text(collation='utf8mb4_bin'))
    answer = db.Column(db.Text(collation='utf8mb4_bin'))
    type = db.Column(db.String(100))
    division = db.Column(db.String(100))
    tag = db.Column(db.Text)
    is_delete = db.Column(db.Boolean(), nullable=False, server_default='0')

    def __init__(self, title, type, division, ask='', answer='', **kwargs):
        self.title = title
        self.ask = ask
        self.answer = answer
        self.type = type
        self.division = division
        self.tag = kwargs.get('tag')
        self.key = gen_salt(15)

        _content = f'民眾提問:\n{ask}\n醫師回答:\n{answer}'
        self.content = kwargs.get('content') or _content

    @property
    def info(self):
        return {
            'id': self.id,
            'type': self.type,
            'division': self.division,
            'title': self.title,
            'content': self.content,
            'ask': self.ask,
            'answer': self.answer,
            'created_on': self.created_on,
            'updated_on': self.updated_on
        }

    @classmethod
    def get_all(cls):
        return cls.query.filter(cls.is_delete == 0).all()

    def update(self, **kwargs):
        from recommender.blueprints.article.tasks import del_vector_and_similarity, cache_vector
        fix_contnet = False
        if kwargs.get('title'):
            self.title = kwargs.get('title')

        if kwargs.get('ask'):
            self.ask = kwargs.get('ask')
            fix_contnet = True

        if kwargs.get('asnwer'):
            self.asnwer = kwargs.get('asnwer')
            fix_contnet = True

        if kwargs.get('type'):
            self.type = kwargs.get('type')

        if kwargs.get('division'):
            self.division = kwargs.get('division')

        if kwargs.get('tag'):
            self.tag = kwargs.get('tag')

        if fix_contnet:
            _content = f'民眾提問:\n{self.ask}\n醫師回答:\n{self.answer}'
            self.content = _content

        if kwargs.get('content'):
            self.content = kwargs.get('content')
        del_vector_and_similarity(self.id)
        cache_vector(self)
        self.save()