Password Vault Screen using Tkinter

Programming PASSWORD MANAGER USING TKINTER SERIES Image

    In the last part, we covered the basic authentication part of the application. In this part, we're going to build the Password Vault Screen.
     

    Vault Methods

    There will be a few buttons like Add Password, Update Password, and Delete Password in the password vault screen. These buttons when clicked will call some specific methods. Let's create those methods:

    from tkinter import simpledialog
    from database import init_database
    
    
    class VaultMethods:
    
        def __init__(self):
            self.db, self.cursor = init_database()
    
        def popup_entry(self, heading):
            answer = simpledialog.askstring("Enter details", heading)
            return answer
    
        def add_password(self, vault_screen):
            platform = self.popup_entry("Platform")
            userid = self.popup_entry("Username/Email")
            password = self.popup_entry("Password")
    
            insert_cmd = """INSERT INTO vault(platform, userid, password) VALUES (?, ?, ?)"""
            self.cursor.execute(insert_cmd, (platform, userid, password))
            self.db.commit()
            vault_screen()
    
        def update_password(self, id, vault_screen):
            password = self.popup_entry("Enter New Password")
            self.cursor.execute(
                "UPDATE vault SET password = ? WHERE id = ?", (password, id))
            self.db.commit()
            vault_screen()
    
        def remove_password(self, id, vault_screen):
            self.cursor.execute("DELETE FROM vault WHERE id = ?", (id,))
            self.db.commit()
            vault_screen()
    

    In the above script, we are using simpledialog to create popups. Whenever any of the buttons will be clicked, the user will see a popup asking for some information. We have created a VaultMethod class in which we'll have all the methods. In the constructor, we are getting the db and cursor objects. 

    The first method is called popup_entry(). We have created this method as a shortcut to create popups. This method takes a heading as an argument. We're using askstring method for creating the popup. We then return the value entered in the popup input field.

    The next method is add_password() that takes the vault screen as an argument. Whenever we are adding a new password, we need three details - Platform Name, Username/Email, and Password. So, we need to create three popups for the same. We'll create the popups using the method created above. After we get the three corresponding values from these popups, we add this data into the database using the insert_cmd. We then show the vault_screen() again to the user.

    The next method is update_password() that takes the id(from the database) of the entry and vault screen as the arguments. It then asks for a new password using the popup method. Once we get the value of the new password, we execute another database command to update the password for the id provided. We then show the vault_screen() again to the user. 

    The last method is remove_password() that again takes the id(from the database) of the entry and vault screen as the arguments. In this method, we just delete the entry that matches the id provided. We then show the vault_screen() again to the user. 
     

    3. Password Vault Screen

    This is the main screen of the application where users will be able to add new passwords, modify previously saved passwords, delete passwords and copy passwords. 

    def password_vault_screen(self):
        for widget in self.window.winfo_children():
            widget.destroy()
    
        vault_methods = VaultMethods()
    
        self.window.geometry("850x350")
        main_frame = Frame(self.window)
        main_frame.pack(fill=BOTH, expand=1)
    
        main_canvas = Canvas(main_frame)
        main_canvas.pack(side=LEFT, fill=BOTH, expand=1)
    
        main_scrollbar = Scrollbar(main_frame, orient=VERTICAL, command=main_canvas.yview)
        main_scrollbar.pack(side=RIGHT, fill=Y)
    
        main_canvas.configure(yscrollcommand=main_scrollbar.set)
        main_canvas.bind('<Configure>', lambda e: main_canvas.configure(
                scrollregion=main_canvas.bbox("all")))
    
        second_frame = Frame(main_canvas)
        main_canvas.create_window((0, 0), window=second_frame, anchor="nw")
    
        generate_password_btn = Button(second_frame, text="Generate Password",
                                           command=PasswordGenerator)
        generate_password_btn.grid(row=1, column=2, pady=10)
    
        add_password_btn = Button(
                second_frame, text="Add New Password", command=partial(vault_methods.add_password, self.password_vault_screen))
        add_password_btn.grid(row=1, column=3, pady=10)
    
        lbl = Label(second_frame, text="Platform")
        lbl.grid(row=2, column=0, padx=40, pady=10)
        lbl = Label(second_frame, text="Email/Username")
        lbl.grid(row=2, column=1, padx=40, pady=10)
        lbl = Label(second_frame, text="Password")
        lbl.grid(row=2, column=2, padx=40, pady=10)
    
        self.cursor.execute("SELECT * FROM vault")
    
        if self.cursor.fetchall():
            i = 0
            while True:
                self.cursor.execute("SELECT * FROM vault")
                array = self.cursor.fetchall()
    
                platform_label = Label(second_frame, text=(array[i][1]))
                platform_label.grid(column=0, row=i + 3)
    
                account_label = Label(second_frame, text=(array[i][2]))
                account_label.grid(column=1, row=i + 3)
    
                password_label = Label(second_frame, text=(array[i][3]))
                password_label.grid(column=2, row=i + 3)
    
                copy_btn = Button(second_frame, text="Copy Password",
                                      command=partial(self.copy_text, array[i][3]))
                copy_btn.grid(column=3, row=i + 3, pady=10, padx=10)
                update_btn = Button(second_frame, text="Update Password",
                                        command=partial(vault_methods.update_password, array[i][0], self.password_vault_screen))
                update_btn.grid(column=4, row=i + 3, pady=10, padx=10)
                remove_btn = Button(second_frame, text="Delete Password",
                                        command=partial(vault_methods.remove_password, array[i][0], self.password_vault_screen))
                remove_btn.grid(column=5, row=i + 3, pady=10, padx=10)
    
                i += 1
    
                self.cursor.execute("SELECT * FROM vault")
                if len(self.cursor.fetchall()) <= i:
                    break

    In the above script, first, we destroy all the other opened widgets(if any). We then create a vault_method object of the VaultMethod class. We are then creating a frame and canvas inside that frame. Further, we are creating a scrollbar which we might need if we have too many passwords. 

    Next, we are creating another frame where we'll put our buttons and data. In the first row, we'll have two buttons - Generate Password and Add Password. Generate Password button, when clicked, will call the password generator that we had built in the first part of the series. The Add New Password button will call the add_password() method from the VaultMethod class. 

    Next in the second row, we'll have three labels - Platform, Email/Username, and Password. After this, we have to render the data from the database in the upcoming rows. So, we need to fetch all the data. We are using a while loop and an iterator i. All the data is stored in a variable called array. The array will look like this:

    [(1, 'Facebook', 'ashutosh', '3ftF%IkoQJ'), (2, 'Gmail', 'ashutosh', '[email protected]')]

    If you notice, the array is a list of tuples. Each tuple has four elements - id, Platform Name, Username/Email, and Password

    Now, within the loop, we are creating corresponding labels for each of them. The first column, i.e., the platform name will be given by array[i][1]. Similarly, the second column is the username/email field given by array[i][2] and the third column is the password field given by array[i][3]. The rows will be changing accordingly for each iteration. Since the first data should be placed in the third row, it can be written as row=i+3, where i=0 for the first iteration. Also for each column, we have three buttons - Copy Password, Update Password, and Delete Password. These buttons will be placed in the same rows, but the value of columns will be 3, 4, and 5 respectively. These buttons will call their methods as defined in the VaultMethod class. After we are done with one row, we increment the value of i by 1 to move to the next row. 

    If the number of data from the database is less than or equal to the value of i, we break the loop immediately. 
     

    Demo


     

    Conclusion

    This was the final blog of this series. You can further add more features to this application such as Forgot Master Password. This application can be converted to an executable application that can be run on any machine whether Python is installed there or not. Hope you loved this series!

    Github Repository - https://github.com/ashutoshkrris/Password-Manager-using-Tkinter

     

    0 Comments

    To add a comment, please Signup or Login