Flask-Admin & Authentication: "/admin" is protected but "/admin/anything-else" is not
Asked Answered
A

1

9

I'm trying to customize my Admin views with Flask and Flask-SuperAdmin, however, the index view and subviews are apparently not using the same is_accessible method:

EDIT: I managed to figure out what I was doing wrong. I needed to define is_accessible in every view class. This is well-accomplished with a mixin-class, as show in the fixed code:

app/frontend/admin.py (FIXED & WORKING CODE)

from flask.ext.security import current_user, login_required
from flask.ext.superadmin import expose, AdminIndexView
from flask.ext.superadmin.model.base import ModelAdmin
from ..core import db

# all admin views should subclass AuthMixin
class AuthMixin(object):
    def is_accessible(self):
        if current_user.is_authenticated() and current_user.has_role('Admin'):
            return True
        return False

# the view that gets used for the admin home page
class AdminIndex(AuthMixin, AdminIndexView):
    # use a custom template for the admin home page
    @expose('/')
    def index(self):
        return self.render('admin/index.jade')

# base view for all other admin pages
class AdminBase(AuthMixin, ModelAdmin): # AuthMixin must come before ModelAdmin!
    """A base class for customizing admin views using our DB connection."""
    session = db.session

# customize the form displays for User and Role models

class UserAdmin(AdminBase):
    list_display = ('email',)
    search_fields = ('email',)
    exclude = ['password',]
    #fields_order = ['email', 'active', 'last_login_at',]

class RoleAdmin(AdminBase):
    field_args = {'name': {'label': 'Role Name'},
                'description': {'description': "Duties & Responsibilities"}}
    list_display = ('name', 'description')

Then set up the Flask app with our admin views:
apps/factory.py

app = Flask(package_name, instance_relative_config=True)
# other app setup stuff like db, mail, ...

from .frontend.admin import AdminIndex, UserAdmin, RoleAdmin
admin = Admin(app, name='PyCBM Admin',
              index_view=AdminIndex(url='/admin', name='Admin Home'))
admin.register(User, UserAdmin)
admin.register(Role, RoleAdmin)

So, like the title says, here's the problem:

/admin throws a 403 when an 'Admin' user isn't logged in, like it should, but
/admin/user lets anybody right on in.

I dug through the source code to try to find another "global all-of-admin-blueprint" security function - maybe I'm blind - but I couldn't find one.

Afton answered 11/7, 2013 at 0:40 Comment(2)
You should answer you own question to mark this as solvedSophronia
This isn't actually flask-admin, this is flask-superadminCodi
M
1

If you go to flask_superadmin/base.py, at line 193 there is the following code snippet:

def _handle_view(self, name, *args, **kwargs):
    if not self.is_accessible():
        return abort(403)

So maybe this method has to be overriden by AdminIndex to avoid returning abort(403) but to redirect to /login

Malvaceous answered 6/11, 2013 at 15:26 Comment(1)
@app.errorhandler(403) def page_forbiden(e): return redirect(url_for_security("login"))Lobachevsky

© 2022 - 2024 — McMap. All rights reserved.