Validating user details using sqlite3 and python - python

I created a database called finance.db and it contains a table named 'test'. The table takes 5 parameters including 'user' and 'password'. A user is already inserted into the table.
I would like the user to be able to log in by providing their username and password and matching that against the database table 'test'. If the table contains the correct username and password it allows the user to log in.
Here is how I imagine it would work:
import sqlite3
user_name = input('Enter username: ')
user_password = input('Enter password:')
def login_details(username, password):
connection = sqlite3.connect('finance.db')
cursor = connection.cursor()
cursor.execute('SELECT * FROM test')
check = cursor.fetchall()
for i in check:
if username and password in check:
print('works')
else:
print('not in db')
login_details(username=user_name, password=user_password)
Unfortunatelly it always returns 'not in db', even if correct details are inserted. I'm not sure what I am missing, but I suspect that my if statement is simply incorrect, but it does not result in a syntax or other error.
UPDATE:
I solved the problem by extracting the information that I require from a tuple and then storing its value in a variable. Here is what I changed:
for i in check:
user_name_input = i[1]
user_pass_input = i[2]
if user_name_input != username and user_pass_input != password:
print('not in db')
else:
print('in db')

In this part of code
for i in check:
if username and password in check
I suppose that check is a list of tuples that represents all the query matched rows in the table. So i is a tuple and you should compare your variables with the specific positions of the tuple which correspond to the fields username and password. Perhaps something like that:
for i in check:
if username == i[0] and password == i[1]

Related

how do you auto generate a random ID for an SQLite database table

