User authentication not working in flask and sqlite - python

What I am trying to do is to get the email id and compare against the SQLite table.
If email exists in the table then I update the table with the emailid and random generated password and mail them.
If email does not exists in the table then I use insert query to enter the email as well as random generated password into the table.
After the insert or the update query is fired I mail them the generated password using Flask-mail
However I am unable to execute it
def sqliteconfig():
try:
conn = sqlite3.connect('auth.db',check_same_thread=False)
cur = conn.cursor()
conn.execute('CREATE TABLE IF NOT EXISTS auth (AID INTEGER PRIMARY KEY AUTOINCREMENT, emailid TEXT UNIQUE, otp TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP)')
cur.close()
except Exception as e:
print(e)
return 'DatabaseDown'
# return 'DatabaseDown'
return conn
#bp.route('/')
def index_redirect():
return redirect(url_for('devcon.login'))
#bp.route('/login',methods=['GET','POST'])
def login():
conn = sqliteconfig()
cur = conn.cursor()
if request.method == 'POST':
emailid = request.form['emailid']
if emailid != "":
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
passlen = 8
password = "".join(random.sample(s,passlen ))
conn.execute('select count(*) from auth where emailid=(?)',[emailid])
rows = cur.fetchall();
if len(rows) == 0:
conn.execute('insert into auth(email,otp) values(?,?)',[emailid,password])
conn.commit()
elif len(rows)==1:
conn.execute('update auth SET otp=(?) where emailid=(?)',[emailid,password])
conn.commit()
return str(rows)
return render_template("login/login.html")
The Particular problem I am facing right know is SELECT COUNT query returns nothing and INSERT query throws constraint violation error of unique emailid.
I am looking forward if there is any better way to do this

For the first error where SELECT COUNT returns nothing, in Sqlite3 select * is used instead of select count(*). Therefore your code should be:
rows = conn.execute('SELECT * FROM auth WHERE emailid = ?',(emailid,)).fetchall()
For the second insertion error, you may already have an equivalent emailid value stored into auth. That is the only reason why you would have a constraint violation of an unique emailid.
Another (potential) error is that you set otp to emailid and password to emailid, while the order should be reversed:
conn.execute('update auth SET otp=(?) where emailid=(?)',[emailid,password])
Instead, do this:
conn.execute('UPDATE auth SET otp = ? WHERE emailid = ?',(password, emailid))
Final code:
def sqliteconfig():
try:
conn = sqlite3.connect('auth.db',check_same_thread=False)
cur = conn.cursor()
conn.execute('CREATE TABLE IF NOT EXISTS auth (AID INTEGER PRIMARY KEY AUTOINCREMENT, emailid TEXT UNIQUE, otp TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP)')
cur.close()
except Exception as e:
print(e)
return 'DatabaseDown'
# return 'DatabaseDown'
return conn
#bp.route('/')
def index_redirect():
return redirect(url_for('devcon.login'))
#bp.route('/login',methods=['GET','POST'])
def login():
conn = sqliteconfig()
cur = conn.cursor()
if request.method == 'POST':
emailid = request.form['emailid']
if emailid != "":
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
passlen = 8
password = "".join(random.sample(s,passlen ))
rows = conn.execute('SELECT * FROM auth WHERE emailid = ?',(emailid,)).fetchall()
if len(rows) == 0:
conn.execute('INSERT into auth (email, otp) VALUES (?, ?)',(emailid, password))
conn.commit()
elif len(rows)==1:
conn.execute('UPDATE auth SET otp = ? WHERE emailid = ?',(emailid, password))
conn.commit()
return str(rows)
return render_template("login/login.html")

Related

Get value of row from mysqlphp in flask python

I have table like:
Database
I want to print password only like:
samer
I tried this:
mysql = MySQL()
flask.config['MYSQL_HOST'] = 'localhost'
flask.config['MYSQL_USER'] = 'root'
flask.config['MYSQL_PASSWORD'] = ''
flask.config['MYSQL_DB'] = 'web'
mysql.init_app(flask)
#flask.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
# print(password)
cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cur.execute('SELECT * FROM users WHERE password=%s', (password,))
user = cur.fetchall()
print(user)
# if password is wrong, user will be None else Dict
if user is not None:
print(user['password'])
else:
print("User not found")
but i get this error:
TypeError: tuple indices must be integers or slices, not str
i can print result if i use:
for row in user:
passw = row['password']
but i need to use first method, how can i achieve that?
You need to replace the fetchall call with fetchone:
cur = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cur.execute('SELECT * FROM users WHERE password=%s', (password,))
user = cur.fetchone()
# if password is wrong, user will be None else Dict
if user is not None:
print(user['password'])
else:
print("User not found")

