Пример #1
0
    def get(self):
        # Get optional page number
        try:
            filter_params = {
                'per_page':
                request.args.get('per_page', default=10, type=int),
                'page':
                request.args.get('page', default=1, type=int),
                'from':
                request.args.get('from', default=None, type=toDate),
                'to':
                request.args.get('to', default=None, type=toDate),
                'sort':
                request.args.get('sort',
                                 default=OrderType.DESCENDING,
                                 type=OrderType),
                'query':
                request.args.get('query', default='', type=str)
            }
        except ValueError:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details={'page': 'Page should be number'},
                              error='validation errors'))
            log.info(f'Invalid page query argument: {error_response}')
            return error_response, 400

        # Find all articles on that page
        articles = Article.find_all_articles(filter_params)

        # Map articles to schema
        return self.paginated_articles_schema.dump(articles), 200
Пример #2
0
class NotificationResource(Resource):
    error_schema = ErrorResponseSchema()
    user_schema = UserSchema()
    notification_preferences_schema = NotificationPreferencesSchema()

    @api.expect(notification_preferences_model)
    @api.response(204, 'No Content')
    @jwt_required([RoleTypes.ADMIN, RoleTypes.CLIENT])
    def post(self):
        # Find user
        uuid = get_jwt_identity()
        user = User.find_by_uuid(uuid)
        if not user:
            error_response = self.error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # Deserialize input
        notification_preferences = self.notification_preferences_schema.load(
            api.payload)

        # update notification preferences
        for key, value in notification_preferences.items():
            setattr(user, key, value)
        user.commit()

        # return updated user
        return self.user_schema.dump(user), 200
Пример #3
0
    def get(self):

        # Get optional page number
        try:
            page = int(request.args.get('page'))
        except ValueError:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details={'page': 'Page should be number'},
                              error='validation errors'))
            log.info(f'Invalid page query argument: {error_response}')
            return error_response, 400

        # Find all users on that page
        users = User.find_all_users(page or 1, 20)

        # Map users to schema
        paginated_user_schema = PaginatedUserSchema()
        return paginated_user_schema.dump(users), 200
Пример #4
0
class LoginResource(Resource):
    login_schema = LoginSchema()
    error_schema = ErrorResponseSchema()
    token_schema = TokenSchema()

    @api.expect(login_model)
    @api.response(200, 'Success', login_response)
    def post(self):
        # Serialize login model
        try:
            login_dto = self.login_schema.load(api.payload)
        except ValidationError as err:
            error_response = self.error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(f'Validation errors during login: {error_response}')
            return error_response, 400

        # Find user in database
        user = User.find_by_email(login_dto.email)
        if not user:
            error_response = self.error_schema.dump(
                ErrorResponse(details={
                    'user': [f'There is no user with {login_dto.email} email']
                },
                              error='not existing user'))
            log.info(f'Trying to log in non existing user: {error_response}')
            return error_response, 404

        # Chcek if user is confirmed
        if not user.confirmed:
            error_response = self.error_schema.dump(
                ErrorResponse(
                    details={'user': [f'User {user.name} is unconfirmed']},
                    error='user not confirmed'))
            log.info(f'Trying to log in unconfirmed user: {error_response}')
            return error_response, 400

        # Check user password
        if not user.check_password(login_dto.password):
            error_response = self.error_schema.dump(
                ErrorResponse(
                    details={'password': ['You provided wrong password']},
                    error='wrong password'))
            log.info(f'Wrong password used during login: {error_response}')
            return error_response, 400

        # Create JWT from user data
        token = TokenDto(create_access_token(identity=user),
                         create_refresh_token(identity=user))

        # Return token
        log.info('User login sucessful')
        return self.token_schema.dump(token), 200
Пример #5
0
    def get(self, uuid):
        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If user is requesting details for another user
        user_claims = self.user_claims_schema.load(get_jwt_claims())
        if user_claims.is_client() and user.uuid != UUID(get_jwt_identity()):
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'Access to that resource is forbidden'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 403

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # Return user
        return self.user_schema.dump(user), 200
Пример #6
0
    def delete(self, uuid):
        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # delete user
        user.remove()

        return '', 204
Пример #7
0
    def get(self):
        # Get identity of user from refresh token
        current_user_uuid = get_jwt_identity()

        # Try to find user in db
        user = User.find_by_uuid(UUID(current_user_uuid))
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'user': ['There is no user with given email']},
                    error='not existing user'))
            log.warn(f'Non existing user {current_user_uuid}' +
                     f' trying to refresh token: {error_response}')
            return error_response, 404

        # Generate new access token with user
        token = TokenDto(create_access_token(identity=user))

        # Return only access token
        token_schema = TokenSchema(only=['access_token'])
        log.info(f'Access token refresh successful')
        return token_schema.dump(token), 200
