示例#1
0
class User(UserMixin, db.Model, BaseModel):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    email = db.Column(db.String(255), unique=True, nullable=False)
    first_name = db.Column(db.String, nullable=True)
    last_name = db.Column(db.String, nullable=True)
    full_name = db.Column(db.String, nullable=True)
    avatar_url = db.Column(db.String, nullable=True)
    is_active = db.Column(db.Boolean, nullable=False, default=True)
    # password_hash = db.Column(db.String(255), nullable=False)
    registered_on = db.Column(db.DateTime,
                              nullable=False,
                              default=datetime.utcnow())
    # admin = db.Column(db.Boolean, nullable=False, default=False)
    roles = db.relationship('UserRole',
                            secondary='users_user_roles',
                            lazy='dynamic',
                            backref=db.backref('users', lazy=True))
    symbols = db.relationship('CurrencyPair',
                              secondary=symbol_subscribers,
                              lazy='subquery',
                              backref=db.backref('users', lazy=True))

    buy_percentage = db.Column(db.Float, nullable=True, default=0.5)
    sell_percentage = db.Column(db.Float, nullable=True, default=0.5)

    close_bet_interval_in_minutes = db.Column(db.Float,
                                              nullable=True,
                                              default=10)

    def __repr__(self):
        return '<User {0}>'.format(self.email)

    def add_role(self, role_name):
        try:
            role = UserRole.query.filter_by(role_name=role_name).first()
            if role not in self.roles:
                return self.roles.append(role)
            else:
                return self.roles
        except exc.IdentifierError:
            pass

    def get_full_name(self):
        return "{0} {1}".format(self.first_name, self.last_name)

    @property
    def get_user_roles_names_list(self):
        return [each.role_name for each in self.roles]
示例#2
0
class Task(db.Model):
    __tablename__ = 'tasks'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(250), unique=True, nullable=False)
    description = db.Column(db.String)
    creation_date = db.Column(db.TIMESTAMP,
                              server_default=db.func.current_timestamp(),
                              nullable=False)
    status = db.Column(db.Integer, nullable=False, default=0)
    # Relationships
    users = db.relationship('User',
                            secondary=task_users,
                            backref=db.backref('tasks'))

    @hybrid_property
    def nr_users(self):
        return len(self.annotations)

    def update_users(self, user_ids):
        new_users = db.session.query(User).filter(User.id.in_(user_ids)).all()
        self.users = new_users
        db.session.commit()

    def __init__(self, name, status=0):
        self.name = name
        self.status = status
示例#3
0
class Post(ResourceMixin, db.Model):
    __tablename__ = 'posts'

    # Relationships
    comments = db.relationship('Comment',
                               backref=db.backref('post', uselist=False),
                               passive_deletes=True,
                               lazy='dynamic')

    # Properties
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), index=True, unique=True, nullable=False)
    body = db.Column(db.ARRAY(db.String), nullable=False)
    summary = db.Column(db.String(250), nullable=False)
    img_src = db.Column(db.String(200))
    thumbnail_src = db.Column(db.String(200))
    view_count = db.Column(db.Integer, server_default='0')

    # Foreign Keys
    author_id = db.Column(db.Integer, db.ForeignKey('staff.id'))
    practice_area_id = db.Column(db.Integer,
                                 db.ForeignKey('practice_areas.id'))

    def __init__(self, **kwargs):
        # Call Flask-SQLAlchemy's constructor.
        super(Post, self).__init__(**kwargs)

    @hybrid_property
    def slug(self):
        return slugify(self.title)

    @classmethod
    def find_by_title(cls, title):
        """
        Find client by user ID.

        :param user_id: user ID
        :type title: str
        :return: Client instance
        """
        return cls.query.filter(cls.title == title).first()

    def to_json(self):
        return {
            'id': self.id,
            'title': self.title,
            'author': self.author.user.first_last_name,
            'body': self.body,
            'summary': self.summary,
            'practiceArea': self.practice_area.area,
            'imgSrc': self.img_src,
            'thumbnailSrc': self.thumbnail_src,
            'created': self.created_on,
            'updated': self.updated_on,
            'views': self.view_count,
            'authorPhoto': self.author.user.photo,
            'slug': self.slug
        }
示例#4
0
class UserUserRole(db.Model, BaseModel):
    __tablename__ = 'users_user_roles'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    product_id = db.Column(db.Integer, db.ForeignKey('user_roles.id'))

    creation_date = db.Column(db.DateTime, default=datetime.utcnow)

    user = db.relationship(User,
                           lazy='subquery',
                           backref=db.backref("users_user_roles",
                                              cascade="all, delete-orphan",
                                              lazy=True))
    user_role = db.relationship(UserRole,
                                lazy='subquery',
                                backref=db.backref(
                                    "users_user_roles",
                                    cascade="all, delete-orphan",
                                    lazy=True))