Data Not inserting in sqlite3 even after commiting in python

I am making a authentication web app , and trying to insert data in database and commiting it too but still doesn't work . I am using flask-sqlite,It says success but when I go my /list endpoint it is blank and even does't print's anything in console . Here's the full code
from flask import Flask, render_template, request, url_for
import sqlite3
app = Flask(__name__)
con = sqlite3.connect("details.db")
print("Database opened successfully")
con.execute("create table if not exists Users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE NOT NULL, password TEXT NOT NULL)")
print("Table created successfully")
con.close()
#app.route('/signup', methods=['GET', 'POST'])
def signup():
msg = ""
if request.method == "POST":
try:
email = request.form["email"]
password = request.form["password"]
print(name, email)
with sqlite3.connect("details.db") as con:
cur = con.cursor()
cur.execute("INSERT into Users (email, password) values (%s, %s)",(email, password))
cur.commit()
msg = "User successfully Added"
except Exception as err:
con.rollback()
msg = "Sorry We Can't Signup You"
finally:
return render_template("res.html",msg = msg)
con.close()
#app.route("/signup-page")
def signupTemplate():
return render_template('index.html')
#app.route("/list")
def list_users():
con = sqlite3.connect("details.db")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select * from Users")
row = cur.fetchall()
email = ""
password = ""
for rows in row:
email = rows["email"]
password = rows["password"]
con.close()
return render_template("list.html", email=email,password=password)
app.run(debug=True)
change this two lines.
cur.execute(f"INSERT into Users (email, password) values ('{email}', '{password}')")
con.commit()
you can use format string in your query and connection.commit() not cursor.

SQLITE3 FROM table Select column WHERE Boolean statement

I have tried 3 different variations of sqlite3 statement to SELECT a data:
cursor.execute('SELECT * FROM users WHERE username = ?', (username,))
cursor.execute('''SELECT * FROM users WHERE username = ?;''', (username,))
cursor.execute('SELECT * FROM users WHERE username = "monkey1" ')
References for these statements are from 1 2. However, none of them worked. I suspect that I am doing something really silly but can't seem to figure this out.
I want to be able to print out the data of username "monkey". Appreciate any help to point out my silly mistake.
import sqlite3
import datetime
def get_user(connection, rows='all', username=None ):
"""Function to obtain data."""
#create cursor object from sqlite connection object
cursor = connection.cursor()
if rows == 'all':
print("\nrows == 'all'")
cursor.execute("SELECT * FROM users")
data = cursor.fetchall()
for row in data:
print(row)
if rows == 'one':
print("\nrows == 'one'")
cursor.execute('SELECT * FROM users WHERE username = ?', (username,))
#cursor.execute('''SELECT * FROM users WHERE username = ?;''', (username,))
#cursor.execute('SELECT * FROM users WHERE username = "monkey1" ')
data = cursor.fetchone()
print('data = ',data)
cursor.close()
return data
def main():
database = ":memory:"
table = """ CREATE TABLE IF NOT EXISTS users (
created_on TEXT NOT NULL UNIQUE,
username TEXT NOT NULL UNIQUE,
email TEXT NOT NULL UNIQUE
); """
created_on = datetime.datetime.now()
username = 'monkey'
email = 'monkey#gmail'
created_on1 = datetime.datetime.now()
username1 = 'monkey1'
email1 = 'monkey1#gmail'
# create a database connection & cursor
conn = sqlite3.connect(database)
cursor = conn.cursor()
# Insert data
if conn is not None:
# create user table
cursor.execute(table)
cursor.execute('INSERT INTO users VALUES(?,?,?)',(
created_on, email, username))
cursor.execute('INSERT INTO users VALUES(?,?,?)',(
created_on1, email1, username1))
conn.commit()
cursor.close()
else:
print("Error! cannot create the database connection.")
# Select data
alldata = get_user(conn, rows='all')
userdata = get_user(conn, rows='one', username=username )
print('\nalldata = ', alldata)
print('\nuserdata = ', userdata)
conn.close()
main()
Your table definition has the fields in order created_on, username, email but you inserted your data as created_on, email, username. Therefore the username of the first row was 'monkey#gmail'.
A good way to avoid this kind of mistake is to specify the columns in the INSERT statement rather than relying on getting the order of the original table definition correct:
INSERT INTO users (created_on, email, username) VALUES (?,?,?)

