Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using flask-login with postgresql

I'm working on a flask app that needs authentication. I've hooked up flask-login but it doesn't seem very graceful.

First flask-login needs to make sure the user exists:

@login_manager.user_loader
def load_user(id):
    return User.query.get(id)

But you also need to use 'login_user' to create the user object

# Some code above 
  user = User.query.filter_by(email = form.email.data, password = form.password.data).first()
  user.login_status = 1
  db.session.commit()
  login_user(objects.SignedInUser(user.id, user.email, user.login_status == LoginStatus.Active))    
# Some code below

In the code above 'User' is a model for postgres and SignedInUser is just an object to be used for flask-login.

Does anyone have an example of flask-login used with postgres?

like image 967
Jay Avatar asked Feb 01 '12 12:02

Jay


1 Answers

It looks like you might be misunderstanding what Flask-Login handles. It's there to keep track of everything about the user's session after you tell it authentication was successful (by calling login_user.) The user_loader callback only tells it how to reload the object for a user that has already been authenticated, such as when someone reconnects to a "remember me" session. The docs are not especially clear on that.

There should be no need to keep a flag in the database for the user's login status. Also, the code you included will raise an AttributeError if the credentials are incorrect (user = None).

Here's an example from a Flask-SQLAlchemy application. It uses an external authentication source and a wrapper for the SQLAlchemy User object, but the process is basically the same.

user_loader callback:

@login_manager.user_loader
def load_user(user_id):
    user = User.query.get(user_id)
    if user:
        return DbUser(user)
    else:
        return None

User class (wrapper for SQLAlchemy object):

# User class
class DbUser(object):
    """Wraps User object for Flask-Login"""
    def __init__(self, user):
        self._user = user

    def get_id(self):
        return unicode(self._user.id)

    def is_active(self):
        return self._user.enabled

    def is_anonymous(self):
        return False

    def is_authenticated(self):
        return True

Login handler:

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    next = request.args.get('next')
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']


        if authenticate(app.config['AUTH_SERVER'], username, password):
            user = User.query.filter_by(username=username).first()
            if user:
                if login_user(DbUser(user)):
                    # do stuff
                    flash("You have logged in")

                    return redirect(next or url_for('index', error=error))
        error = "Login failed"
    return render_template('login.html', login=True, next=next, error=error)

Note that login fails if:

  • external auth fails
  • user query returns None (user does not exist)
  • login_user returns False (user.is_active() == False)

Logout

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('You have logged out')
    return(redirect(url_for('login')))
like image 117
robots.jpg Avatar answered Oct 20 '22 22:10

robots.jpg