示例#5
0
class UserRole(db.Model, BaseModel):
    """This model created for custom permission
        role_name: is the permissions' name.
                    It can be "owner" or screens' name ("order history") for which user has permission"""

    __tablename__ = 'user_roles'

    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    role_name = db.Column(db.String, unique=True, nullable=False)
    roles = db.relationship('User',
                            secondary='users_user_roles',
                            lazy='dynamic',
                            backref=db.backref('user_roles', lazy=True))

    def __repr__(self):
        return '<Role {0}>'.format(self.role_name)
示例#6
0
class StockMarket(db.Model, BaseModel):
    __tablename__ = 'stock_market'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), unique=True, nullable=False)
    web_address = db.Column(db.String(200), unique=True, nullable=True)
    currencies = db.relationship('Currency', secondary=market_currencies, lazy='subquery',
                                 backref=db.backref('stock_markets', lazy=True))

    leverage = db.Column(db.Integer, default=1)
    max_leverage = db.Column(db.Integer, default=leverage)
    balance_percentage = db.Column(db.Integer, default=0)

    transaction_fee = db.Column(db.Float, nullable=True, default=0.001)

    is_available = db.Column(db.Boolean, nullable=True, default=True)

    is_trading_active = db.Column(db.Boolean, default=False)
    is_terminate_all_required = db.Column(db.Boolean, default=False)

    def to_json(self, currencies=False):
        result = {
            "id": self.id,
            "name": self.name,
            "web_address": self.web_address,
            "leverage": self.leverage,
            "balance_percentage": self.balance_percentage
        }

        if currencies:
            result["currencies"] = [currency.to_json() for currency in self.currencies]

        return result

    def __repr__(self):
        return "<id: {}>, <name: {}>".format(self.id, self.name)

    @staticmethod
    def get_by_name(market_name):
        market = StockMarket.query.filter_by(name=market_name).first()
        if not market:
            raise NoMarketByNameException("No market by name: {}".format(market_name))
        return market
示例#7
0
class Picture(db.Model):
    """ Picture database
    """
    __table__name = 'picture'

    id = Column('Id', db.Integer, primary_key=True, autoincrement=True)
    data = Column('data', db.LargeBinary, nullable=False)

    author_id = Column(
        'AuthorID', db.String(STRING_LEN),
        db.ForeignKey('user.Id', ondelete='SET NULL', onupdate='CASCADE'))

    author = db.relationship("User",
                             backref=db.backref("pictures", lazy='dynamic'),
                             lazy=True)

    def __init__(self):
        pass

    def set_data(self, data, author_id):
        self.data = data
        self.author_id = author_id

    def add_picture(self):
        try:
            Picture.query.filter_by(id=self.id).one()
            return False
        except NoResultFound:
            try:
                db.session.add(self)
                db.session.commit()
                return True
            except IntegrityError:
                db.session.rollback()
                return False
            except Exception as e:
                db.session.rollback()
                raise e
class PracticeArea(ResourceMixin, db.Model):
    __tablename__ = 'practice_areas'

    # Relationships
    posts = db.relationship('Post', backref=db.backref('practice_area', lazy="joined"), lazy='dynamic')
    matters = db.relationship('Matter', backref='practice_areas', secondary=practice_area_matter)

    # Properties
    id = db.Column(db.Integer, primary_key=True)
    area = db.Column(db.String(128), nullable=False, unique=True, index=True)
    img_src = db.Column(db.String(200))
    thumbnail_src = db.Column(db.String(200))
    description = db.Column(db.ARRAY(db.String), nullable=False)
    slug = db.Column(db.String(128), nullable=False, unique=True, index=True)

    @classmethod
    def get_by_slug(cls, slug):
        return PracticeArea.query.filter(PracticeArea.slug == slug).first()
    
    def to_json_short(self):
        return {
            'id': self.id,
            'area': self.area
        }

    def to_json(self):
        return {
            'id': self.id,
            'area': self.area,
            'imgSrc': self.img_src,
            'thumbnailSrc': self.thumbnail_src,
            'posts': [post.id for post in self.posts],
            'matters': [matter.id for matter in self.matters],
            'staff': [staff_member.id for staff_member in self.staff],
            'description': self.description,
            'slug': self.slug
        }
