Esempio n. 1
0
class TrustedReview(db.Model):
    __tablename__ = 'trusted_reviews'

    id = db.Column(db.Integer, primary_key=True)
    reviewer_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    app_id = db.Column(db.Integer, db.ForeignKey('trusted_applications.id'), nullable=False)
    created_time = db.Column(db.DateTime(timezone=False), default=datetime.utcnow)
    comment = db.Column(db.String(length=4000), nullable=False)
    recommendation = db.Column(ChoiceType(TrustedRecommendation, impl=db.Integer()),
                               nullable=False)
    reviewer = db.relationship('User', uselist=False, lazy='joined', foreign_keys=[reviewer_id])
    application = db.relationship('TrustedApplication', uselist=False, lazy='joined',
                                  foreign_keys=[app_id])
Esempio n. 2
0
class Ban(db.Model):
    __tablename__ = 'bans'

    id = db.Column(db.Integer, primary_key=True)
    created_time = db.Column(db.DateTime(timezone=False),
                             default=datetime.utcnow)
    admin_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=True)
    user_ip = db.Column(db.Binary(length=16), nullable=True)
    reason = db.Column(db.String(length=2048), nullable=False)

    admin = db.relationship('User',
                            uselist=False,
                            lazy='joined',
                            foreign_keys=[admin_id])
    user = db.relationship('User',
                           uselist=False,
                           lazy='joined',
                           foreign_keys=[user_id])

    __table_args__ = (
        Index('user_ip_4', 'user_ip', mysql_length=4, unique=True),
        Index('user_ip_16', 'user_ip', mysql_length=16, unique=True),
    )

    def __repr__(self):
        return '<Ban %r>' % self.id

    @property
    def ip_string(self):
        if self.user_ip:
            return str(ip_address(self.user_ip))

    @classmethod
    def all_bans(cls):
        return cls.query

    @classmethod
    def by_id(cls, id):
        return cls.query.get(id)

    @classmethod
    def banned(cls, user_id, user_ip):
        if user_id:
            if user_ip:
                return cls.query.filter((cls.user_id == user_id)
                                        | (cls.user_ip == user_ip))
            return cls.query.filter(cls.user_id == user_id)
        if user_ip:
            return cls.query.filter(cls.user_ip == user_ip)
        return None
Esempio n. 3
0
class TrustedApplication(db.Model):
    __tablename__ = 'trusted_applications'

    id = db.Column(db.Integer, primary_key=True)
    submitter_id = db.Column(db.Integer,
                             db.ForeignKey('users.id'),
                             nullable=False,
                             index=True)
    created_time = db.Column(db.DateTime(timezone=False),
                             default=datetime.utcnow)
    closed_time = db.Column(db.DateTime(timezone=False))
    why_want = db.Column(db.String(length=4000), nullable=False)
    why_give = db.Column(db.String(length=4000), nullable=False)
    status = db.Column(ChoiceType(TrustedApplicationStatus, impl=db.Integer()),
                       nullable=False,
                       default=TrustedApplicationStatus.NEW)
    reviews = db.relationship('TrustedReview', backref='trusted_applications')
    submitter = db.relationship('User',
                                uselist=False,
                                lazy='joined',
                                foreign_keys=[submitter_id])

    @hybrid_property
    def is_closed(self):
        # We can't use the attribute names from TrustedApplicationStatus in an or here because of
        # SQLAlchemy jank. It'll generate the wrong query.
        return self.status > 1

    @hybrid_property
    def is_new(self):
        return self.status == TrustedApplicationStatus.NEW

    @hybrid_property
    def is_reviewed(self):
        return self.status == TrustedApplicationStatus.REVIEWED

    @hybrid_property
    def is_rejected(self):
        return self.status == TrustedApplicationStatus.REJECTED

    @property
    def created_utc_timestamp(self):
        ''' Returns a UTC POSIX timestamp, as seconds '''
        return (self.created_time - UTC_EPOCH).total_seconds()

    @classmethod
    def by_id(cls, id):
        return cls.query.get(id)
Esempio n. 4
0
 def trackers(cls):
     return db.relationship(
         cls._flavor_prefix('TorrentTrackers'),
         uselist=True,
         cascade="all, delete-orphan",
         lazy='select',
         order_by=cls._flavor_prefix('TorrentTrackers.order'))
