Kurdish Learner
Kurdish Learner

Reputation: 75

Is there a way for my GUI Password Manager to be accessed with a username and password in Python?

I made a program (Password Manager) using Python which I can enter a Website, Email and Password and click "Add" button to write the inputs into a json file, I have no problem with that, it works good, what I want to do is when I open the program I want it to ask me for a login username and password.

Not to mention, I have created the login window with two labels and two entries for each "Username" and "Password", as well as adding a "Enter" button below, I also created a function called "validate" on line 107, and assigned it to the "Enter" button using "command=validate", I cannot think of a way to figure out whenever the username.input.get() == "username" and password.input.get() == "password" my program should open and this login window should close.

I have searched a lot but I couldn't find anything that I can use in my code.

here's my code:

from tkinter import *
from tkinter import messagebox
import random
import pyperclip
import json
# --------------------------------- Password Generator ---------------------------------- #
# Password Generator Project

def generate_password():
    letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
    numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
    symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']

    nr_letters = random.randint(8, 10)
    nr_symbols = random.randint(2, 4)
    nr_numbers = random.randint(2, 4)

    password_list = []


    password_letters = [random.choice(letters) for _ in range(nr_letters)]

    password_symbols = [random.choice(symbols) for _ in range(nr_symbols)]

    password_numbers = [random.choice(numbers) for _ in range(nr_numbers)]
    password_list = password_letters + password_symbols + password_numbers
    random.shuffle(password_list)


    password = "".join(password_list)
    password_input.insert(0, password)
    pyperclip.copy(password)
# --------------------------------- Save Passwords ---------------------------------- #
def save():
    website = website_input.get()
    email = email_input.get()
    password = password_input.get()

    new_data = {

        website: {
            "email": email,
            "password": password,

        }

                }

    if len(website) == 0 or len(email) == 0 or len(password) == 0:
        messagebox.showinfo(title="Oops", message="Please don't leave any fields empty!")

    else:
        try:
            with open("data.json", "r") as file:

                # Reading old data
                data = json.load(file)

        except FileNotFoundError:
            with open("data.json", "w") as file:
                # Updating old data with new data
                json.dump(new_data, file, indent=4)
        else:
            data.update(new_data)

            with open("data.json", "w") as file:
                # Saving updated data
                json.dump(data, file, indent=4)
        finally:
            website_input.delete(0, END)
            email_input.delete(0, END)
            password_input.delete(0, END)
            website_input.focus()

# --------------------------------- Fine Password ---------------------------------- #

def find_password():

    website = website_input.get()
    try:
        with open("data.json") as file:
            data = json.load(file)

    except FileNotFoundError:
        messagebox.showinfo(title="Error", message="No data file found!")

    else:
        if website in data:
            email = data[website]["email"]
            password = data[website]["password"]
            messagebox.showinfo(title=website,message=f"Email: {email}\n\nPassword: {password}")
        else:
            messagebox.showinfo(title="Error", message=f"No details for {website} exists!")


# --------------------------------- UI Setup ---------------------------------- #


def validate():
    username = username_check_input.get()
    password = password_check_input.get()
    if username == "username" and password == "password":
        pass
    else:
        messagebox.showwarning(title="Error", message="Wrong password, try again!")
        username_check_input.delete(0, END)
        password_check_input.delete(0, END)



password_checker_window = Tk()
password_checker_window.title("Login to the password database")
password_checker_window.config(padx=50, pady=50, width=500, height=350, bg="#282120")

# canvas = Canvas(width=200, height=200, bg="#282120", highlightthickness=0)
# logo_image = PhotoImage(file="logo.png")
# canvas.create_image(100, 100, image=logo_image)
# canvas.grid(column=1, row=0)

username_check_label = Label(text="Username:", bg="#282120", fg="#D4483B")
username_check_label.grid(column=0, row=2)
password_check_label = Label(text="Password:", bg="#282120", fg="#D4483B")
password_check_label.grid(column=0, row=3)
space1 = Label(text=" ", bg="#282120")
space1.grid(column=1, row=1)