class User(UserMixin, ResourceMixin, db.Model):
    ROLE = OrderedDict([('admin', 'Admin'), ('client', 'Client'),
                        ('staff', 'Staff'), ('public', 'Public')])

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

    # Relationships
    client = db.relationship(Client,
                             backref=db.backref('user', uselist=False),
                             uselist=False,
                             cascade="all, delete-orphan")
    staff = db.relationship(Staff,
                            backref=db.backref('user', uselist=False),
                            uselist=False,
                            cascade="all, delete-orphan")
    comments = db.relationship(Comment,
                               backref=db.backref('author', uselist=False),
                               lazy='dynamic')
    appointments = db.relationship(Appointment, backref='user', lazy='dynamic')

    # Properties.
    role = db.Column(db.Enum(*ROLE, name='role_types', native_enum=False),
                     index=True,
                     nullable=False,
                     server_default='public')
    active = db.Column('is_active',
                       db.Boolean(),
                       nullable=False,
                       server_default='1')
    username = db.Column(db.String(24),
                         unique=True,
                         index=True,
                         nullable=False)
    email = db.Column(db.String(255),
                      unique=True,
                      index=True,
                      nullable=False,
                      server_default='')
    password = db.Column(db.String(128), nullable=False, server_default='')
    first_name = db.Column(db.String(256), nullable=False)
    middle_name = db.Column(db.String(256))
    last_name = db.Column(db.String(256), index=True, nullable=False)
    unit_number = db.Column(db.String(128))
    street_address = db.Column(db.String(128))
    suburb = db.Column(db.String(128))
    postcode = db.Column(db.String(4))
    state = db.Column(db.String(128))
    country = db.Column(db.String(128))
    phone_number = db.Column(db.String(128), nullable=False)
    photo = db.Column(db.String(256))

    # Activity tracking.
    sign_in_count = db.Column(db.Integer, nullable=False, default=0)
    current_sign_in_on = db.Column(AwareDateTime())
    current_sign_in_ip = db.Column(db.String(45))
    last_sign_in_on = db.Column(AwareDateTime())
    last_sign_in_ip = db.Column(db.String(45))

    # Additional settings.
    locale = db.Column(db.String(5), nullable=False, server_default='en')

    def __init__(self, **kwargs):
        # Call Flask-SQLAlchemy's constructor.
        super(User, self).__init__(**kwargs)

        self.password = User.encrypt_password(kwargs.get('password', ''))

    @hybrid_property
    def full_name(self):
        if self.middle_name:
            return self.last_name.upper(
            ) + ', ' + self.first_name + ' ' + self.middle_name
        else:
            return self.last_name.upper() + ', ' + self.first_name

    @hybrid_property
    def first_last_name(self):
        return self.first_name + ' ' + self.last_name

    @hybrid_property
    def full_address(self):
        street_address = self.unit_number + "/" + self.street_address if self.unit_number and self.street_address else self.street_address
        address_elements = [
            street_address, self.suburb, self.postcode, self.state,
            self.country
        ]
        return ", ".join(
            address_elements) if None not in address_elements else None

    @classmethod
    def find_by_identity(cls, identity):
        """
        Find user by 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 encrypt_password(cls, plaintext_password):
        """
        Hash password using Bcrypt.

        :param plaintext_password: Password in plain text
        :type plaintext_password: str
        :return: str
        """
        if plaintext_password:
            return hashpw(plaintext_password, gensalt())

        return None

    @classmethod
    def deserialize_token(cls, token):
        """
        Obtain user from de-serializing token.

        :param token: Signed token.
        :type token: str
        :return: User instance or None
        """
        private_key = TimedJSONWebSignatureSerializer(
            current_app.config['SECRET_KEY'])
        try:
            decoded_payload = private_key.loads(token)

            return User.find_by_identity(decoded_payload.get('user_email'))
        except Exception:
            return None

    @classmethod
    def initialize_password_reset(cls, identity):
        """
        Generate token to reset the password for a specific user.

        :param identity: User e-mail address or username
        :type identity: str
        :return: User instance
        """
        u = User.find_by_identity(identity)
        reset_token = u.serialize_token()

        # This prevents circular imports.
        from server.blueprints.user.tasks import (deliver_password_reset_email)
        deliver_password_reset_email.delay(u.id, reset_token)

        return u

    @classmethod
    def search(cls, query):
        """
        Search using ILIKE (case-insensitive) expression.

        :param query: Search query
        :type query: str
        :return: SQLAlchemy filter
        """
        if not query:
            return ''

        search_query = '%{0}%'.format(query)
        search_chain = (User.email.ilike(search_query),
                        User.username.ilike(search_query))

        return or_(*search_chain)

    @classmethod
    def is_last_admin(cls, user, new_role, new_active):
        """
        Return whether user is last admin account.

        :param user: User being tested
        :type user: User
        :param new_role: New role being set
        :type new_role: str
        :param new_active: New active status being set
        :type new_active: bool
        :return: bool
        """
        is_changing_roles = user.role == 'admin' and new_role != 'admin'
        is_changing_active = user.active is True and new_active is None

        if is_changing_roles or is_changing_active:
            admin_count = User.query.filter(User.role == 'admin').count()
            active_count = User.query.filter(User.is_active is True).count()

            if admin_count == 1 or active_count == 1:
                return True

        return False

    def is_active(self):
        """
        Return whether user account is active (overrides Flask-Login default).

        :return: bool
        """
        return self.active

    def get_auth_token(self):
        """
        Return user's auth token.

        :return: str
        """
        private_key = current_app.config['SECRET_KEY']

        serializer = URLSafeTimedSerializer(private_key)
        data = [str(self.id), md5(self.password.encode('utf-8')).hexdigest()]

        return serializer.dumps(data)

    def authenticated(self, with_password=True, password=''):
        """
        Ensure user authenticated.

        :param with_password: Optionally check password
        :type with_password: bool
        :param password: Password to verify
        :type password: str
        :return: bool
        """
        if with_password:
            return checkpw(password.encode('utf-8'),
                           self.password.encode('utf-8'))

        return True

    def serialize_token(self, expiration=3600):
        """
        Serialize token for resetting passwords, etc.

        :param expiration: Seconds until it expires, defaults to 1 hour
        :type expiration: int
        :return: JSON
        """
        private_key = current_app.config['SECRET_KEY']

        serializer = TimedJSONWebSignatureSerializer(private_key, expiration)
        return serializer.dumps({'user_email': self.email}).decode('utf-8')

    def update_activity_tracking(self, ip_address):
        """
        Update user's meta data.

        :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 = datetime.datetime.now(pytz.utc)
        self.current_sign_in_ip = ip_address

        return self.save()

    def to_json(self):
        active = "Active" if self.active == True else "Disabled"
        json_data = {
            'id': self.id,
            'created': self.created_on,
            'updated': self.updated_on,
            'active': active,
            'firstLastName': self.first_last_name,
            'firstName': self.first_name,
            'middleName': self.middle_name,
            'lastName': self.last_name.upper(),
            'fullName': self.full_name,
            'username': self.username,
            'email': self.email,
            'phoneNumber': self.phone_number,
            'unitNumber': self.unit_number,
            'streetAddress': self.street_address,
            'suburb': self.suburb,
            'postcode': self.postcode,
            'state': self.state,
            'country': self.country,
            'fullAddress': self.full_address,
            'role': self.role,
            'photo': self.photo,
        }

        return json_data
