Flask User Session - python

After authenticating a user, I am having trouble keeping a user logged in as they move through the website I have built. I have tried using cookies and sessions but I can't seem to get it to work.
I am sharing my code for login where I grab data to authenticate a user from an excel sheet that is populated at Sign Up
I locate the names of each team member to have them appear on the Team Page, which is where the user is redirected to after login
#app.route('/login',methods=['POST','GET'])
def login():
# get data from form
try:
username = str(request.form['username2'])
password2 = str(request.form['password2'])
teamname = str(request.form['teamname'])
print(username)
print(password2)
# read excel sheet
data = pd.read_excel("C:\\Users\\290002925\\Documents\\registration.xlsx")
for name in data['Team']:
if name == teamname:
team_info = data.loc[data['Team'] == teamname]
print(team_info)
team_info['FullName'] = team_info['FirstName'] + [' '] + team_info['LastName']
teamroster = team_info[['FullName']].copy()
finalteamroster = pd.DataFrame(teamroster, index=range(5))
print(finalteamroster)
print(len(finalteamroster))
finalteamroster.fillna(value='', inplace=True)
print(finalteamroster)
amember1 = finalteamroster.at[0,'FullName']
print(amember1)
amember2 = finalteamroster.at[1,'FullName']
print(amember2)
amember3 = finalteamroster.at[2,'FullName']
print(amember3)
amember4 = finalteamroster.at[3,'FullName']
print(amember4)
amember5 = finalteamroster.at[4,'FullName']
print(amember5)
This is where the authentication of the user comes in
for user in data['Email']:
#check username
if user == username:
passw = data.loc[data['Email'] == username]
# check password
print(passw)
test2 = passw.iat[0,3]
This is how I wrote out cookies but I think Session might be more useful
if test2 == password2:
# authenticated
print("User is authenticated")
response = render_template('teampage.html', teamname=teamname, member1=amember1, member2=amember2, member3=amember3, member4=amember4, member5=amember5)
response.set_cookie('userID', username)
return response
else:
print("Password is incorrect")
return render_template('login.html')
else:
print("Username is incorrect")
return render_template('index.html')
except:
print("fail")
return render_template('login.html')
Code for Teampage
#app.route('/teampage')
def teampage():
userid = request.cookies.get('userID')
return render_template('teampage.html', userid=userid)
HTML user reference
{{userid}}

It is a bit hard to understand your initial code but what I understand is that you need to maintain a User session-
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html', title=': Login')
if request.method == 'POST':
if YourMethodToCheckPassword==True:
session['username'] = request.form['user']
return redirect(url_for('home'))
And then use the Session object everywhere like-
#app.route('/home')
def home():
if 'username' in session:
return render_template("index.html", name=session['username'])
Inside your HTML use
{{ name }}

Related

JSON Token won't load the value after being verified

Once I get to the verify_token function it keeps executing the except statement instead of returning the value in 'id_user' and I'm not sure why. I am using these libraries. flask-login, sqlalchemy, itsdangerous for jsonwebserializer, and wtforms.
Functions
def get_reset_token(user):
serial = Serializer(app.config['SECRET_KEY'], expires_in=900) # 15 mins in seconds
return serial.dumps({'id_user':user.id}).decode('utf-8')
def verify_token(token):
serial = Serializer(app.config['SECRET_KEY'])
try:
user_id = serial.load(token)['id_user']
except:
return None
return Users.query.get('id_user')
def send_mail(user):
token = get_reset_token(user)
message = Message('Password Reset Request', recipients = [user.email], sender='noreply#gmail.com')
message.body= f'''
To Reset your password, click the following link:
{url_for('reset_token', token = token, _external = True)}
If you did not send this email, please ignore this message.
'''
mail.send(message)
ROUTES
#app.route('/password_reset', methods = ['GET', 'POST'])
def password_reset():
form = Password_request()
if request.method == "POST":
if form.validate_on_submit:
user = Users.query.filter_by(email = form.email.data).first()
send_mail(user)
flash('Check your email. Password change request has been sent')
return redirect(url_for('login'))
else:
flash('Your email was not linked to an account')
return render_template('password_reset.html', form = form)
#app.route('/password_reset/<token>', methods = ['GET', 'POST'])
def reset_token(token):
user = verify_token(token)
if user == None:
flash('The token is invalid or expired')
return redirect(url_for('password_reset'))
form = Password_success()
if form.validate_on_submit:
hashed_password=generate_password_hash(form.password.data, method = 'sha256')
user.password = hashed_password
db.session.commit()
flash('Your password has been updated!')
return redirect(url_for('signup'))
def verify_token(token):
serial = Serializer(app.config['SECRET_KEY'])
try:
user_id = serial.load(token)['id_user']
except:
return None
return Users.query.get('id_user') # this looks wrong
Shouldn't the last line of verify_token be return Users.query.get(user_id)? You're assigning the value of the token to that variable , then ignoring it and telling SQLAlchemy to find a record with the ID of the string value 'id_user' which I doubt is what you're intending to do.
def verify_token(token):
serial = Serializer(app.config['SECRET_KEY'])
try:
user_id = serial.load(token)['id_user']
except:
return None
return Users.query.get(user_id) # What happens when you change this?

