Esempio n. 1
0
class ReportBase(DeclarativeHelperBase):
    __tablename_base__ = 'reports'

    id = db.Column(db.Integer, primary_key=True)
    created_time = db.Column(db.DateTime(timezone=False),
                             default=datetime.utcnow)
    reason = db.Column(db.String(length=255), nullable=False)
    status = db.Column(ChoiceType(ReportStatus, impl=db.Integer()),
                       nullable=False)

    @declarative.declared_attr
    def torrent_id(cls):
        return db.Column(db.Integer,
                         db.ForeignKey(cls._table_prefix('torrents.id'),
                                       ondelete='CASCADE'),
                         nullable=False)

    @declarative.declared_attr
    def user_id(cls):
        return db.Column(db.Integer, db.ForeignKey('users.id'))

    @declarative.declared_attr
    def user(cls):
        return db.relationship('User', uselist=False, lazy="joined")

    @declarative.declared_attr
    def torrent(cls):
        return db.relationship(cls._flavor_prefix('Torrent'),
                               uselist=False,
                               lazy="joined")

    def __init__(self, torrent_id, user_id, reason):
        self.torrent_id = torrent_id
        self.user_id = user_id
        self.reason = reason
        self.status = ReportStatus.IN_REVIEW

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

    @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)

    @classmethod
    def not_reviewed(cls, page):
        reports = cls.query.filter_by(status=0).paginate(page=page,
                                                         per_page=20)
        return reports

    @classmethod
    def remove_reviewed(cls, id):
        return cls.query.filter(cls.torrent_id == id, cls.status == 0).delete()
Esempio n. 2
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. 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
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()