patternpythonMinor
Python + MySQL Login system using Twilio API
Viewed 0 times
twiliosystemloginmysqlusingpythonapi
Problem
This is one of my first python projects. I decided to make a semi-complex login system in Python, using MySQL and the Twilio API.
The current features are:
I want some feedback on the code itself. I'm thinking of making a version 2 that will have a more clean code, since this one is a mess.
Please tell me what I should improve on and good luck into understanding my code.
```
import datetime
from tkinter import *
from tkinter import messagebox
import smtplib
import re
import mysql.connector
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from twilio.rest import TwilioRestClient
import random
### Variables - Change them to fit your needs:
use_two_step_authentication = 'true' # Describes it self. True / False
accountSid = "" # Twilio Account SID
auth_token = "" # Twilio Authentication Token
twilio_number= "" # Twilio Assigned Number
client = TwilioRestClient(accountSid, auth_token)
__author__ = 'hiperbolt' # Gotta get some o' that credit xd
cnx = mysql.connector.connect() # MySQL Connector Information
cursor = cnx.cursor()
server = smtplib.SMTP('smtp.gmail.com', 587) # Mail server, currently set to Gmail
server.starttls()
server.login('', '') # Mail server credentials
EMAIL_REGEX = re.compile(r"[^@]+@[^@]+\.[^@]+") # In case you are curious, REGEX to make sure mail is valid, feel free to make a more comprehensive one
mymail = "" # Mail adress in server.login
###
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
def to_integer(dt_time):
return 10000dt_time.year + 100dt_time.month + dt_time.day
class login():
def __init__(self):
self.frame1 = Frame(root)
self.frame2 = Frame(root)
self.entry1 = Entry(self.frame1)
self.entry2 = Entry(self.frame2)
self.label1 = Label(self.frame1, text='Usernam
The current features are:
- Multi-account support
- Two-Factor Authentication
- Password Recovery
- Password Change
I want some feedback on the code itself. I'm thinking of making a version 2 that will have a more clean code, since this one is a mess.
Please tell me what I should improve on and good luck into understanding my code.
```
import datetime
from tkinter import *
from tkinter import messagebox
import smtplib
import re
import mysql.connector
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from twilio.rest import TwilioRestClient
import random
### Variables - Change them to fit your needs:
use_two_step_authentication = 'true' # Describes it self. True / False
accountSid = "" # Twilio Account SID
auth_token = "" # Twilio Authentication Token
twilio_number= "" # Twilio Assigned Number
client = TwilioRestClient(accountSid, auth_token)
__author__ = 'hiperbolt' # Gotta get some o' that credit xd
cnx = mysql.connector.connect() # MySQL Connector Information
cursor = cnx.cursor()
server = smtplib.SMTP('smtp.gmail.com', 587) # Mail server, currently set to Gmail
server.starttls()
server.login('', '') # Mail server credentials
EMAIL_REGEX = re.compile(r"[^@]+@[^@]+\.[^@]+") # In case you are curious, REGEX to make sure mail is valid, feel free to make a more comprehensive one
mymail = "" # Mail adress in server.login
###
def combine_funcs(*funcs):
def combined_func(*args, **kwargs):
for f in funcs:
f(*args, **kwargs)
return combined_func
def to_integer(dt_time):
return 10000dt_time.year + 100dt_time.month + dt_time.day
class login():
def __init__(self):
self.frame1 = Frame(root)
self.frame2 = Frame(root)
self.entry1 = Entry(self.frame1)
self.entry2 = Entry(self.frame2)
self.label1 = Label(self.frame1, text='Usernam
Solution
Style
I suggest you to read through PEP 8, the official Python style guide to cleanup your various nammings and spacing issues. Ultimately, it is not necessarily about picking a style, but rather being consistent using such style, which you are not, and it impairs readability.
You also don't really need to store that much into your classes as most of the widgets/containers are not reused accross the various methods.
Callables
What bothers me the most in this code is the way you define lambdas to call functions with no arguments.
are better written
I also have a hard time believing that the way you call
when clicking the button, the
You should instead write:
As you pass callables to
Passwords
An other bad idea here is to store passwords as plain text in the database. Even worse, sending them as plain text in emails.
Instead you should look into the
I suggest you to read through PEP 8, the official Python style guide to cleanup your various nammings and spacing issues. Ultimately, it is not necessarily about picking a style, but rather being consistent using such style, which you are not, and it impairs readability.
You also don't really need to store that much into your classes as most of the widgets/containers are not reused accross the various methods.
Callables
What bothers me the most in this code is the way you define lambdas to call functions with no arguments.
self.button1 = Button(self.frame2, text='Login', command=lambda: self.loginconfirm())
self.button2 = Button(self.frame2, text='Forgot password?', command=lambda: self.loginhelp())
self.button1 = Button(self.frame2, text='Submit', command=lambda: checkrandomnumber())
self.button1 = Button(self.frame2, text='Recover password', command=lambda: self.loginhelpconfirm())are better written
self.button1 = Button(self.frame2, text='Login', command=self.loginconfirm)
self.button2 = Button(self.frame2, text='Forgot password?', command=self.loginhelp)
self.button1 = Button(self.frame2, text='Submit', command=checkrandomnumber)
self.button1 = Button(self.frame2, text='Recover password', command=self.loginhelpconfirm)I also have a hard time believing that the way you call
combine_funcs produces correct results. Well it works, but not as it should:self.button3 = Button(self.frame2, text='Go back', command=lambda: combine_funcs(self.frame1.pack_forget(), self.frame2.pack_forget(), initialscreen()))when clicking the button, the
lambda will execute, calling combine_funcs with the result of self.frame1.pack_forget(), self.frame2.pack_forget() and initialscreen(). At this point, all 3 functions has been executed and combine_funcs executes with their result (None, None, None), returning a callable that will crash when called because None (which will be f in combine_funcs) is not callable.You should instead write:
self.button3 = Button(self.frame2, text='Go back', command=combine_funcs(self.frame1.pack_forget, self.frame2.pack_forget, initialscreen))As you pass callables to
combine_funcs so the call f(*args, **kwargs) will not fail. And since combine_funcs returns a callable too, you can use it as the command parameter.Passwords
An other bad idea here is to store passwords as plain text in the database. Even worse, sending them as plain text in emails.
Instead you should look into the
hashlib module and only store hashes in your database. Whenever someone tries to authenticate, you hash the provided value and compare it to the hash stored in the database.Code Snippets
self.button1 = Button(self.frame2, text='Login', command=lambda: self.loginconfirm())
self.button2 = Button(self.frame2, text='Forgot password?', command=lambda: self.loginhelp())
self.button1 = Button(self.frame2, text='Submit', command=lambda: checkrandomnumber())
self.button1 = Button(self.frame2, text='Recover password', command=lambda: self.loginhelpconfirm())self.button1 = Button(self.frame2, text='Login', command=self.loginconfirm)
self.button2 = Button(self.frame2, text='Forgot password?', command=self.loginhelp)
self.button1 = Button(self.frame2, text='Submit', command=checkrandomnumber)
self.button1 = Button(self.frame2, text='Recover password', command=self.loginhelpconfirm)self.button3 = Button(self.frame2, text='Go back', command=lambda: combine_funcs(self.frame1.pack_forget(), self.frame2.pack_forget(), initialscreen()))self.button3 = Button(self.frame2, text='Go back', command=combine_funcs(self.frame1.pack_forget, self.frame2.pack_forget, initialscreen))Context
StackExchange Code Review Q#140930, answer score: 2
Revisions (0)
No revisions yet.