class Staff(ResourceMixin, db.Model):
    __tablename__ = 'staff'

    # Relationships
    posts_authored = db.relationship(Post,
                                     backref=db.backref('author',
                                                        lazy="joined"),
                                     lazy='dynamic')
    matters_handled = db.relationship(Matter,
                                      backref='staff',
                                      secondary=staff_matter)
    appointments = db.relationship(Appointment,
                                   backref='staff',
                                   secondary=staff_appointment)
    practice_areas = db.relationship(PracticeArea,
                                     backref='staff',
                                     secondary=staff_practice_area)

    id = db.Column(db.Integer, primary_key=True)
    dated_joined = db.Column(AwareDateTime(), default=tzaware_datetime)
    position = db.Column(db.String(128))
    description = db.Column(db.ARRAY(db.String))

    # Foreign Keys
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.id'),
                        index=True,
                        unique=True,
                        nullable=False)

    @classmethod
    def find_by_user_id(cls, user_id):
        """
        Find staff by user ID.

        :param user_id: user ID
        :type title: str
        :return: Staff instance
        """
        return cls.query.filter(cls.user_id == user_id).first()

    def to_json(self):
        matters_handled = [matter.id for matter in self.matters_handled]
        posts_authored = [post.id for post in self.posts_authored]
        practice_areas = [
            practice_area.id for practice_area in self.practice_areas
        ]

        return {
            'id': self.id,
            'name': self.user.first_last_name,
            'dateJoined': self.dated_joined,
            'position': self.position,
            'photo': self.user.photo,
            'posts': self.posts_authored.count(),
            'description': self.description,
            'userId': self.user_id,
            'mattersHandled': matters_handled,
            'postsAuthored': posts_authored,
            'practiceAreas': practice_areas
        }