Change user's boolean when signing out on Flask

Every time a new user is connected to the server I got a list of the users that refresh to show them in my page. I'm using a boolean for that, every time a user is connecting their boolean changes to True and my list is looking for users with the boolean True only. I'm trying now to change the boolean back to False when they sign out. How can I do this?
#app.route("/sign-in", methods=["GET", "POST"])
def signin():
form = forms.SignInForm()
if flask.request.method == "POST":
if form.validate_on_submit():
username = form.username.data
password = form.password.data
# Retrieve the user that matches this username
user = models.User.query.filter_by(name=username).first()
print(user.boolean)
# Check the provided password against the user's one
if user is not None and user.password == password:
flask_login.login_user(user)
flask.flash(f"{user.name} logged in successfully !", "success")
idn = user.id
user.boolean = True
db.session.commit()
print(user.boolean)
return flask.render_template('user_page.html', user=user)
else:
flask.flash("Something went wrong.", "danger") # Put the message into the flashed messages
# To retrieve those messages: flask.get_flashed_messages()
return flask.render_template("signin.html", form=form)
#app.route("/sign-out", methods=["GET"])
def signout():
flask_login.logout_user()
return flask.redirect('/sign-in')
Put it in the signout route:
#app.route("/sign-out", methods=["GET"])
def signout():
user = models.User.query.filter_by(id=current_user.id).first()
user.boolean = False
db.session.commit()
flask_login.logout_user()
return flask.redirect('/sign-in')

TypeError: render_template() takes 1 positional argument but 2 were given in (Flask Framework)

kindly help it out folks! I am new to programming. I am trying to Authenticate Login. But its showing "TypeError....." i couldn't figure out.
See Below This is My code (main.py)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
email = request.form.get('EMAIL')
con1 = sqlite3.connect("check10.db")
cur = con1.cursor()
data = cur.execute("SELECT EMAIL FROM register WHERE EMAIL = ? ", (email,))
if data == email:
return render_template('homepage.html')
else:
alert = "Check Credentials "
return render_template('loginpage.html', alert)
return render_template("loginpage.html")
Try this:
from flask import request, render_template, flash
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
email = request.values.get('EMAIL')
con1 = sqlite3.connect("check10.db")
cur = con1.cursor()
data = cur.execute("SELECT EMAIL FROM register WHERE EMAIL = ? ", (email,))
if data == email:
return render_template('homepage.html')
else:
flash('Check Credentials ')
return render_template('loginpage.html')
return render_template("loginpage.html")
Try also to change the variable email like:
email = request.args.get('EMAIL')
You are getting error because of return render_template('loginpage.html', alert).
If you want to send some data from server to HTML page then you can refer to link.
If you want flash message 'check credentials' to the user then refer to this Link

How to stop Pyrebase set() from overriding existing data?

