title: Using flask-login with flask-admin
body: <p><a href="https://i.stack.imgur.com/fbdxZ.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/fbdxZ.png" alt="enter image description here"></a></p>
  
  <p>I'm looking at an open source app <a href="https://github.com/AlvinCJin/deepfit-app/tree/master/app" rel="nofollow noreferrer">https://github.com/AlvinCJin/deepfit-app/tree/master/app</a></p>
  
  <p>This is using flask-admin for admin purposes/ On the page <a href="https://github.com/AlvinCJin/deepfit-app/blob/master/app/main/views.py" rel="nofollow noreferrer">https://github.com/AlvinCJin/deepfit-app/blob/master/app/main/views.py</a>:</p>
  
  <pre><code># admin management setup
  admin.add_view(ModelView(User, db.session))
  admin.add_view(ModelView(Post, db.session))
  path = op.join(os.path.abspath(__file__ + "/../../"), 'static')  # need to get parent path of this code
  admin.add_view(FileAdmin(path, '/static/', name='Static Files'))
  </code></pre>
  
  <p>This works fine as far as producing a helpful dashboard but is unsecured. I have flask-login installed and I read the section <a href="http://flask-admin.readthedocs.io/en/latest/introduction/#rolling-your-own" rel="nofollow noreferrer">http://flask-admin.readthedocs.io/en/latest/introduction/#rolling-your-own</a> , but it is unclear to me how to link the class discussed:</p>
  
  <pre><code>class MicroBlogModelView(sqla.ModelView):
  
  def is_accessible(self):
      return login.current_user.is_authenticated
  
  def inaccessible_callback(self, name, **kwargs):
      # redirect to login page if user doesn't have access
      return redirect(url_for('login', next=request.url))
  </code></pre>
  
  <p>with the admin route.</p>
  
  <p>The user table is defined in models.py as:</p>
  
  <pre><code>class User(UserMixin, db.Model):
      __tablename__ = 'users'
      id = db.Column(db.Integer, primary_key=True)
      nickname = db.Column(db.String(64), unique=True)
      firstname = db.Column(db.String(100))
      lastname = db.Column(db.String(100))
      email = db.Column(db.String(120), index=True, unique=True)
      pwdhash = db.Column(db.String(54))
      phone = db.Column(db.Integer)
      address = db.Column(db.String(64))
      confirmed = db.Column(db.Boolean, default=False)
  
      role = db.Column(db.SmallInteger, default=ROLE_APPLICANT)
      comments = db.relationship('Comment', backref='author', lazy='dynamic')
      posts = db.relationship('Post', order_by="Post.timestamp", backref='author',
                              lazy='dynamic', cascade="all, delete, delete-orphan")
      about_me = db.Column(db.Text())
      last_seen = db.Column(db.DateTime, default=datetime.utcnow)
      member_since = db.Column(db.DateTime(), default=datetime.utcnow)
      portrait = db.Column(db.String(140))
      pref = db.relationship('Preference', uselist=False, backref='author')
      fav = db.relationship('Favourite', backref='user', lazy='dynamic')
  
      active = db.Column(db.Boolean, default=False)
  
      @staticmethod
      def make_unique_nickname(nickname):
          if User.query.filter_by(nickname=nickname).first() is None:
              return nickname
          version = 2
          while True:
              new_nickname = nickname + str(version)
              if User.query.filter_by(nickname=new_nickname).first() is None:
                  break
              version += 1
          return new_nickname
  
      def __init__(self, nickname, firstname, lastname, email, password, role):
          self.nickname = nickname.title()
          self.firstname = firstname.title()
          self.lastname = lastname.title()
          self.email = email.lower()
          self.set_password(password)
          self.role = role
  
      def ping(self):
          self.last_seen = datetime.utcnow()
          db.session.add(self)
  
      def set_password(self, password):
          self.pwdhash = generate_password_hash(password)
  
      def check_password(self, password):
          return check_password_hash(self.pwdhash, password)
  
      def is_authenticated(self):
          return True
  
      def generate_confirmation_token(self, expiration=3600):
          s = Serializer(current_app.config['SECRET_KEY'], expiration)
          return s.dumps({'confirm': self.id})
  
      def confirm(self, token):
          s = Serializer(current_app.config['SECRET_KEY'])
          try:
              data = s.loads(token)
          except:
              return False
          if data.get('confirm') != self.id:
              return False
          self.confirmed = True
          db.confirmed = True
          db.session.add(self)
          return True
  
      def to_json(self):
          json_user = {
              'url': url_for('api.get_post', id=self.id, _external=True),
              'nickname': self.nickname,
              'member_since': self.member_since,
              'last_seen': self.last_seen,
              'posts': url_for('api.get_user_posts', id=self.id, _external=True),
              'post_count': self.posts.count(),
          }
          return json_user
  
      def generate_reset_token(self, expiration=3600):
          s = Serializer(current_app.config['SECRET_KEY'], expiration)
          return s.dumps({'reset': self.id})
  
      def generate_auth_token(self, expiration):
          s = Serializer(current_app.config['SECRET_KEY'], expiration)
          return s.dumps({'id': self.id})
  
      @staticmethod
      def verify_auth_token(token):
          s = Serializer(current_app.config['SECRET_KEY'])
          try:
              data = s.loads(token)
          except:
              return None
          return User.query.get(data['id'])
  
      def is_active(self):
          if self.active is True:
              return True
          else:
              return False
  
      def is_anonymous(self):
          return False
  
      def get_id(self):
          return unicode(self.id)
  
      def __repr__(self):
          return '&lt;User %r&gt;' % self.nickname
  </code></pre>
  
  <p>And has a is_authenticated method, but how do I use this to require login of as specific user?</p>
  
  <p>I have tried :</p>
  
  <pre><code>class MyView(BaseView):
      @expose('/')
      def index(self):
          return self.render('admin/index.html')
  
      def is_accessible(self):
          return login.current_user.is_authenticated()
  
  # admin management setup
  admin.add_view(ModelView(User, db.session))
  admin.add_view(ModelView(Post, db.session))
  path = op.join(os.path.abspath(__file__ + "/../../"), 'static')  # need to get parent path of this code
  admin.add_view(FileAdmin(path, '/static/', name='Static Files'))
  </code></pre>
  
  <p>Based on:</p>
  
  <p><a href="https://flask-admin.readthedocs.io/en/v1.0.7/quickstart/" rel="nofollow noreferrer">https://flask-admin.readthedocs.io/en/v1.0.7/quickstart/</a></p>
  
  <p>EDIT:</p>
  
  <p>So just for my understanding you are subclassing the ModelViews and adding the ability to have routes?</p>
  
  <p>I've changed it to:</p>
  
  <pre><code>class MyView(ModelView):
      @expose('/')
      def index(self):
          return self.render('admin/index.html')
  
      def is_accessible(self):
          return login.current_user.is_authenticated()
  
  # admin management setup
  admin.add_view(MyView(User, db.session))
  admin.add_view(MyView(Post, db.session))
  path = op.join(os.path.abspath(__file__ + "/../../"), 'static')  # need to get parent path of this code
  admin.add_view(FileAdmin(path, '/static/', name='Static Files'))
  </code></pre>
  
  <p>That is getting closer but I need to integrate this with flask login - I'm getting:</p>
  
  <pre><code>NameError: global name 'login' is not defined
  </code></pre>
  
  <p>EDIT2:</p>
  
  <p>I've changed it to:</p>
  
  <pre><code>class MyView(ModelView):
      @expose('/')
      @login_required
      def index(self):
          return self.render('admin/index.html')
  </code></pre>
  
  <p>removing the is_accessible function, so its not overridden, The user class already has a built in is_accessible function.</p>
  
  <p>This is at least partially working, but I would like to only allow access to admins that have a ROLE in user defined as 0</p>