SQLite -> Checking if a username already exists - python

When a user creates an account it needs to check whether the username already exists within the SQLite database. This functions job is to check this and currently takes in the username that the user has inputted. However, whenever running this it wouldn't return True when a username that doesn't exist is inputted so a new account can never be created due to this issue. I need this to return true if the username that the user has inputted doesn't already exist in the table.
This is what I currently have
def checkDB(username):
c.execute('select exists(select 1 from LoginCredentials where username = [username])')
[exists] = c.fetchone() # fetch and unpack the only row our query returns
if exists:
print("False")
return False # Returns false if the username already exists in the database
else:
print("True")
return True # Returns true if the username doesn't exist in the database

You can use the fact that None is falsy to check the existence of a user.
First thing why are you not using a placeholder ? for the username, then you've used a more complex than necessary query.
import sqlite3
con = sqlite3.connect(":memory:")
cur = con.cursor()
cur.execute("CREATE TABLE LoginCredentials (username VARCHAR)")
cur.execute("INSERT INTO LoginCredentials VALUES ('ljmc')")
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", ("ljmc",))
if cur.fetchone(): # (1,) is returned as one row matched, non empty tuple is truthy
print("ljmc exists") # will print
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", ("nonexistent",))
if cur.fetchone(): # None is returned as no row matched, None is falsy
print("nonexistent exists") # won't print
con.close()
Or as a function if you want, with explicitly checking for None.
def user_exists(cur: sqlite3.Cursor, username: str) -> bool:
cur.execute("SELECT 1 FROM LoginCredentials WHERE username = ?", (username,))
return cur.fetchone() is not None
Notice I pass a cursor as a function argument, this is for dependency inversion.

After going back and forth I was able to come up with a solution here it is in case anybody else is having a similar issue in their own program
def checkDB(username):
c.execute("SELECT username FROM LoginCredentials")
query = c.fetchall()
length = len(query)
for i in range(length):
dbUsername = query[i][0]
if username == dbUsername:
return True
return False

Related

Python variable loses value when passed to a if statement

I am trying to retrieve a password hash that i stored in my database. The problem is how i handle when the query is null.
In the case that I search for a user that exists the first print will print something but the in the second print that is inside the if statement it will output None
I don't understand what is happening. It seems to me that the variable is loosing it's value
db_password = c.execute("SELECT hashed FROM contas WHERE username=?", [username])
print(db_password.fetchone())
if(db_password.fetchone() != None):
print(db_password.fetchone())
hashed, = db_password.fetchone()
# Verify if passwords match
if ((bcrypt.checkpw(password.encode('utf8'), hashed) == False)):
print("Wrong credentials")
else:
print("User logged in successfully")
else:
print(db_password.fetchone())
print("User doesn't exist")
Each time you call db_password.fetchone() it fetches the next row of results. But your query only returns one row.
The call in the if statement fetches that row. Then the call in the print() call tries to fetch the next row, but there isn't another row, so it prints None. Then the third call in the variable assignment tries to fetch the next row, but there still isn't another row, so you get an error because you're trying to assign None in a tuple assignment.
You should fetch into a variable. Then you can test that and use it in the assignment.
row = db_password.fetchone()
if row:
print(row)
hashed = row[0]
...
else:
print("user doesn't exist")
Calling fetchone() will move the cursor to the next row each time and return None if there are no rows available (see documentation here). If you want to just check the one password, store the result of the fetchone call in a variable and use it for future comparisons/printing, i.e.
password = db_password.fetchone()
print(password)
if password is not None:
print(password) # If password is not None, this will print the same thing as the previous print call
...
else:
...

Error when checking if username, hash, and key exists in a table stored in mysql

