I am trying to register a user. I am having problem in preventing the user to register if the username typed already exists in the database.
#app.route("/register", methods=["GET", "POST"])
def register():
"""Register user"""
if request.method == "GET":
return render_template("register.html")
elif request.method == "POST":
# Ensure username was submitted
if not request.form.get("username"):
return apology("must provide username", 400)
# Ensure password was submitted
elif not request.form.get("password"):
return apology("must provide password", 400)
# Ensure password confirmation was submitted
elif not request.form.get("password-confirmation"):
return apology("must provide password confirmation", 400)
# Check if the password confirmation field matches the password field
elif request.form.get("password-confirmation") != request.form.get("password"):
return apology("Your passwords didn't match", 400)
# Query database for that username
row = db.execute("SELECT * FROM users WHERE username = ?", request.form.get("username"))
# Database
database = db.execute("SELECT * FROM users")
# Ensure username is not already in the database
if row in database:
return apology("username already exists", 400)
# Insert username and password into the database AND Hash user's password
insert = db.execute("INSERT INTO users (username,hash) VALUES(?,?)" , request.form.get("username"), generate_password_hash(request.form.get("password")))
# Remember which user has logged in
session["user_id"] = insert
# Redirect user to home page
return redirect("/")
Instead of getting "username already exists", I get "internal server error".
Can someone please specify why it might be the case.?
Your SELECT syntax is wrong. It should be rows = db.execute("SELECT * FROM users WHERE username = :username", username=request.form.get("username"))
This if row in database: will never be true.
row is a list, so it is trying to find a list in database. database is itself a list, but does not contain any lists, only dictionaries.
Program would know if username is already in users if row is not the empty list. Hint, Hint.
Related
I am pograming a simple web app with flask and am trying to implement a login process. My /register seems to work fine with username and hashed pwd being correctly inserted in my database when registering. However, when it comes to the login part I can't seem to be comparing the username stored in MySQL and the one from resquest.form.get, I get the following error message : TypeError: Object of type Cursor is not JSON serializable.
Here is my code:
#app.route('/login', methods=["GET", "POST"])
def login():
db = sqlite3.connect("users.db")
c = db.cursor()
if request.method== "POST":
username = request.form.get("username")
password = request.form.get("password")
pwd_hash = sha256(password.encode('utf-8')).hexdigest()
# Ensure username was submitted
if not request.form.get("username"):
flash("must provide username", "error")
return redirect("/login")
# Ensure password was submitted
elif not request.form.get("password"):
flash("must provide password", "error")
return redirect("/login")
# Query database for username
if (c.execute("SELECT COUNT(*) FROM users WHERE username=:username", {"username" : username}).fetchall()[0][0] == 0):
flash("invalid username", "error")
return redirect("/login")
if (c.execute("SELECT password FROM users WHERE(username=:username)", {"username": username}).fetchall()[0][0] != pwd_hash):
flash("invalid password", "error")
return redirect("/login")
# Remember which user has logged in
session["user_id"] = c.execute("SELECT username FROM users WHERE(:username=:username)", {"username": username})
# Redirect user to home page
return redirect("/")
# User reached route via GET (as by clicking a link or via redirect)
else:
return render_template("login.html")
Any idea ?
You didn't fetch the row here:
session["user_id"] = c.execute("SELECT username FROM users WHERE(:username=:username)", {"username": username})
c.execute() returns the cursor object, you can't put that into a session variable. It should be
session["user_id"] = c.execute("SELECT username FROM users WHERE(:username=:username)", {"username": username}).fetchone()[0]
But there doesn't seem to be a reason to do another query here. It's just going to return the same username that's in the parameter. So just write
sesion["user_id"] = username
BTW, it's generally considered poor security design to distinguish invalid usernames from invalid passwords. Just do a single query with both the username and password. If it fails, report "Invalid username or password".
if (c.execute("SELECT COUNT(*) FROM users WHERE username=:username AND password=:password", {"username" : username, "password": pwd_hash}).fetchone()[0] == 0):
flash("invalid username or password", "error")
return redirect("/login")
Other issues:
You're assigning variables from the request.form parameters before you check that they were actually filled in.
If you only need one row, use fetchone() instead of fetchall()[0].
I can't get past the Register section of CS50 Finance without an Internal Service Error. The issue arises from an Invalid Syntax error when I go to insert a new user's username and password hash into the users table.
if request.method == "POST":
# return error messages if any field is left blank
if not request.form.get("username"):
return apology("Must provide username", 403)
elif not request.form.get("password"):
return apology("Must provide password", 403)
elif not request.form.get("confirmation"):
return apology("Must provide password confirmation", 403)
# make sure the username does not already exist and that the passwords match
rows = db.execute("SELECT * FROM users WHERE username = :username",
username = request.form.get("username"))
if len(rows) > 0:
return apology("Sorry, this username already taken.", 403)
# make sure password and password confirmation match
elif request.form.get("password") != request.form.get("confirmation"):
return apology("Passwords do not match.", 403)
# declare username and hash variables to clean up SQL code
username = request.form.get("username")
hash = generate_password_hash(request.form.get("password"))
# insert new user's username and password hash into users table
db.execute=("INSERT INTO users (username, hash) VALUES (:username, :hash)",
username=username,
hash=hash)
else:
return render_template("register.html")
The syntax error is in the db.execute block:
File "/home/ubuntu/pset8/finance/application.py", line 143
username=username,
^
SyntaxError: invalid syntax
I have tried changing the name of username, putting the variable assignment in the actual db.execute block instead of above, and even different SQL code, but nothing has worked.
I believe this is the only place I have an error in my code because when I comment out the db.execute block, the Finance site loads fine and I get the correct error messages.
Any suggestions? Thanks!
I'm a beginner programmer and am tinkering with a login system with flask and SQLite3. The user inputs information from an HTML form and that form gets put into my database table named logins. The input works great and inputs data into the database, however when I try to select the data from the database, I am able to print a specific value with this:
rows = c.execute("SELECT password FROM logins")
Where password is is a column in the database. That part works fine. However, when I try to put a single cell into a python variable, for example like into userCheck below, my if logic doesn't work in comparing the two values. If both username userCheck and password passCheck are the same, it still won't be True.
#app.route("/login", methods=["GET","POST"])
def login():
if request.method == "GET":
return render_template("login.html")
else:
username = request.form.get("username")
password = request.form.get("password")
userCheck = c.execute("SELECT password FROM logins WHERE username = (?)", (username,))
passCheck = c.execute("SELECT username FROM logins WHERE password = (?)", (password,))
if username == userCheck and password == passCheck:
return redirect("/")
else:
error = "Username and Password don't match"
return render_template("login.html", error=error)
I've been stuck on this for a bit so any help would be awesome!
You must fetch the result of the database, like below:
userCheck = c.execute("SELECT password FROM logins WHERE username = (?)", (username,)).fetchall()[0][0]
passCheck = c.execute("SELECT username FROM logins WHERE password = (?)", (password,)).fetchall()[0][0]
The Problem:
I have been receiving an error whenever I tried to register a user from the UI. The idea is to submit the form and take the data into python and run an INSERT query in order to add it to the database to allow logging in.
Sample input:
Name: Kieron
Password(Hashed):
pbkdf2:sha256:150000$aQfm996V$af032bc39170c1e2b59cab53691ebb48e50d3824b851de6921c56f07f4a10d3c
Email: Kieron#example.com
Error Message:
> sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) A
> value is required for bind parameter 'password'
>[SQL: INSERT INTO
> users (name, password, email) VALUES(%(user)s, %(password)s,
> %(email)s)] [parameters: [{'user': 'Kieron', ':password':
> 'pbkdf2:sha256:150000$aQfm996V$af032bc39170c1e2b59cab53691ebb48e50d3824b851de6921c56f07f4a10d3c',
> 'email': 'kieron#example.com'}]]
Database Connection:
The database is connected with a sqlalchemy engine bind without using ORM with the intention of learning more about doing it without the ORM and the application config is below:
app = Flask(__name__)
app.config['DATABASE_URL']="url to db"
# Check for environment variable
if not os.getenv("DATABASE_URL"):
raise RuntimeError("DATABASE_URL is not set")
# Configure session to use filesystem
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Set up database
engine = create_engine(os.getenv("DATABASE_URL"))
db = scoped_session(sessionmaker(bind=engine))
Code Associated with the Problem:
I believe the following route is the source of the problem and I am not quite sure where I have gone wrong within it. The entire idea of the route is:
Clear previous session and take details from the form.
Run form entries against database to ensure unique entries.
Create password hash and input into the database.
#app.route("/register", methods=['POST','GET'])
def register():
session.clear()
if request.method == 'POST':
#check for empty fields
if not request.form.get("name"):
return apology("must provide username", 403)
elif not request.form.get("password"):
return apology("must provide password", 403)
elif not request.form.get("email"):
return apology("must provide email", 403)
#get variables from form
user = request.form.get("name")
password = request.form.get("password")
email = request.form.get("email")
#hash password
passwordHash = generate_password_hash(password, method='pbkdf2:sha256', salt_length=8)
#check email and username don't exist
if db.execute("SELECT name FROM users WHERE name = :user", {"user": user}).rowcount != 0:
return apology("Username already taken", 403)
elif db.execute("SELECT email FROM users WHERE email = :email", {"email": email}).rowcount != 0:
return apology("Email already has an account in system",403)
#add to db
db.execute("INSERT INTO users (name, password, email) VALUES(:user, :password, :email)", {"user":user, "password":passwordHash, "email":email})
db.commit()
return redirect("/login")
return render_template("register.html")
Question Summary:
I believe the error is coming from within the INSERT query, however I am not certain where.
Where am I going wrong and how could I make this work correctly?
You have a typo in the values to be inserted.
The current code has {"user":user, ":password":passwordHash, "email":email} while it should be {"user":user, "password":passwordHash, "email":email} (removed : before password)
#app.route("/login", methods=["GET", "POST"])
def login():
"""Log user in"""
# Forget any user_id
session.clear()
# User reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# Ensure username was submitted
if not request.form.get("username"):
return apology("must provide username", 403)
# Ensure password was submitted
elif not request.form.get("password"):
return apology("must provide password", 403)
# Query database for username
rows = db.execute("SELECT * FROM users WHERE username = :username",
username=request.form.get("username"))
# Ensure username exists and password is correct
if len(rows) != 1 or not check_password_hash(rows[0]["hash"], request.form.get("password")):
return apology("invalid username and/or password", 403)
# Remember which user has logged in
session["user_id"] = rows[0]["id"]
# Redirect user to home page
return redirect("/")
# User reached route via GET (as by clicking a link or via redirect)
else:
return render_template("login.html")
return apology("TODO")
when i run the above code for pset9 finance it is giving this error
TypeError: 'int' object is not subscriptable
As i understand the problem is in line 192:
session["user_id"] = rows[0]["id"]
Can anybody put forward his/her opinion?
From some of the comments, the error is coming from register after this line executes:
results = db.execute("INSERT INTO users (username, hash) VALUES (:username, :password)", username = username, password = hashed)
From the Hints section of the spec:
If str is an INSERT, and the table into which data was inserted
contains an autoincrementing PRIMARY KEY, then execute returns the
value of the newly inserted row’s primary key.
Therefore this line session["user_id"] = results[0]['id'] gives an error because results is an integer.
----ORIGINAL ANSWER -----
Actually, the problem is in index. One can expect login from the distro code to work. login is redirected to "/" (index function).
When you run the code locally, it will produce the same error when logging in a registered user. The traceback in the flask terminal should direct your attention to:
user = db.execute("SELECT * FROM users WHERE id = :id", id = session["user_id"][0]["cash"])
Notice, it is trying to set id to session["user_id"][0]["cash"]. session["user_id"] is an int. Double check the syntax.