Issue
I am trying to use Flask-User (which incorporates Flask-Login). I would like to use the @login_required
and @roles_required
decorators to manage access to routes. However, it is not working.
The Flask-User documentation shows login_required
being imported from flask_user
, not flask_login
. When imported from flask_login
it works as expected, but if I switch it to be imported from flask_user
it does not work. Instead, it says that an authenticated user is not signed in.
Why don't I just import from flask_login
? Well, I could, but that does not solve my other problem which is that @roles_required
can only be imported from flask_user
, and that does not work either (same problem as above - says that authenticated users are not signed in).
My setup is below. I would be grateful if anyone could help me out, please. I have previously had Flask User working on another app, but can't figure out what's going wrong here. At the moment, the user database is stored in an SQLite database.
config.py
# Flask-User settings
USER_APP_NAME = "App name" # Shown in and email templates and page footers
USER_ENABLE_EMAIL = True # Enable email authentication
USER_ENABLE_USERNAME = False # Disable username authentication
USER_EMAIL_SENDER_NAME = USER_APP_NAME
USER_EMAIL_SENDER_EMAIL = "email"
USER_ENABLE_AUTH0 = True
USER_UNAUTHENTICATED_ENDPOINT = "login"
USER_UNAUTHORIZED_ENDPOINT = "login"
__init__.py
# Initialise flask_login
login = LoginManager(app)
login.login_view = 'login'
login.refresh_view = "login"
login.needs_refresh_message = "Please sign in again to access this page"
models.py
from andon import db, app, login
from flask_user import UserMixin, UserManager
from flask_login import current_user
@login.user_loader
def load_user(id):
return User.query.get(int(id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
# User Authentication fields
email = db.Column(db.String(255), nullable=False, unique=True)
email_confirmed_at = db.Column(db.DateTime())
password = db.Column(db.String(255), nullable=False)
# User fields
active = db.Column(db.Boolean())
first_name = db.Column(db.String(50), nullable=False)
last_name = db.Column(db.String(50), nullable=False)
registered = db.Column(db.DateTime, default=datetime.utcnow)
last_login = db.Column(db.DateTime)
client_id = db.Column(db.Integer, db.ForeignKey('client.id', ondelete='CASCADE'))
login_count = db.Column(db.Integer, default=0)
invitation_token = db.Column(db.String(50))
roles = db.relationship('Roles', secondary='user_roles')
def check_password(self, password):
# Check password against hash; return True or False
return bcrypt.checkpw(password.encode('utf8'), self.password)
# Define the Role data model
class Roles(db.Model):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(50), nullable=False, unique=True) # for @roles_accepted()
def __repr__(self):
return self.name
# Define the UserRoles association model
class UserRole(db.Model):
__tablename__ = 'user_roles'
id = db.Column(db.Integer(), primary_key=True)
user_id = db.Column(db.Integer(), db.ForeignKey('user.id', ondelete='CASCADE'))
role_id = db.Column(db.Integer(), db.ForeignKey('roles.id', ondelete='CASCADE'))
# Setup Flask-User
user_manager = UserManager(app, db, User)
main.py
from flask_login import current_user, login_user, logout_user
from flask_user import roles_required, login_required
@app.route('/test')
@login_required
def register_hub():
return "Test"
Solution
After hours of tearing out my remaining hairs, I have found the issue. I had set USER_ENABLE_EMAIL = True
, which I thought allowed flask-user
to allow sign ins via email (as opposed to a username). What it actually does is require users to be email verified.
Since my user account did not have a flag saying it had been email verified, it was throwing as not having any login permissions. Annoying that flask-user
does not throw a descriptive error in this circumstance, instead just saying that the user isn't signed in.
So, the fix: set USER_ENABLE_EMAIL = False
, unless you want to force email verification before users have access to @login_required
routes.
Answered By - Rob
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.