Why is my web application generating a 1064 (42000) error when trying to POST an INSERT query? [duplicate]

This question already has answers here:
How to create a "singleton" tuple with only one element
(4 answers)
Closed 6 years ago.
I'm trying to create a user registration page using Flask, MySQL and HTML forms. I'm running into this error when I try to post data from the form to the database. Can anyone see where I might have gone wrong with the SQL?
The full error received is:
1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%s' at line 1
My connection function is:
import mysql.connector
from flask import *
def connection():
conn = mysql.connector.connect(host="localhost", db="user_login",user="root",
password="password")
c = conn.cursor()
return c, conn
This is imported in the init.py file and called below:
class RegistrationForm(Form):
firstName = StringField('First Name', [validators.Length(min = 3, max = 25)])
lastName = StringField('Surname', [validators.Length(min = 3, max = 25)])
username = StringField('Username', [validators.Length(min = 4, max = 25)])
email = StringField('Email Address', [validators.Length(min = 6, max = 50)])
password = PasswordField('Password', [validators.required(),
validators.EqualTo('confirm', message = 'Passwords must match')])
confirm = PasswordField('Repeat Password')
#app.route('/register/', methods = ['GET', 'POST'])
def register_page():
try:
form = RegistrationForm(request.form)
if request.method == "POST" and form.validate():
firstName = form.firstName.data
lastName = form.lastName.data
username = form.username.data
email = form.email.data
password = form.password.data
is_admin = 0
c, conn = connection()
x = c.execute("SELECT * FROM users WHERE username = %s",(username))
if int(x) > 0:
flash("That username is already taken, please choose another")
return render_template('register.html', form = form)
else:
c.execute("""
INSERT INTO users (firstName, lastName, username, email, password, is_admin)
VALUES (%s, %s, %s, %s, %s, %s)
""",(firstName, lastName, username, email, password, is_admin))
conn.commit()
flash("Thanks for registering!")
c.close()
conn.close()
gc.collect()
session['logged_in'] = True
session['username'] = username
return redirect(url_for('dashboard'))
return render_template('register.html', form = form)
except Exception as e:
return(str(e))
I think your issue is the SELECT, not the INSERT. You are passing (username) as a parameter -- this is not a tuple. You need to use a trailing comma:
x = c.execute("SELECT * FROM users WHERE username = %s", (username,))

Python Flask SQL Register Login Page "hash must be unicode or bytes, not long"

Im trying to create a login / register page. My register page works and I see the information and hashed passwords added. When I try to login, I get "hash must be unicode or bytes, not long" flashed. Please help!
#app.route('/login/', methods=['GET','POST'])
def login():
try:
c,conn = connection()
if request.method == 'POST':
data = c.execute("SELECT * FROM users WHERE username = %s",
thwart(request.form['username']))
if sha256_crypt.verify(request.form['password'], data):
session['logged_in'] = True
session['username'] = request.form['username']
flash('You are now logged in.'+str(session['username']))
return redirect(url_for('dashboard'))
else:
error = 'Invalid credentials. Try again'
return render_template('login.html', error=error)
except Exception, e:
flash(e)
------------------------------------------------------------------
import MySQLdb
def connection():
conn = MySQLdb.connect(host="localhost",
user = "root",
passwd = "julie774",
db = "PYTHONTUT")
c = conn.cursor()
return c, conn
data = c.execute("SELECT * FROM users WHERE username = %s",
thwart(request.form['username']))
cursor.execute just executes the query and returns the number of affected rows. (see pydoc of cursor.execute). Thus in your data variable you have the number of found rows.
Instead you have to fetch the data from the cursor. Also since you are requesting all the columns from user (*), you will have to extract only a particular column (the index of it — see the end note).
c.execute("SELECT password FROM users WHERE username = %s",
thwart(request.form['username']))
data = c.fetchone()
# c.fetchone() returns None if no row has been found
if sha256_crypt.verify(request.form['password'], data[0]):
...
In your example you are connecting to database without specifying the type of the cursor, thus c.fetchone() will return a tuple (for example (1L, 'John Doe', '392347')). And to select particular column you have to use numerical index — data[1] to retrieve 'John Doe'.
If you want named dictionary instead, you will have to specify it when connecting to db.
conn = MySQLdb.connect(host="localhost",
user = "root",
passwd = "***",
db = "PYTHONTUT",
cursorclass=MySQLdb.cursors.DictCursor
)
Then c.fetchone() will return a dict instead (e.g. {'id': 1L, 'name': 'John Doe', 'password': '392347'}) so you can use more readable data['name'] etc.

Categories

Resources