The output of the program:
WELCOME, PLEASE ENTER YOUR USERNAME AND PASSWORD
Enter username:Manas
Enter password:123456
error2
Error3
Below is a minimal code of the program:
import mysql.connector
import hashlib
import os
mycon=mysql.connector.connect(host="localhost",user="root",passwd="123456",database="library",use_unicode=True,charset="utf8")
cursor=mycon.cursor()
stmt = "SHOW TABLES LIKE 'users'"
cursor.execute(stmt)
result = cursor.fetchone()
if result:
pass
else:
cursor.execute("create table users(username varchar(20),key varbinary(100),salt varbinary(100));")
def users(username,password):
cursor.execute("select * from users where username='{}'".format(username))
data=cursor.fetchone()
if data=="(NULL)":
return False
elif data==True:
salt=data[2]
key=hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
if data[1]==key:
return True
elif data[1]!=key:
return False
else:
print("error1")
else:
print("error2")
return False
#Main program
print("WELCOME, PLEASE ENTER YOUR USERNAME AND PASSWORD")
username=input("Enter username:")
password=input("Enter password:")
users(username,password)
if users==True:
print("user exists")
elif users==False:
print("user does not exist")
else:
print("Error3")
The table it was being referred to:
mysql> use library;
Database changed
mysql> select * from users;
+----------+--------------------------------------------------------------------+--------------------------------------------------------------------+
| username | key | salt |
+----------+--------------------------------------------------------------------+--------------------------------------------------------------------+
| Manas | 0xE42AB9B18A8F144EA7933FFA8E69E1FE28F20DA67B3E0FF3F1A0C2203D6148B2 | 0xF68894D924A69D035CC096C497F933B29A08E075F6DA2B19D955D08A33C0CAB4 |
+----------+--------------------------------------------------------------------+--------------------------------------------------------------------+
1 row in set (0.00 sec)
Print(Data):
WELCOME, PLEASE ENTER YOUR USERNAME AND PASSWORD
Enter username:Manas
Enter password:12345
('Manas', bytearray(b'\xe4*\xb9\xb1\x8a\x8f\x14N\xa7\x93?\xfa\x8ei\xe1\xfe(\xf2\r\xa6{>\x0f\xf3\xf1\xa0\xc2 =aH\xb2'), bytearray(b'\xf6\x88\x94\xd9$\xa6\x9d\x03\\\xc0\x96\xc4\x97\xf93\xb2\x9a\x08\xe0u\xf6\xda+\x19\xd9U\xd0\x8a3\xc0\xca\xb4'))
error2
Error3
Why does this happen?
You have to make also the connection so that it uses utf8
Assuming that you have uft8mb4
mycon=mysql.connector.connect(host="localhost"
,user="root"
,passwd="123456"
,database="library"
,charset="utf8mb4")
the character set cpould also be utf8, thqat yoiu have to check
and use prepared statements when hadling parameters
cursor.execute("select * from users where username=%s",(username,))
Update
Addidtional your table definion has a problem key is a reserved word in MySQL so oyu ned to encapsule it in backticks like below
cursor.execute("create table users(username varchar(20),`key` varbinary(100),salt varbinary(100));")
Update 2
after testing your code i found some problems in it
Your function retuns a value ut you never assign it
And the data IS NULL if there are no users
import mysql.connector
import hashlib
import os
mycon=mysql.connector.connect(host="localhost",user="root",passwd="123456",database="library",use_unicode=True,charset="utf8mb4")
cursor=mycon.cursor()
stmt = "SHOW TABLES LIKE 'users'"
cursor.execute(stmt)
result = cursor.fetchone()
if result:
pass
else:
cursor.execute("create table users(username varchar(20),`key` varbinary(100),salt varbinary(100));")
def users(username,password):
cursor.execute("select * from users where username=%s",(username,))
data=cursor.fetchone()
if data is None :
return False
elif data is not None:
salt=data[2]
key=hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt, 100000)
if data[1]==key:
return True
elif data[1]!=key:
return False
else:
print("error1")
else:
print("error2")
return False
#Main program
print("WELCOME, PLEASE ENTER YOUR USERNAME AND PASSWORD")
username=input("Enter username:")
password=input("Enter password:")
users = users(username,password)
if users==True:
print("user exists")
elif users==False:
print("user does not exist")
else:
print("Error3")

Error when sending information to the database