Esempio n. 5
0
 def sub_category(cls):
     join_sql = (
         "and_({0}SubCategory.id == foreign({0}Torrent.sub_category_id), "
         "{0}SubCategory.main_category_id == {0}Torrent.main_category_id)")
     return db.relationship(cls._flavor_prefix('SubCategory'),
                            uselist=False,
                            backref='torrents',
                            lazy="joined",
                            primaryjoin=join_sql.format(cls.__flavor__))
Esempio n. 6
0
class UserPreferences(db.Model):
    __tablename__ = 'user_preferences'

    user_id = db.Column(db.Integer, db.ForeignKey('users.id', ondelete='CASCADE'), primary_key=True)

    def __init__(self, user_id):
        self.user_id = user_id

    def __repr__(self):
        return '<UserPreferences %r>' % self.user_id

    user = db.relationship('User', back_populates='preferences')
    hide_comments = db.Column(db.Boolean, nullable=False, default=False)
Esempio n. 7
0
 def torrent(cls):
     return db.relationship(cls._flavor_prefix('Torrent'),
                            uselist=False,
                            lazy="joined")
Esempio n. 8
0
 def torrent(cls):
     return db.relationship(cls._flavor_prefix('Torrent'),
                            uselist=False,
                            back_populates='stats')
Esempio n. 9
0
class User(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(length=32, collation=COL_ASCII_GENERAL_CI),
                         unique=True,
                         nullable=False)
    email = db.Column(EmailType(length=255, collation=COL_ASCII_GENERAL_CI),
                      unique=True,
                      nullable=True)
    password_hash = db.Column(PasswordType(max_length=255, schemes=['argon2']),
                              nullable=False)
    status = db.Column(ChoiceType(UserStatusType, impl=db.Integer()),
                       nullable=False)
    level = db.Column(ChoiceType(UserLevelType, impl=db.Integer()),
                      nullable=False)

    created_time = db.Column(db.DateTime(timezone=False),
                             default=datetime.utcnow)
    last_login_date = db.Column(db.DateTime(timezone=False),
                                default=None,
                                nullable=True)
    last_login_ip = db.Column(db.Binary(length=16),
                              default=None,
                              nullable=True)
    registration_ip = db.Column(db.Binary(length=16),
                                default=None,
                                nullable=True)

    nyaa_torrents = db.relationship('NyaaTorrent',
                                    back_populates='user',
                                    lazy='dynamic')
    nyaa_comments = db.relationship('NyaaComment',
                                    back_populates='user',
                                    lazy='dynamic')

    sukebei_torrents = db.relationship('SukebeiTorrent',
                                       back_populates='user',
                                       lazy='dynamic')
    sukebei_comments = db.relationship('SukebeiComment',
                                       back_populates='user',
                                       lazy='dynamic')

    bans = db.relationship('Ban', uselist=True, foreign_keys='Ban.user_id')

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password_hash = password
        self.status = UserStatusType.INACTIVE
        self.level = UserLevelType.REGULAR

    def __repr__(self):
        return '<User %r>' % self.username

    def validate_authorization(self, password):
        ''' Returns a boolean for whether the user can be logged in '''
        checks = [
            # Password must match
            password == self.password_hash,
            # Reject inactive and banned users
            self.status == UserStatusType.ACTIVE
        ]
        return all(checks)

    def gravatar_url(self):
        if 'DEFAULT_GRAVATAR_URL' in app.config:
            default_url = app.config['DEFAULT_GRAVATAR_URL']
        else:
            default_url = flask.url_for('static',
                                        filename='img/avatar/default.png',
                                        _external=True)
        if app.config['ENABLE_GRAVATAR']:
            # from http://en.gravatar.com/site/implement/images/python/
            params = {
                # Image size (https://en.gravatar.com/site/implement/images/#size)
                's': 120,
                # Default image (https://en.gravatar.com/site/implement/images/#default-image)
                'd': default_url,
                # Image rating (https://en.gravatar.com/site/implement/images/#rating)
                # Nyaa: PG-rated, Sukebei: X-rated
                'r': 'pg' if app.config['SITE_FLAVOR'] == 'nyaa' else 'x',
            }
            # construct the url
            return 'https://www.gravatar.com/avatar/{}?{}'.format(
                md5(self.email.encode('utf-8').lower()).hexdigest(),
                urlencode(params))
        else:
            return default_url

    @property
    def userlevel_str(self):
        level = ''
        if self.level == UserLevelType.REGULAR:
            level = 'User'
        elif self.level == UserLevelType.TRUSTED:
            level = 'Trusted'
        elif self.level == UserLevelType.MODERATOR:
            level = 'Moderator'
        elif self.level >= UserLevelType.SUPERADMIN:
            level = 'Administrator'
        if self.is_banned:
            level = 'BANNED ' + level
        return level

    @property
    def userstatus_str(self):
        if self.status == UserStatusType.INACTIVE:
            return 'Inactive'
        elif self.status == UserStatusType.ACTIVE:
            return 'Active'
        elif self.status == UserStatusType.BANNED:
            return 'Banned'

    @property
    def userlevel_color(self):
        color = ''
        if self.level == UserLevelType.REGULAR:
            color = 'default'
        elif self.level == UserLevelType.TRUSTED:
            color = 'success'
        elif self.level >= UserLevelType.MODERATOR:
            color = 'purple'
        if self.is_banned:
            color += ' strike'
        return color

    @property
    def ip_string(self):
        if self.last_login_ip:
            return str(ip_address(self.last_login_ip))

    @property
    def reg_ip_string(self):
        if self.registration_ip:
            return str(ip_address(self.registration_ip))

    @classmethod
    def by_id(cls, id):
        return cls.query.get(id)

    @classmethod
    def by_username(cls, username):
        def isascii(s):
            return len(s) == len(s.encode())

        if not isascii(username):
            return None

        user = cls.query.filter_by(username=username).first()
        return user

    @classmethod
    def by_email(cls, email):
        user = cls.query.filter_by(email=email).first()
        return user

    @classmethod
    def by_username_or_email(cls, username_or_email):
        return cls.by_username(username_or_email) or cls.by_email(
            username_or_email)

    @property
    def is_moderator(self):
        return self.level >= UserLevelType.MODERATOR

    @property
    def is_superadmin(self):
        return self.level == UserLevelType.SUPERADMIN

    @property
    def is_trusted(self):
        return self.level >= UserLevelType.TRUSTED

    @property
    def is_banned(self):
        return self.status == UserStatusType.BANNED

    @property
    def is_active(self):
        return self.status != UserStatusType.INACTIVE

    @property
    def age(self):
        '''Account age in seconds'''
        return (datetime.utcnow() - self.created_time).total_seconds()

    @property
    def created_utc_timestamp(self):
        ''' Returns a UTC POSIX timestamp, as seconds '''
        return (self.created_time - UTC_EPOCH).total_seconds()
