0
votes

In my flask app, I want to redirect users that are already logged in to the members area when they open the login page. I am using flask-login extension.

Now the issue is that anonymous users can open the member page without having to log in even though it has the login-required decorator. When I checked the terminal I get this error on a members page opened by anonymous user:

Error on request:
Traceback (most recent call last):
  File "/home/maxwell/py/aqua/lib/python2.7/site-packages/werkzeug/serving.py", line 209, in run_wsgi
    execute(self.server.app)
  File "/home/maxwell/py/aqua/lib/python2.7/site-packages/werkzeug/serving.py", line 200, in execute
    write(data)
  File "/home/maxwell/py/aqua/lib/python2.7/site-packages/werkzeug/serving.py", line 168, in write
    self.send_header(key, value)
  File "/usr/lib/python2.7/BaseHTTPServer.py", line 412, in send_header
    self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe

This is my Flask code. I am pasting only the bits that I think are necessary:

import os

from flask import Flask, render_template, redirect, flash, request, url_for
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
from flask_bcrypt import Bcrypt
from flask_debugtoolbar import DebugToolbarExtension
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.exc import IntegrityError
from forms import LoginForm, RegisterForm
from flask_bootstrap import Bootstrap
from datetime import timedelta


##############
### config ###
##############

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)

from models import User, PValue, History, Anonymous

##############
# extensions #
##############

login_manager = LoginManager()
login_manager.init_app(app)
bcrypt = Bcrypt(app)
toolbar = DebugToolbarExtension(app)
bootstrap = Bootstrap(app)

##################
####flask-login###
##################

login_manager.login_view = "login"
login_manager.login_message_category = 'danger'
login_manager.anonymous_user = Anonymous

@login_manager.user_loader
def load_user(user_id):
    return User.query.filter(User.id == user_id).first()

@app.route('/', methods = ['GET','POST'])
def login():
    if current_user.is_authenticated():
        return redirect(url_for('dashboard'))
    form = LoginForm(request.form)
    if request.method == 'POST':
        print("First If")
        if form.validate_on_submit():
            print("Second If")
            user1 = User.query.filter_by(username = form.username.data).first()
            if user1 and bcrypt.check_password_hash(user1.password, request.form['password']):
                login_user(user1)
                flash('You are logged in. Welcome!','success')
                return redirect(url_for('dashboard'))
            else:
                flash('Invalid username and/or password.','danger')
                return render_template('login.html', title = "Please Login", form = form)
    else:
        return render_template('login.html', form=form)

I am using current_user.is_authenticated() to check if the user is logged in.

Now I set the login view as 'login' so by default when an anonymous user enters a route with a login-required decorator it is supposed to go to the login route but that does not happen.

And this is my models.py containing the AnonymousUserMixin object with necessary return values for an Anonymous user:

from views import db
import datetime
from flask_login import UserMixin, AnonymousUserMixin

class User(db.Model, UserMixin):

    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, nullable = False)
    password = db.Column(db.String, nullable = False)

    def __init__(self, username = None, password = None):
        self.username = username
        self.password = password

    def is_authenticated(self):
        return True

    def is_active(self):
        return True

    def is_anonymous(self):
        return False

    def get_id(self):
        return self.id

class Anonymous(AnonymousUserMixin):
    def __init__(self):

        print "Exec"

    def is_authenticated(self):
        return False

    def is_active(self):
        return False

    def is_anonymous(self):
        return True

    def get_id(self):
        return None

I am not able to figure out why this broken pipe error keeps occurring. Is it something to do with the installed library or is there a mistake in my code?

1

1 Answers

0
votes

I solved it by removing all the other methods from my Anonymous class. Now my anonymous class has only a username assigned Guest.

class Anonymous(AnonymousUserMixin):
    def __init__(self):
        self.username = 'Guest'

Then to check if the user is logged in I just put

if current_user is not 'Guest':
        return redirect(url_for('dashboard'))

But I still don't know why the earlier is_authenticated method did not work.