I'm doing a code where the program ask for personal informations of someone, then he reads those infomations and send to the database. So I have the option to register and to consult. I don't know if the program is with more problems because I need to fix it first.
When I try to register the person It's give me the error "Is not possible to register." and I can't find why.
import sqlite3
conn = sqlite3.connect('database.db')
c = conn.cursor()
def criardb():
c.execute('CREATE TABLE IF NOT EXISTS pessoas(id INTEGER PRIMARY KEY
AUTOINCREMENT,nome VARCHAR, idade INT, tel VARCHAR, pais VARCHAR)')
conn.commit()
def insertdata(nome,idade,tel,pais):
c.execute = ('INSERT INTO pessoas VALUES (?,?,?,?)',
(nome,idade,tel,pais))
conn.commit()
def consultdata():
sql = c.execute('SELECT * FROM pessoas')
for row in sql:
print("Nome: {}".format(row[0]))
def consultdataind(esc):
sql = c.execute('SELECT * FROM pessoas WHERE id = ?')
for row in sql(sql,(esc)):
print("Nome: {} Idade: {} Telefone: {} País:
{}".format(row[0],int(row[1]),row[2],row[3]))
try:
print("Creating database...")
criardb()
except:
print("ERRO: It was not possible to create the database.")
else:
print("Database successfully created.")
while True:
print("Welcome to the register system, choose a option:")
op = int(input("| 1 - Register | 2 - Consult | 3 - Exit | "))
if op == 1:
n = input("Nome: ")
i = int(input("Idade: "))
t = input("Telefone: ")
p = input("País: ")
try:
insertdata(n,i,t,p)
except:
print("ERRO: It's not possible to register")
else:
print("Successfully registered.")
elif op == 2:
print("List of registered users:")
try:
consultdata()
except:
print("It was not possible to load the list.")
print("Write the person ID to individual consult.")
esc = int(input(">> "))
consultdataind(esc)
elif op == 3:
break
else:
print("Invalid command.")
I need to send all the information to the database and return the consult, first it will show all the registered person then the user can write the respective ID of someone in the list and it will show all the details about this person
Replace your insertdata with this and everything should work fine.
def insertdata(nome,idade,tel,pais):
c.execute('INSERT INTO pessoas (nome,idade,tel,pais) VALUES (?,?,?,?)', [nome,idade,tel,pais])
conn.commit()
You need to call the execute method of the cursor here.
And on the side note, never use except directly without specifying an exception. It hides the simplest of error messages which will make your code very hard to debug. As of now it was AttributeError that was causing this problem as you were trying to assign value to Cursor which is ReadOnly

Why does not the string equal to a text value in sqlite3 database (Python)

hi i am trying to make a simple login module in tkinter for that i am taking input from the user via the entry widget and comparing that password to the password in database via a if loop... but for some reason the password doesnt match, so i tried some tests and it dosent match ....
import sqlite3
conn=sqlite3.connect('auth_rWebsites.db')
c=conn.cursor()
def check_password(key):
thePass= c.execute("SELECT pass FROM user_pass")
if key == thePass:
print("right Password")
else:
print("Wrong Password")
rows= c.execute("SELECT * FROM user_pass")
for row in rows:
print row
check_password("root")
this the above simple test code i wrote..
output is
(u'root',)
Wrong Password
so someone please explain me why is this happening and what do i have to do to match it ....
thePass is an iterable that yeilds tuples, key is a string.
In general, the python db api always returns database rows as tuples because you can select multiple things in a statement. Rather than having confusing logic that needs to look at the query to determine the return type of the row (for both the database api and the caller), the spec says to just return a tuple always.
You need to compare key with the row correctly...
rows = c.execute("Select pass FROM user_pass")
for row in rows:
if row[0] == thePass:
print("right password")
return
else:
print("Wrong Password")
Note, this probably isn't what you actually want. All it does is verify that one row in the user_pass table has that pass value. More likely, you want to filter the query against the username and then check the password:
c.execute("SELECT pass FROM user_pass WHERE username = ?", username)
result = c.fetchone() # username should be unique I assume :-)
if result[0] == salt_and_hash(key):
print("Yeah!")
else:
print("No!")
c.execute("SELECT pass FROM user_pass") is returning a tuple, not a string, but key is a string. You need to get the first value from the tuple and compare that to your key argument, so change your function to this:
def check_password(key):
thePass= c.execute("SELECT pass FROM user_pass")[0] # Changed here
if key == thePass:
print("right Password")
else:
print("Wrong Password")

login function using sqlite in python

I'm writing a python script that allows for sign up and log in, the signup works fine, but the login and authentication doesn't work even if the user is registered.
def userlogin(self, ID, password):
try:
statement = conn.execute('SELECT ID FROM USERS')
conn.commit()
for row in statement:
if ID in statement:
print "%d" % ID
pas = conn.execute('SELECT PASSWORD FROM USERS WHERE ID = %d' % (ID))
conn.commit()
if password in pas:
print "welcome user %d" % ID
conn.close()
else:
print "username/password incorrect!"
conn.close()
else:
print "Incorrect ID! If you are not a user, please register here."
except IOError:
print "Select statement could not execute!"
I know this is not the best way to write this function, I'm doing it for practice. Even if the password and ID are entered correctly, it always prints Incorrect ID. Is there anything wrong with the if statement?
The problems I see at first glance: (there may be more)
No need for commit statements since you only read data
Your first select statement should filter on something; a user name perhaps?
You close the connexion in the middle of the loop, so event if you find the right user you may have an exception
Bonus: are your passwords in clear text?? (not so important since you say it is only practice; but it is good practice to encrypt passwords anyway)
for your code, it should be if ID in row rather than if ID in statement and your need break the for loop if a user is valid.
def userlogin(self, ID, password):
try:
statement = conn.execute('SELECT ID FROM USERS')
for row in statement:
if ID in row: # compare one by one
print "%d" % ID
pas = conn.execute('SELECT PASSWORD FROM USERS WHERE ID = %d' % (ID))
if password in pas:
print "welcome user %d" % ID
else:
print "password incorrect!" # ID is matched
conn.close()
return
print "Incorrect ID! If you are not a user, please register here."
except IOError:
print "Select statement could not execute!"
finally:
conn.close()
Instead of so many checks, you can just use a query like
SELECT COUNT(*) FROM USERS WHERE PASSWORD = %s AND ID=%d
Now if the count is 0 then the password/id combo is wrong, else, if the count is non-zero, the password/id combination is correct.

Categories