Пример #8
0
class ConfirmationResource(Resource):
    error_schema = ErrorResponseSchema()

    def get(self, token):
        # Confirm token
        try:
            email = ConfirmationMailHandler.confirm_token(token)
        except InvalidConfirmationToken:
            error_response = self.error_schema.dump(
                ErrorResponse(
                    details={'token': f'{email} is invalid or expired'},
                    error='Invalid or expired token'))
            log.info(f'Invalid token: {error_response}')
            return error_response, 403

        # Find user that token belongs to
        user = User.find_by_email(email)
        if not user:
            error_response = self.error_schema.dump(
                ErrorResponse(
                    details={'user': [f'There is no user with {email} email']},
                    error='not existing user'))
            log.info(f'Trying to confirm non existing user: {error_response}')
            return error_response, 404

        # Check if user was already confirmed
        if user.confirmed:
            error_response = self.error_schema.dump(
                ErrorResponse(details={
                    'user': [f'User "{user.name}" is already confirmed']
                },
                              error='User already confirmed'))
            log.info(
                f'Trying to confirm already confirmed user: {error_response}')
            return error_response, 404

        # Confirm user
        user.confirm_account()
        user.commit()

        return '', 204
Пример #9
0
    def post(self):
        # Map request body to user model
        try:
            user = self.user_schema.load(api.payload)
        except ValidationError as err:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(
                f'Validation errors during user creation: {error_response}')
            return error_response, 400

        # Check if user with same email already exists
        if User.find_by_email(user.email) is not None:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details={
                    'user': ['User with provided email already exists']
                },
                              error='duplicate email'))
            log.info(f'trying to create user with existing email {user.email}')
            return error_response, 400

        # If caller was ADMIN create ADMIN if caller was CLIENT create CLIENT
        user_claims = self.user_claims_schema.load(get_jwt_claims())
        if user_claims.is_admin():
            user.add_to_role(RoleTypes.ADMIN)
        else:
            user.add_to_role(RoleTypes.CLIENT)

        # Send confirmation mail that user was created
        if app.config['REQUIRE_MAIL_CONFIRMATION']:
            send_confirmation_token(user.email)
        else:
            user.confirm_account()

        # Save model to DB
        user.commit()

        # Map saved user to response body
        log.info(f'Sucessfuly created new user')
        return self.user_schema.dump(user), 201
Пример #10
0
    def put(self, uuid):
        # Map input data
        try:
            user_update_schema = UpdateUserSchema()
            update_info = user_update_schema.load(api.payload)
        except ValidationError as err:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(f'Validation errors during user update: {error_response}')
            return error_response, 400

        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # update user properties
        for key, value in update_info.items():
            setattr(user, key, value)
        user.commit()

        # return updated user
        return self.user_schema.dump(user), 200
Пример #11
0
class ArticlesResource(Resource):
    article_schema = ArticleSchema()
    paginated_articles_schema = PaginatedArticleSchema()
    error_schema = ErrorResponseSchema()
    create_article_schema = CreateArticleSchema()
    error_schema = ErrorResponseSchema()

    # POST api/article - create new article
    @api.expect(create_article_model)
    @api.response(201, 'Created', article_model)
    @jwt_required([RoleTypes.ADMIN])
    def post(self):

        # Find user trying to save article
        user = User.find_by_uuid(get_jwt_identity())

        # Check if article is valid
        try:
            article = self.create_article_schema.load(request.form.to_dict())
        except ValidationError as err:
            error_response = self.error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(
                f'Validation errors during article creation: {error_response}')
            return error_response, 400

        # Try to save images to AWS
        saved_images = upload_request_files(request.files)
        article.images = saved_images

        # Add user to article
        article.user = user

        # Save article
        article.commit()

        # Send notification that there is new article
        users_to_notify = User.find_with_mail_notifications_enabled()
        send_notification_mail([user.email for user in users_to_notify],
                               article.title, article.uuid)

        # Return article model
        return self.article_schema.dump(article), 201

    # GET api/article - get all articles (filtered by query)
    def get(self):
        # Get optional page number
        try:
            filter_params = {
                'per_page':
                request.args.get('per_page', default=10, type=int),
                'page':
                request.args.get('page', default=1, type=int),
                'from':
                request.args.get('from', default=None, type=toDate),
                'to':
                request.args.get('to', default=None, type=toDate),
                'sort':
                request.args.get('sort',
                                 default=OrderType.DESCENDING,
                                 type=OrderType),
                'query':
                request.args.get('query', default='', type=str)
            }
        except ValueError:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details={'page': 'Page should be number'},
                              error='validation errors'))
            log.info(f'Invalid page query argument: {error_response}')
            return error_response, 400

        # Find all articles on that page
        articles = Article.find_all_articles(filter_params)

        # Map articles to schema
        return self.paginated_articles_schema.dump(articles), 200
