Пример #1
0
class Answer(db.Model):
    """Contain the user's answers to the secret questions they've chosen."""

    id = db.Column(db.Integer(), primary_key=True)
    answer = db.Column(db.String(256), nullable=False)
    user_id = db.Column(db.Integer(),
                        db.ForeignKey('user.id', ondelete='CASCADE'),
                        nullable=False)
    question_id = db.Column(db.Integer(),
                            db.ForeignKey('question.id', ondelete='CASCADE'),
                            nullable=False)
Пример #2
0
class FailedAttempt(db.Model):
    """Represent a failed password reset attempt."""

    id = db.Column(db.Integer(), primary_key=True)
    user_id = db.Column(db.Integer(),
                        db.ForeignKey('user.id', ondelete='CASCADE'),
                        nullable=False)
    time = db.Column(db.DateTime, nullable=False)
Пример #3
0
class BlacklistedToken(db.Model):
    """Contain issued JSON web tokens."""

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(
        db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'), nullable=False)
    jti = db.Column(db.String(36), nullable=False)
    expires = db.Column(db.DateTime, nullable=False)

    @staticmethod
    def add_token(token):
        """
        Add a new token to the database in the unrevoked state.

        :param dict token: the decoded token to blacklist
        """
        user = User.query.filter_by(ad_guid=token['sub']).one()
        db_token = BlacklistedToken(
            jti=token['jti'],
            user_id=user.id,
            expires=datetime.fromtimestamp(token['exp'])
        )
        db.session.add(db_token)
        db.session.commit()

    @staticmethod
    def is_token_revoked(token):
        """
        Check if the token is revoked and default to True if the token is not present.

        :param dict token: the decoded JSON web token to check
        :rtype: bool
        :return: a boolean representing if the token is revoked
        """
        jti = token['jti']
        return bool(BlacklistedToken.query.filter_by(jti=jti).first())

    @staticmethod
    def revoke_token(jti):
        """
        Revoke a token for the given user.

        :param str jti: the GUID that identifies the token
        :raises werkzeug.exceptions.NotFound: if the specified token does not exist in the database
        """
        return bool(BlacklistedToken.query.filter_by(jti=jti).first())
Пример #4
0
class Answer(db.Model):
    """Contain the user's answers to the secret questions they've chosen."""

    id = db.Column(db.Integer(), primary_key=True)
    # The hashed answer should be around 120 characters, but give it plenty of room to expand in
    # the event the hashing algorithm is updated
    answer = db.Column(db.String(256), nullable=False)
    user_id = db.Column(db.Integer(),
                        db.ForeignKey('user.id', ondelete='CASCADE'),
                        nullable=False)
    question_id = db.Column(db.Integer(),
                            db.ForeignKey('question.id', ondelete='CASCADE'),
                            nullable=False)

    @validates('answer')
    def validate_answer(self, key, answer):
        """
        Ensure the answer is hashed.

        :param str key: the key/column being validated
        :param str answer: the answer being validated
        :return: the answer being validated
        :rtype: str
        :raises RuntimeError: if the answer is not hashed or isn't a string
        """
        if not isinstance(answer, string_types):
            raise RuntimeError(_must_be_str.format(key))
        elif not passlib.hash.sha512_crypt.identify(answer):
            raise RuntimeError('The answer must be stored as a SHA512 hash')
        return answer

    @staticmethod
    def hash_answer(answer):
        """
        Hash the answer using the SHA512 algorithm.

        :param str answer: the answer to hash
        :return: a SHA512 hash of the string
        :rtype: str
        """
        return passlib.hash.sha512_crypt.hash(answer)

    @staticmethod
    def verify_answer(input_answer, hashed_answer):
        """
        Verify the input answer and the hashed answer stored in the database are the same.

        :param str input_answer: the answer to verify
        :param str hashed_answer: the hashed answer to verify against
        :return: a boolean determining if the answers match
        :rtype: bool
        """
        return passlib.hash.sha512_crypt.verify(input_answer, hashed_answer)

    def to_json(self, include_url=True):
        """Represent the row as a dictionary for JSON output."""
        rv = {
            'id': self.id,
            'user_id': self.user_id,
            'question': self.question.to_json(),
        }
        if include_url:
            rv['url'] = url_for('api_v1.get_answer',
                                answer_id=self.id,
                                _external=True)
        return rv