Esempio n. 10
0
 def user(cls):
     return db.relationship('User', uselist=False, lazy="joined")
Esempio n. 11
0
 def user(cls):
     return db.relationship('User',
                            uselist=False,
                            back_populates=cls._table_prefix('comments'),
                            lazy="joined")
Esempio n. 12
0
 def torrent(cls):
     return db.relationship(cls._flavor_prefix('Torrent'),
                            uselist=False,
                            back_populates='comments',
                            lazy="joined")
Esempio n. 13
0
 def torrents(cls):
     return db.relationship(cls._flavor_prefix('Torrent'),
                            back_populates='main_category')
Esempio n. 14
0
 def main_category(cls):
     return db.relationship(cls._flavor_prefix('MainCategory'),
                            uselist=False,
                            back_populates='sub_categories')
Esempio n. 15
0
 def tracker(cls):
     return db.relationship('Trackers', uselist=False, lazy='joined')
Esempio n. 16
0
 def sub_categories(cls):
     return db.relationship(cls._flavor_prefix('SubCategory'),
                            back_populates='main_category')
Esempio n. 17
0
 def user(cls):
     return db.relationship('User',
                            uselist=False,
                            back_populates=cls._table_prefix('torrents'))
Esempio n. 18
0
 def comments(cls):
     return db.relationship(cls._flavor_prefix('Comment'),
                            uselist=True,
                            cascade="all, delete-orphan")
Esempio n. 19
0
 def main_category(cls):
     return db.relationship(cls._flavor_prefix('MainCategory'),
                            uselist=False,
                            back_populates='torrents',
                            lazy="joined")
Esempio n. 20
0
 def stats(cls):
     return db.relationship(cls._flavor_prefix('Statistic'),
                            uselist=False,
                            cascade="all, delete-orphan",
                            back_populates='torrent',
                            lazy='joined')
Esempio n. 21
0
 def filelist(cls):
     return db.relationship(cls._flavor_prefix('TorrentFilelist'),
                            uselist=False,
                            cascade="all, delete-orphan",
                            back_populates='torrent')