I have been messing around and creating a user-authentication system. I tackled a bunch of bugs (thanks to Stackoverflow), however, I have run in to a bug that I cannot identify. When I login and it redirects me to my profile page, it brings me back to my login. Which is certainly expected if I try and access the page without proper credentials, however, I do.
I set a print(current_user.is_authenticated) to see what the value is and it always is False. I cannot figure it out. Any help would be appreciated.
from flask import Flask, render_template, redirect, url_for, Blueprint, request, flash
from flask_login import LoginManager
import os
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, EmailField
from wtforms.validators import DataRequired, Email
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixin, LoginManager, login_user, login_required, current_user
import pymongo
app = Flask(__name__)
app.config['SECRET_KEY'] = '12345'
myclient = pymongo.MongoClient("thegoodstuff")
mydb = myclient["dbb"]
mycol = mydb["db"]
login_manager = LoginManager()
login_manager.login_view = 'homepage'
login_manager.init_app(app)
class User(UserMixin):
def __init__(self, user_json):
self.user_json = user_json
#Overriding get_id is required if you don't have the id property
# Check the source code for UserMixin for details
def get_id(self):
object_id = self.user_json.get('_id')
return str(object_id)
def is_authenticated(self):
return self.authenticated
@login_manager.user_loader
def load_user(user_id):
u = mycol.find_one({"_id": user_id})
if not u:
return None
return User(u)
class LoginForm(FlaskForm):
username = StringField('Username',validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
submit = SubmitField('Login')
class SignUp(FlaskForm):
username = StringField('Username',validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
email = EmailField('Email', validators=[DataRequired(), Email()])
submit = SubmitField('Register')
@app.route("/")
def homepage():
form = LoginForm()
return render_template('index.html', form=form)
@app.route("/login", methods=['POST'])
def login_post():
username = request.form.get('username')
password = request.form.get('password')
user = mycol.find_one({"username": username})
if not user or not check_password_hash(user['password'], password):
flash('Please check your login details and try again.')
return redirect(url_for('homepage'))
loginuser = User(user)
login_user(loginuser, remember=True)
return redirect(url_for('profile'))
@app.route("/register")
def register():
form = SignUp()
return render_template('register.html', form=form)
@app.route("/register", methods=["POST"])
def register_post():
email = request.form.get('email')
username = request.form.get('username')
password = request.form.get('password')
user = mycol.find_one({"email": email})
if user:
flash('Email address already exists. Please login below.')
return redirect(url_for('homepage'))
mycol.insert_one({"username": username, "email": email, "password": generate_password_hash(password, method='sha256')})
return redirect(url_for('homepage'))
@app.route("/profile")
@login_required
def profile():
return render_template('profile.html')
CodePudding user response:
So it looks like my issue was related to my user_loader
.
My database query was always returning None as no record was found. This is because MongoDB defines the _id
as an object ID, and not a str
, I assume.
I imported ObjectId
from bson.objectid
and modified my user_loader
to:
@login_manager.user_loader
def load_user(user_id):
u = mycol.find_one({"_id": ObjectId(user_id)})
if not u:
return None
return User(u)
This solved my issue.