I'm refactoring my app.py
for my flask application. I'm trying to get a user.py
class handle all user related things. How should I structure my user.py
class to return false if that user does not exist in my database?
app.py:
db = get_db_connection()
user = User(db, request.form.get("email"))
if not user.get_email(): # If user does not exist send user to registration page
return redirect("/register", email=request.form.get("email")) # go to the registration page and fill in the used e-mail address
# Check password and send to user_index if correct
password = request.form.get('password')
if user.check_password(password):
session['userID'] = user.get_id()
session['name'] = user.get_first_name()
session['email'] = user.get_email()
return redirect("/user_index")
return message("Wrong Password. Go to log in page to try again.")
user.py:
class User:
def __init__(self, database, email):
db = database
user = db.execute("SELECT * FROM users WHERE users.email = ?", [email]).fetchall()
if user:
self.__id = user['id']
self.__last_name = user['lastName']
self.__first_name = user['firstName']
self.__email = user['email']
self.__date_of_birth = user['dateOfBirth']
self.__hash = user['hash']
I understand that when I instantiate an object in python it should return none. How can I structure my code so that if a user with the given email does not exist I could get some type of false value? Once I get a false value I should be able to redirect the users to the registration page.
If I'm doing this completely wrong please point me in the right direction.
CodePudding user response:
There are many things to mention here:
- I recommend using an ORM like SQLAlchemy together with Flask. It will make your life a lot easier and you won't have to worry about some security issues (such as SQL Injection).
- If a user is going to log in, it is a good practice to return the message "wrong credentials" if their email OR password is incorrect, so an attacker will not know which one is correct or incorrect, therefore they will have many, many more combinations to try. That is, by just changing the phrase "wrong password" to "wrong credentials" you will be covering a security hole in your application. The same message should be returned if a user is not registered.
- I recommend reading up on the uses of underscore in Python, since you are apparently using it in a place where it isn't needed.
- In Python you don't need to use getters and setters unless you need to do some preprocessing before getting or setting an attribute.
Finally, in Flask this is a common way to structure a small project:
__init__.py
from flask import Flask
from utils import get_db_connection
app = Flask(__name__)
db = get_db_connection()
utils.py
# Do the necessary imports.
def get_db_connection():
...
run.py
from . import app
if __name__ == "__main__":
app.run() # You can set multiple settings in run().
routes.py
from . import app
from user import User
@app.route("/login", methods=["POST"])
def login():
user = User.get(request.form.get("email"))
# This is not recommended.
# if not user:
# return redirect("/register", email=request.form.get("email"))
password = request.form.get('password')
if user and user.check_password(password):
session['userID'] = user.id
session['name'] = user.first_name
session['email'] = user.email
return redirect("/user_index")
return message("Wrong credentials. Go to log in page to try again.")
models.py
from . import db
class User:
def __init__(self, id, last_name, first_name, email, date_of_birth, hash):
self.id = id
self.last_name = last_name
self.first_name = first_name
self.email = email
self.date_of_birth = date_of_birth
self.hash = hash
def check_password(self, password):
return check_password_hash(self.hash, password)
@staticmethod
def get(email):
user_result = db.execute("SELECT * FROM users WHERE users.email = ?", [email]).fetchall()
if user_result:
return User(user_result['id'], user_result['lastName'], user_result['firstName'],
user_result['email'], user_result['dateOfBirth'], user_result['hash'])
return None
# Declare more classes for your database models!
# class Admin:
#
# ...