Im in the process of creating a website with python flask and html. I want it to have a register, login, edit, delete, and home page. I want to store the users login data in an sqlite database that can then be called to veify the login of the user. in order to have different users have the same username and/or password, I need to give each user a unique ID. I use this ID in the url, and I want the user to be able to use this ID for other things in the website. because of this, when a new user is added I need to give them a random (unique) ID (probably 8 digits). I saw a bunch of stuff about AUTO INCRAMENT being random, but I didnt understand it very much, and I tried it, and it gave me consecutive numbers (which is not what I want) I also tried RANDOM() and RAND() but they both threw syntax errors. can anyone tell me how to generate an sqlite column for an random unique 8 digit ID?
here's what I have:
schema.sql
DROP TABLE IF EXISTS users;
CREATE TABLE users (
id INTEGER PRIMARY KEY --insert random generator here,
username TEXT NOT NULL,
password1 TEXT NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
heres the python that runs the schema:
init_db.py
import sqlite3
connection = sqlite3.connect('database.db')
with open('schema.sql') as f:
connection.executescript(f.read())
cur = connection.cursor()
cur.execute("INSERT INTO users (username, password1) VALUES (?, ?)",
('user1', 'pass1')
)
cur.execute("INSERT INTO users (username, password1) VALUES (?, ?)",
('user2', 'pass2')
)
connection.commit()
connection.close()
thanks in advance for any help
okay.
Ive fixed this by generating a random number in the python code. when a user registers, I take their username and password, then generate a random number between 10000000 and 99999999. then I check if its in the database already, and if so, generate another one, until I generate a unique number. then I add username, password and ID to the database at the same time.
heres what I have now
(disclaimer: i am only showing the relevant code, so some of it might not make sense)
CREATE TABLE users (
id INTEGER,
username TEXT NOT NULL,
password1 TEXT NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
the init_db.py is the same,
heres the python:
from flask import Flask, render_template, url_for, request, flash, redirect, abort#imports
import sqlite3
import random
app = Flask(__name__)
def get_db_connection():
conn = sqlite3.connect('database.db')
conn.row_factory = sqlite3.Row
return conn
def get_username(usernamex):#def and pass usernamex
validated_uname = False#reset progress variable
conn = get_db_connection()#connect to database
cur = conn.cursor()#create a cursor
try:
cur.execute('SELECT * FROM users WHERE username = ?',(usernamex,))#select the row in the users table where username == the usernamex variable
uname = cur.fetchone()[1]#uname = the second column of that row
validated_uname = True#update progress variable
except:#if the above failed: (most likely because usernamex was not in the database):
validated_uname = False#reset progress variable
if validated_uname == True:#if the try function passed:
return(uname)#update uname and send it back
conn.commit()#commit and close database
conn.close()
def get_password1(password1x):#def and pass password1x
validated_upass = False#reset progress variable
conn = get_db_connection()#connect to database
cur = conn.cursor()#create a cursor
try:
cur.execute('SELECT * FROM users WHERE password1 = ?',(password1x,))#select the row in the users table where password1 == the password1x variable
upass = cur.fetchone()[2]#upass = the third column of that row
validated_upass = True#update progress variable
except:
validated_upass = False#reset progress variable
if validated_upass == True:#if the try function passed:
return(upass)#update upass and send it back
conn.commit()#commit and close database
conn.close()
app.config['SECRET_KEY'] = '013ecbdd4aae3899c7feed1bf36dee4e'#secret key
#app.route("/register", methods=('GET', 'POST'))#url, and pass the get and post vaiables to make forms
def register():
if request.method == 'POST':#when request method is post in the html page: #(after they press submit)
usernamex = request.form['username']#take the username entered from html
password1x = request.form['password1']#same for pass1 and pass2
password2x = request.form['password2']
if not usernamex:#if nothing was entered for username:
flash('Username is required!')#error message
elif not password1x:#if nothing was entered for pass1:
flash('Password is required!')#error message
elif not password2x:#if nothing was entered for pass2:
flash('Valdiated password is required!')#error message
elif password1x != password2x:# if pass1 and pass2 dont match:
flash('Passwords do not match!')#error message
else:#otherwise
conn = get_db_connection()#connect to database
cur = conn.cursor()#create cursor
loop = True
while loop == True:
rand_id = random.randint(10000000, 99999999)#generate random number (8 digits)
try:
cur.execute('SELECT * FROM users where id = ?',(rand_id,))#select the row in the users table where id == the rand_id variable
r_id = cur.fetchone()[0]#r_id = the first column from that row ## this is just here to throw the error
except:
cur.execute('INSERT INTO users (id, username, password1) VALUES (?, ?, ?)',(rand_id, usernamex, password1x))#make a new row, and put in ID, username and password1 in their respective places
loop = False#break the loop
conn.commit()#commit and close database
conn.close()
id = rand_id#for the home url
#id = home_id(usernamex, password1x)#id = [call the home_id function {pass usernamex and password1x}]
return redirect(url_for('home', id=id))#go to the home page and pass id for the url
return render_template('register.html', title = 'Register')#render the template from register.html
thanks for everyones help :)

I am trying to create a Tkinter register system, i can add entries, I cannot validate to see if email and password in the same row match

connection = sqlite3.connect("login_register_system/user_db")
c = connection.cursor()
c.execute("""CREATE TABLE IF NOT EXISTS users (
ID text,
Firstname text,
Lastname text,
Email text,
Password text)""")
def login_authenticator():
e = (emailE.get())
p = (passwordE.get())
c.execute(f"""SELECT * FROM users WHERE Email=? AND Password=?""", (e, p))
if e == p in "user_db":
print("User exists")
else:
print("User does not exist")
This is just a part of the whole program I am trying to create, I want to know how I can check to see if a user email and password in the same row match, if they do, I can then create an IF statement to create a log in. I am not sure if I'm on the right track.
More like this:
def login_authenticator():
e = emailE.get()
p = passwordE.get()
q = c.execute("SELECT * FROM users WHERE Email=? AND Password=?", (e, p))
if q.fetchone():
print("User exists and password matches")
else:
print("User does not exist or password does not match")
I assume you understand it's a hugely bad idea to store and transmit passwords in the clear like that.
One also might ask why you're using print in a tkinter application, but I assume you'll get to that.

How can I make to make a complex query for my login system?

I want a login system which relates to a register database I made
I am trying to make a complex query which takes the user input:
Entry(self.root,
textvariable=self.username) ##There is more but I want this to be as minimal as possible
Entry(self.root,
textvariable=self.password,
show="*")
This user input then gets compared with the one in the database.
This is where I am finding it diffucult:
def login(self):
con = sqlite3.connect("register.db") ##The database which I want to open and compare user inputs to
c = con.cursor()
c.execute("SELECT * FROM register")
slist = c.fetchall()
values = [row[0] for row in slist]
values2 = [row[1] for row in slist]
if self.username.get() == values and self.password.get()==values2:
command=self.invcon ##A external thing I want to open if the user enters the data in correctly
else:
messagebox.showerror("Error","Error"parent=self.root)
con.commit()
con.close()
The error which is now happening is instead of opening the new window it moves into the else and pops up with the error box.
Database
The SQL "SELECT username * FROM register" should be "SELECT * FROM register".
Also values and values2 are list, so the comparison between a string (self.username.get() or self.password.get()) and a list will always be False.
However, you don't need to select all records from the table, just select the record with the username and password is enough:
def login(self):
con = sqlite3.connect("register.db") ##The database which I want to open and compare user inputs to
c = con.cursor()
# assume the fields required are 'username' and 'password'
# change them to suit your table definition
c.execute("SELECT 1 FROM register WHERE username = ? AND password = ?", (self.username.get(), self.password.get()))
result = c.fetchone() # get the record if any
if result:
# record found
command=self.invcon ##A external thing I want to open if the user enters the data in correctly
else:
# record not found
messagebox.showerror("Error", parent=self.root)
con.close()
I don't understand all of the errors but when selecting something from a table (in this case 'register') you can either select things by listing them up like:
c.execute("SELECT username, password ... FROM register")
or you simply select everything:
c.execute("SELECT * FROM register")
In this case you did both ("SELECT username * FROM ...") which is why there could be an error.

cur.fetchone()[0] is all of a sudden a Nonetype

Im making a login system as a data base Im using SQLite.
def loginfunction(self):
user = self.emailfield.text()
password = self.passwordfield.text()
if len(user)==0 or len(password)==0:
self.error.setText("Please input all fields.")
else:
conn = sqlite3.connect("shop_data.db")
cur = conn.cursor()
query = 'SELECT password FROM login_info WHERE username =\''+user+"\'"
cur.execute(query)
result_pass = cur.fetchone()[0]
if result_pass == password:
print("Successfully logged in.")
self.error.setText("")
else:
self.error.setText("Invalid username or password")
When I run it if the password does not match with the username from the data base it works but if I type a wrong username the app closes and prints out this
main.py", line 38, in loginfunction
result_pass = cur.fetchone()[0]
TypeError: 'NoneType' object is not subscriptable
Here is what SQLite log says + what the data base looks like data base
fetchone does
Fetches the next row of a query result set, returning a single
sequence, or None when no more data is available.
For any
'SELECT password FROM login_info WHERE username =\''+user+"\'"
there is not matching row in data if user provided username not present in username column. You should do something like
query_result = cur.fetchone()
if result_pass is None:
print("Username with given name is not known")
# action to undertake in such case
result_pass = query_result[0]
then continue as earlier

Using an SQLite return as a password field within Bcrypt (Python)

I want to check if the input password is the same as that stored in the database but when I use bcrypt.checkpw() it returns an error saying that it expects a string or byte because the SQL query returns a tuple. I can't find a way to convert the database response to a byte from a tuple to make it compatible.
sql = ''' SELECT password FROM user_data WHERE username=? '''
username = input('Input username: ')
password = bytes(input('Input Password: '), encoding='utf-8')
cur = conn.cursor()
cur.execute(sql, (username,))
rows = cur.fetchall()
for row in rows:
if bcrypt.checkpw(password, row):
details = (user_id, username, password)
print('logged in')
return details
break
Simply adding row[0] within the function solves the problem as it returns the first (and only) value inside the tuple.
Treat it like a list in other words
Extracting the a value from a tuple when the other values are unused

Categories