I am creating a simple directory with Flask & Pyrebase; I have managed to create the login ok, and the registration form. The user is redirected to their profile page once signed in & registered.
My issue that I have is when I try to add a new entry my existing data is overwritten. When I create a new db entry I use set() instead of push() I am thinking this could be why?
I have shortened the code us much as possible
creating account & registering business:
#app.route('/register', methods=['GET', 'POST'])
def register():
unsuccessful = 'Please check your credentials'
successful = 'Registraion successful'
if request.method == 'POST':
email = request.form.get('email')
confirmEmail = request.form('confirmEmail')
password = request.form.get('pass')
userName = request.form.get('inputName')
businessName = request.form.get('businessName')
startYear = request.form.get('startYear')
selectCategory = request.form.get('selectCategory')
businessDescription = request.form.get('businessDescription')
businessAddress = request.form.get('businessAddress')
businessTown = request.form.get('businessTown')
businessCity = request.form.get('businessCity')
businessPostcode = request.form.get('businessPostcode')
businessNumber = request.form.get('businessNumber')
businessEmail = request.form.get('businessEmail')
bameRegister = dict(
userName = userName,
confirmationEmail = confirmEmail,
businessName = businessName,
businessStartYear = startYear,
businessCategory = selectCategory,
businessDescription = businessDescription,
businessAddress = [businessAddress, businessTown, businessCity, businessPostcode],
businessNumber = businessNumber,
businessEmail = businessEmail,
)
if selectCategory == "arts":
try:
user = auth.create_user_with_email_and_password(email, password)
auth.send_email_verification(user['idToken'])
db.child("Bame_Buisness").child("business").child("arts").set(bameRegister, user['idToken'])
return render_template('homepage.html', x=successful)
except:
return render_template('homepage.html', y=unsuccessful)
elif selectCategory == "food":
try:
user = auth.create_user_with_email_and_password(email, password)
auth.send_email_verification(user['idToken'])
db.child("Bame_Business").child("business").child("food").set(bameRegister, user['idToken'])
return render_template('homepage.html', x=successful)
except:
return render_template('homepage.html', y=unsuccessful)
elif selectCategory == "health":
try:
user = auth.create_user_with_email_and_password(email, password)
auth.send_email_verification(user['idToken'])
db.child("Bame_Business").child("business").child("health").set(bameRegister, user['idToken'])
return render_template('homepage.html', x=successful)
except:
return render_template('homepage.html', y=unsuccessful)
return render_template('homepage.html')
Creating the login:
#app.route('/login', methods=['GET', 'POST'])
def login():
unsuccessful = 'Please check your credentials'
if request.method == 'POST':
try:
user = auth.sign_in_with_email_and_password(email, password)
signed_in_user = auth.get_account_info(user['idToken'])
artCategory = db.child("Bame_Business").child("business").child("arts").get(user['idToken']).val()
foodCategory = db.child("Bame_Business").child("business").child("food").get(user['idToken']).val()
healthCategory = db.child("Bame_Business").child("business").child("health").get(user['idToken']).val()
if signed_in_user['users'][0]['email'] == artCategory['confirmationEmail']:
return render_template('profile.html', artCategory=artCategory)
elif signed_in_user['users'][0]['email'] == foodCategory['confirmationEmail']:
return render_template('profile.html', foodCategory=foodCategory)
elif signed_in_user['users'][0]['email'] == healthCategory['confirmationEmail']:
return render_template('profile.html', healthCategory=heathCategory)
except:
return render_template('homepage.html')
return render_template('homepage.html')
This is the route to create a new business once logged in:
#app.route('newBusiness', methods=['GET', 'POST'])
def newBusiness():
if request.method == 'POST':
email = request.form.get('email')
confirmEmail = request.form.get('confirmEmail')
password = request.form.get('pass')
userName = request.form.get('userName')
businessName = request.form.get('businessName')
startYear = request.form.get('startYear')
selectCategory = request.form.get('selectCategory')
businessDescription = request.form.get('businessDescription')
businessAddress = request.form.get('businessAddress')
businessTown = request.form.get('businessTown')
businessCity = request.form.get('businessCity')
businessPostcode = request.get('businessPostcode')
businessNumber = request.form.get('businessNumber')
businessEmail = request.form.get('businessEmail')
bameRegister = dict(
userName = userName,
confirmationEmail = confirmEmail,
businessName = businessName,
businessStartYear = startYear,
businessCategory = businessCategory,
businessDescription = businessDescription,
businessAddress = [businessAddress, businessTown, businessCity, businessPostcode],
businessNumber = businessNumber,
businessEmail = businessEmail,
)
if selectCategory == "arts":
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
db.child("Bame_Business").child("business").child("arts").set(bameRegister, user['idToken'])
signed_in_user = auth.get_account_info(user['idToken'])
artCategory = db.child("Bame_Business").child("business").child("arts").get(user['idToken']).val()
if signed_in_user['users'][0]['email'] == artCategory['confirmationEmail']:
return render_template('profile.html', artCategory=artCategory)
except:
return render_template('homepage.html')
elif selectCategory == "food":
try:
user = auth.sign_in_with_email_and_password(email, password)
user = auth.refresh(user['refreshToken'])
db.child("Bame_Business").child("business").child("food").set(bameRegister, user['idToken'])
signed_in_user = auth.get_account_info(user['idToken'])
foodCategory = db.child("Bame_Business").child("business").child("food").get(user['idToken']).val()
if signed_in_user['users'][0]['email'] == foodCategory['confirmationEmail']:
return render_template('profile.html', foodCategory=foodCategory)
except:
return render_template('homepage.html')
elif selectCategory == "health":
try:
user = auth.sign_in_with_emal_and_password(email, password)
user = auth.refresh(user['refreshToken'])
db.child("Bame_Business").child("business").child("health").set(bameRegister, user['idToken'])
signed_in_user = auth.get_account_info(user['idToken'])
healthCategory = db.child("Bame_Business").child("business").child("health").get(user['idToken']).val()
if signed_in_user['users'][0]['email'] == healthCategory['confirmationEmail']:
return render_template('profile.html', healthCategory=healthCategory)
except:
return render_template('homepage.html')
return render_template('homepage.html')
After the user has logged in, lets say they register their 1st business in the arts category, when they register their 2nd different business in the arts category the original collection is overwritten in Firebase. This happens even when selecting a different category. This is definitely not ideal as someone could overwrite someone else's data - which then leads to all sorts of problems!
I understand you can use push & set to create new entries in pyrebase; I chose set because when I used push it creates a unique tag which I found it hard to get individual access from a users account. With the set method it is easy to call out the part of the dictionary I want with artCategory['businessName'] or artCategory['businessDescription'] or artCategory['confirmationEmail'] etc
I just need to create a new business registration after login in without overriding any existing data, if anyone could help me come up with a solution that would be much appreciated.
Kind regards
.set() overrides. .update() updates only the fields that have changed.

