Armag3ddon
Armag3ddon

Reputation: 1

How to use flask-admin authorization while also using the recommended flask Application Factory Function?

I am trying to follow the Flask Mega Tutorial while also trying to expand upon it.

I now have a working user login and have refactored my code just like chapter 15 suggests (see The Application Factory Pattern).

I am also trying to include flask-admin

flask-admin suggests to override the is_accessible method to check for admin users (Authorization & Permissions - Rolling Your Own)

This fails because the LoginManager is fully initialised.

My (relevant) code looks as follows:

__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
[...]

from flask_login import LoginManager
[...]

from flask_admin import Admin
from flask_admin.contrib.sqla import ModelView

db = SQLAlchemy()
login = LoginManager()
admin = Admin(name='Test', template_mode='bootstrap3')

def create_app():
    app = Flask(__name__)

    db.init_app(app)
    login.init_app(app)

    admin.init_app(app)
    admin.add_view(MyModelView(models.User, db.session))

from app import models

class MyModelView(ModelView):
    def is_accessible(self):
        return login.current_user.is_admin

project.py

from app import create_app, db

app = create_app()

I have also added the is_admin method to my User class. Now, in theory, when I access /admin of my project, it should check whether or not I am currently logged in with an admin user.

Instead, I receive the following error message:

AttributeError: 'LoginManager' object has no attribute 'current_user'

My understanding is that the LoginManager isn't fully initialised and therefore has no current_user attribute when I create my class MyModelView because it is only fully initialised when create_app() is called and the init_app() method runs. However, I don't know how to spawn the class MyModelView at runtime/delayed so that login is fully functional. I suspect that this wouldn't be the problem if I hadn't restructured the code to use the create_app() method but according to the tutorial, that is the superior way of running the app.

Upvotes: 0

Views: 128

Answers (0)

Related Questions