pythonflaskjwtflask-securityflask-restx

How to use flask app context when using decorators


I'd like to use token authorization from Flask-Security-Too for this "Article" endpoint. However, the decorator function @auth_token_required("token") needs the context of the app. The app is initialized in a different file.

I've added app.app_context() but I don't know how to tell the decorator to use it's context.

Note: I'm working with Flask-RestX for providing a SwaggerUI (and OpenAPI spec). Also, I use Blueprints/Namespaces to modularize the API - which makes it a bit more complex.

from flask import Blueprint
from flask_restx import Api, Resource, fields, Namespace
from flask_security import auth_token_required

from .db import db_session
from .models import Article

from flask import current_app as app

article_blueprint = Blueprint('api', __name__, url_prefix='/api/article')
flask_api = Api(article_blueprint, version='0.1', title='Article Manager',
                description='Article management',)

article_manager = Namespace('article', description='Article Management Endpoint')

parser = article_manager.parser()
parser.add_argument('title', type=str, required=False,
                    help='Title of Article', location='json')
parser.add_argument('text', type=str, required=False,
                    help='Text of Article', location='json')
parser.add_argument('id', type=int, required=False,
                    help='ID of Article', location='json')

@article_manager.route('/<string:title>','/<int:id>')
class GetArticle(Resource):

    # FIXME app.app_context() ?!
    
    @auth_token_required("token")
    def get(self, title=None, id=None):
        # removed error handling for simplicity
        if title is not None:
            data = Article.query.filter(Article.title.ilike('%'+title+'%')).first()
        if id is not None:
            data = Article.query.filter_by(id=id).first()
        db_session.commit()

        return {'id': data.id, 'title': data.title, 'text': data.text}, 200
      

flask_api.add_namespace(article_manager)

Flask tells me:

Exception has occurred: RuntimeError
Working outside of application context.

Solution

  • The problem is in the way of using auth_token_required decorator. auth_token_required decorator unlike auth_required doesn't accept any additional arguments for configuration and expects the only decorated function to be transmitted.

    Your code can be fixed by applying of one of the following variants:

    
    @article_manager.route('/<string:title>', '/<int:id>')
    class GetArticle(Resource):
    
        @auth_token_required
        def get(self, title=None, id=None):
            pass
    

    or

    
    @article_manager.route('/<string:title>', '/<int:id>')
    class GetArticle(Resource):
    
        @auth_required("token")
        def get(self, title=None, id=None):
            pass