Пример #12
0
class ArticleResource(Resource):
    error_schema = ErrorResponseSchema()
    article_schema = ArticleSchema()
    update_article_schema = UpdateArticleSchema()

    def incorrect_uuid(self, uuid):
        error_response = self.error_schema.dump(
            ErrorResponse(details={'uuid': f'Badly formed uuid: {uuid}'},
                          error='uuid format error'))
        log.info(f'uuid format error: {error_response}')
        return error_response

    # GET api/article/1 - get details for article
    def get(self, uuid):
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        article = Article.find_by_uuid(uuid)
        if not article:
            error_response = self.error_schema.dump(
                ErrorResponse(details={
                    'uuid':
                    f'Article with {uuid} uuid does not exist'
                },
                              error='Article not found'))
            log.info(f'Article not found: {error_response}')
            return error_response, 404

        return self.article_schema.dump(article), 200

    # PUT api/article/1 - update article
    @jwt_required([RoleTypes.ADMIN])
    def put(self, uuid):
        # Map input data
        try:
            update_info = self.update_article_schema.load(api.payload)
        except ValidationError as err:
            error_response = self.error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(
                f'Validation errors during article update: {error_response}')
            return error_response, 400

        # Try to find article
        article = Article.find_by_uuid(uuid)
        if not article:
            error_response = self.error_schema.dump(
                ErrorResponse(details={
                    'uuid':
                    f'Article with {uuid} uuid does not exist'
                },
                              error='Article not found'))
            log.info(f'Article not found: {error_response}')
            return error_response, 404

        # Update article
        for key, value in update_info.items():
            setattr(article, key, value)
        article.commit()

        return self.article_schema.dump(article), 200

    # DELETE api/article/1 - delete article
    @jwt_required([RoleTypes.ADMIN])
    def delete(self, uuid):
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        article = Article.find_by_uuid(uuid)
        if not article:
            error_response = self.error_schema.dump(
                ErrorResponse(details={
                    'uuid':
                    f'Article with {uuid} uuid does not exist'
                },
                              error='Article not found'))
            log.info(f'Article not found: {error_response}')
            return error_response, 404

        article.remove()

        return '', 204
        pass
Пример #13
0
class UserResourceList(Resource):
    error_schema = ErrorResponseSchema()
    user_claims_schema = UserClaimsSchema()
    user_schema = UserSchema()

    def incorrect_uuid(self, uuid):
        error_response = self.error_schema.dump(
            ErrorResponse(details={'uuid': f'Badly formed uuid: {uuid}'},
                          error='uuid format error'))
        log.info(f'uuid format error: {error_response}')
        return error_response

    # GET api/user/1 - get details for specific users
    @jwt_required([RoleTypes.ADMIN, RoleTypes.CLIENT])
    def get(self, uuid):
        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If user is requesting details for another user
        user_claims = self.user_claims_schema.load(get_jwt_claims())
        if user_claims.is_client() and user.uuid != UUID(get_jwt_identity()):
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'Access to that resource is forbidden'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 403

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # Return user
        return self.user_schema.dump(user), 200

    # DELETE api/user/1 - delete specific user
    @jwt_required([RoleTypes.ADMIN])
    def delete(self, uuid):
        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # delete user
        user.remove()

        return '', 204

    @jwt_required([RoleTypes.ADMIN])
    def put(self, uuid):
        # Map input data
        try:
            user_update_schema = UpdateUserSchema()
            update_info = user_update_schema.load(api.payload)
        except ValidationError as err:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(details=err.messages, error='validation errors'))
            log.info(f'Validation errors during user update: {error_response}')
            return error_response, 400

        # Try to find user
        try:
            uuid = UUID(uuid)
        except ValueError:
            return self.incorrect_uuid(uuid), 404

        user = User.find_by_uuid(uuid)

        # If there is no user with given id
        if not user:
            error_schema = ErrorResponseSchema()
            error_response = error_schema.dump(
                ErrorResponse(
                    details={'uuid': f'User with {uuid} uuid does not exist'},
                    error='User not found'))
            log.info(f'User not found: {error_response}')
            return error_response, 404

        # update user properties
        for key, value in update_info.items():
            setattr(user, key, value)
        user.commit()

        # return updated user
        return self.user_schema.dump(user), 200
Пример #14
0
from schemas.user.user_claims_schema import UserClaimsSchema
from flask_jwt_extended import JWTManager
from core.responses.error_response import ErrorResponse
from schemas.error.error_response_schema import ErrorResponseSchema
from dao.user.user import User

error_schema = ErrorResponseSchema()


def setup_jwt(app):
    jwt = JWTManager(app)

    @jwt.user_claims_loader
    def add_claims_to_jwt(user: User):
        schema = UserClaimsSchema()
        return schema.dump(user)

    @jwt.user_identity_loader
    def user_identity_lookup(user: User):
        return user.uuid

    @jwt.expired_token_loader
    def expired_token_callback():
        return error_schema.dump(
            ErrorResponse(details={'token': ['Token has expired']},
                          error='expired_token')), 401

    @jwt.invalid_token_loader
    def invalid_token_callback(error):
        return error_schema.dump(
            ErrorResponse(details={'token': ['Signature verification failed']},