username_check_input = Entry(width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
username_check_input.grid(column=1, row=2)
username_check_input.focus()
password_check_input = Entry(width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B", show="*")
password_check_input.grid(column=1, row=3)
space2 = Label(text=" ", bg="#282120")
space2.grid(column=0, row=4)
enter_button = Button(text="Enter", width=7, bg="#282120", fg="#D4483B", command=validate)
enter_button.grid(column=1, row=5, columnspan=2)


while username_check_input.get() == "username" and password_check_input.get() == "password":

    window = Tk()
    window.title("Password Generator")
    window.config(padx=50, pady=50, bg="#282120")

    # canvas = Canvas(width=200, height=200, bg="#282120", highlightthickness=0)
    # logo_image = PhotoImage(file="logo.png")
    # canvas.create_image(100, 100, image=logo_image)
    # canvas.grid(column=1, row=0)

    # Labels
    website_label = Label(text="Website:", bg="#282120", fg="#D4483B")
    website_label.grid(column=0, row=2)
    email_label = Label(text="Email / Username:", bg="#282120", fg="#D4483B")
    email_label.grid(column=0, row=3)
    password_label = Label(text="Password:", bg="#282120", fg="#D4483B")
    password_label.grid(column=0, row=4)
    line_label1 = Label(text=" ", bg="#282120")
    line_label1.grid(column=1, row=1)
    line_label2 = Label(text=" ", bg="#282120")
    line_label2.grid(column=1, row=5)

    # Entries
    website_input = Entry(width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
    website_input.grid(column=1, row=2)
    website_input.focus()
    email_input = Entry(width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
    email_input.grid(column=1, row=3)
    # email_input.insert(0, "[email protected]")
    password_input = Entry(width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
    password_input.grid(column=1, row=4)

    # Buttons
    generate_password_button = Button(text="Generate Password", bg="#282120", fg="#D4483B", command=generate_password)
    generate_password_button.grid(column=2, row=4)

    add_password = Button(text="Add", width=45, bg="#282120", fg="#D4483B", command=save)
    add_password.grid(column=1, row=6, columnspan=2)

    search = Button(text="Search", width=14, bg="#282120", fg="#D4483B", command=find_password)
    search.grid(column=2, row=2)

    window.mainloop()



password_checker_window.mainloop()

Upvotes: 0

Views: 414

Answers (1)

Henry
Henry

Reputation: 3942

You could hide the login window, add password_checker_window.destroy() and put all the manager stuff in a function, then call it once the login has been validated, but this then creates another problem. The variables for the password manager are now local variables, so they can't be accessed from the functions without lots of globals.
To resolve this, I've reorganised your program into two classes. The functions have been organised into their relevant classes and can now access the variables. To learn more about classes and tkinter, search for "OOP tkinter" (it makes big programs a lot easier to work with).
I also fixed a small bug with the password generator where the old password would not be removed before inserting a new one and added in parents for all of your widgets.

Whilst this now all works, I would look at some of the security measures mentioned in Serge Ballesta's comment, as your password manager is very insecure at the moment.

# Class for login window
class loginWindow(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.title("Login to the password database")
        self.config(padx=50, pady=50, width=500, height=350, bg="#282120")

        # canvas = Canvas(self, width=200, height=200, bg="#282120", highlightthickness=0)
        # logo_image = PhotoImage(file="logo.png")
        # canvas.create_image(100, 100, image=logo_image)
        # canvas.grid(column=1, row=0)

        self.username_check_label = Label(self, text="Username:", bg="#282120", fg="#D4483B")
        self.username_check_label.grid(column=0, row=2)
        self.password_check_label = Label(self, text="Password:", bg="#282120", fg="#D4483B")
        self.password_check_label.grid(column=0, row=3)
        self.space1 = Label(self, text=" ", bg="#282120")
        self.space1.grid(column=1, row=1)

        self.username_check_input = Entry(self, width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
        self.username_check_input.grid(column=1, row=2)
        self.username_check_input.focus()
        self.password_check_input = Entry(self, width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B", show="*")
        self.password_check_input.grid(column=1, row=3)
        self.space2 = Label(self, text=" ", bg="#282120")
        self.space2.grid(column=0, row=4)
        self.enter_button = Button(self, text="Enter", width=7, bg="#282120", fg="#D4483B", command=self.validate)
        self.enter_button.grid(column=1, row=5, columnspan=2)

    def validate(self):
        username = self.username_check_input.get()
        password = self.password_check_input.get()
        if username == "username" and password == "password":
            self.destroy()
            global load_manager
            load_manager()
        else:
            messagebox.showwarning(title="Error", message="Wrong password, try again!")
            self.username_check_input.delete(0, END)
            self.password_check_input.delete(0, END)

#This function loads the password manager after logging in.
def load_manager():
    app = managerWindow()
    app.mainloop()

# Class for managerWindow
class managerWindow(Tk):
    def __init__(self):
        Tk.__init__(self)
        self.title("Password Generator")
        self.config(padx=50, pady=50, bg="#282120")

        # self.canvas = Canvas(self, width=200, height=200, bg="#282120", highlightthickness=0)
        # self.logo_image = PhotoImage(file="logo.png")
        # self.canvas.create_image(100, 100, image=logo_image)
        # self.canvas.grid(column=1, row=0)

        # Labels
        self.website_label = Label(self, text="Website:", bg="#282120", fg="#D4483B")
        self.website_label.grid(column=0, row=2)
        self.email_label = Label(self, text="Email / Username:", bg="#282120", fg="#D4483B")
        self.email_label.grid(column=0, row=3)
        self.password_label = Label(self, text="Password:", bg="#282120", fg="#D4483B")
        self.password_label.grid(column=0, row=4)
        self.line_label1 = Label(self, text=" ", bg="#282120")
        self.line_label1.grid(column=1, row=1)
        self.line_label2 = Label(self, text=" ", bg="#282120")
        self.line_label2.grid(column=1, row=5)

        # Entries
        self.website_input = Entry(self, width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
        self.website_input.grid(column=1, row=2)
        self.website_input.focus()
        self.email_input = Entry(self, width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
        self.email_input.grid(column=1, row=3)
        # self.email_input.insert(0, "[email protected]")
        self.password_input = Entry(self, width=32, bg="#282120", fg="#D4483B", insertbackground="#D4483B")
        self.password_input.grid(column=1, row=4)

        # Buttons
        self.generate_password_button = Button(self, text="Generate Password", bg="#282120", fg="#D4483B", command=self.generate_password)
        self.generate_password_button.grid(column=2, row=4)

        self.add_password = Button(self, text="Add", width=45, bg="#282120", fg="#D4483B", command=self.save)
        self.add_password.grid(column=1, row=6, columnspan=2)

        self.search = Button(self, text="Search", width=14, bg="#282120", fg="#D4483B", command=self.find_password)
        self.search.grid(column=2, row=2)
    def generate_password(self):
        letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
        numbers = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        symbols = ['!', '#', '$', '%', '&', '(', ')', '*', '+']

        nr_letters = random.randint(8, 10)
        nr_symbols = random.randint(2, 4)
        nr_numbers = random.randint(2, 4)

        password_list = []


        password_letters = [random.choice(letters) for _ in range(nr_letters)]

        password_symbols = [random.choice(symbols) for _ in range(nr_symbols)]

        password_numbers = [random.choice(numbers) for _ in range(nr_numbers)]
        password_list = password_letters + password_symbols + password_numbers
        random.shuffle(password_list)


        password = "".join(password_list)
        self.password_input.delete(0,"end") #Clear the password input before inserting
        self.password_input.insert(0, password)
        pyperclip.copy(password)
    def save(self):
        website = self.website_input.get()
        email = self.email_input.get()
        password = self.password_input.get()

        new_data = {

            website: {
                "email": email,
                "password": password,

            }

                    }

        if len(website) == 0 or len(email) == 0 or len(password) == 0:
            messagebox.showinfo(title="Oops", message="Please don't leave any fields empty!")

        else:
            try:
                with open("data.json", "r") as file:

                    # Reading old data
                    data = json.load(file)

            except FileNotFoundError:
                with open("data.json", "w") as file:
                    # Updating old data with new data
                    json.dump(new_data, file, indent=4)
            else:
                data.update(new_data)

                with open("data.json", "w") as file:
                    # Saving updated data
                    json.dump(data, file, indent=4)
            finally:
                self.website_input.delete(0, END)
                self.email_input.delete(0, END)
                self.password_input.delete(0, END)
                self.website_input.focus()
    def find_password(self):
        website = self.website_input.get()
        try:
            with open("data.json") as file:
                data = json.load(file)

        except FileNotFoundError:
            messagebox.showinfo(title="Error", message="No data file found!")

        else:
            if website in data:
                email = data[website]["email"]
                password = data[website]["password"]
                messagebox.showinfo(title=website,message=f"Email: {email}\n\nPassword: {password}")
            else:
                messagebox.showinfo(title="Error", message=f"No details for {website} exists!")
app = loginWindow()
app.mainloop()

Upvotes: 1

Related Questions