How to return a JSON request input and use it in another function?

I'm trying to set up an API login of sorts that when the login is successful, it returns an JWT and first/last name sent with the login from the POST request. My problem is that I cant figure out a way that works to return the first/last name variables to another Class and function. This my code:
#app.route('/login', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
username = request.json.get('username', None)
password = request.json.get('password', None)
client_fname = request.json.get('Client First Name', None)
client_lname = request.json.get('Client Last Name', None)
if not username:
return jsonify({"msg": "Missing username parameter"}), 400
if not password:
return jsonify({"msg": "Missing password parameter"}), 400
if username != USER_DATA.get(username) and password not in USER_DATA[username]:
return jsonify({"msg": "Bad username or password"}), 401
access_token = create_access_token(identity=username)
return jsonify(access_token=access_token), 200, PrivateResource.sendData(self, client_fname, client_lname)
class PrivateResource(Resource):
#app.route('/protected', methods=['GET'])
#jwt_required
def sendData(self, client_fname, client_lname):
return mysqldb.addUser("{}".format(client_fname),"{}".format(client_lname))
I want to return client_fname and client_lname so I can then use them with sendData(). How can I achieve this without have issues with unicode from json or passing the variables?
I think what you need is a Session then you can do something like this-
#app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST']
session['username'] = request.form['user']
return redirect(url_for('home'))
And in route for home use-
#app.route('/home')
def home():
if 'username' in session:
return render_template("index.html", name=session['username'])
Hope this helps
You could use session to store the variables you need to access across functions. Add these to login,
session['client_fname'] = request.json.get('Client First Name', None)
session['client_lname'] = request.json.get('Client Last Name', None)
And access it from sendData as:
return mysqldb.addUser("{}".format(session['client_fname']),"{}".format(session['client_lname']))
Hope this answers your question.

Categories

Resources