Dec-01-2023, 09:01 PM
Altered code. I Commented out the password hash. Added row colors. Admin row will be pink, while others will alternate between a light yellow and light gray. Still not worked on the edit or delete. Maybe when I get home from work in the morning.
# Do the imports import tkinter as tk from tkinter import ttk from random import sample from string import ascii_letters, digits import os import sqlite3 as sq import hashlib from PIL import Image # Get path path = os.path.realpath(os.path.dirname(__file__)) # Characters for random password use characters = ascii_letters+digits+'#&!*' class Data: ''' Class will handle all database interaction ''' def __init__(self): self.connect = sq.connect(f'{path}/resources/PasswordManager/password.db') self.cursor = self.connect.cursor() def create(self): query = ''' create table if not exists users ( id integer primary key, level integer default 5, website text not null, username text not null, password text not null, date default current_timestamp ); ''' self.connect.execute(query) self.connect.commit() # Check if we have any entries. If not create the admin entry query = 'select exists(select 1 from users);' result = self.cursor.execute(query).fetchone() if result[0] == 0: self.insert(level=1,website='None',username='admin',password='admin') def insert(self, level=5, **args): ''' Method for inserting users ''' level = int(level) website = args['website'] username = args['username'] password = args['password'] # Hash password # password = args['password'].encode() # password = hashlib.sha256(password).digest() query = ''' insert into users (level, website, username, password) values (?,?,?,?); ''' self.cursor.execute(query, (level, website, username, password)) self.connect.commit() def getuser(self, username, password): ''' Method for getting single user ''' username = username.strip() password = password.strip() # password = password.encode() # password = hashlib.sha256(password).digest() query = f'select username, level, password from users where username="{username}"' cursor = self.cursor.execute(query).fetchone() if cursor: if cursor[2] == password: return cursor return False def getall(self): ''' Method for getting all users ''' query = 'select * from users' result = self.cursor.execute(query).fetchall() return result class Page(tk.Frame): ''' Base class for pages ''' def __init__(self, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) class LoginForm(Page): ''' Page for the login view ''' def __init__(self, *args, **kwargs): Page.__init__(self, *args, **kwargs) def form(self, parent): self.parent = parent container = tk.Frame(parent) container.grid(column=0, row=2, sticky = 'new', padx=5, pady=5) self.msg = tk.Label(container, anchor='w', padx=5, pady=5) self.msg.grid(column=0, columnspan=2, row=0, sticky='new', padx=(280,5), pady=1) self.msg.grid_forget() label = tk.Label(container, text='Username:') label.grid(column=0, row=1, sticky='new', padx=(275,5), pady=5) self.username = tk.Entry(container) self.username.focus() self.username.grid(column=1, row=1, sticky='new', padx=5, pady=5) label = tk.Label(container, text='Password:') label.grid(column=0, row=2, sticky='new', padx=(275,5), pady=5) self.password = tk.Entry(container, show='*') self.password.grid(column=1, row=2, sticky='new', padx=5, pady=5) btnframe = tk.Frame(container) btnframe.grid(column=0, columnspan=2, row=3, sticky='new', padx=(250,5), pady=5) self.btn = tk.Button(btnframe, text='Login', cursor='hand2') self.btn.grid(column=0, row=0, sticky='new', padx=(150,0), pady=5) self.cancel = tk.Button(btnframe, text='Cancel', cursor='hand2') self.cancel.grid(column=1, row=0, sticky='new', padx=(5,0), pady=5) class MainView(Page): ''' Page for the main view ''' def __init__(self, *args, **kwargs): Page.__init__(self, *args, **kwargs) def view(self, parent): self.container = tk.Frame(parent) self.container.grid(column=0, row=2, sticky='news', padx=5, pady=5) self.container.grid_columnconfigure(0, weight=3) self.container.grid_rowconfigure(0, weight=0) self.container.grid_rowconfigure(1, weight=3) self.msg = tk.Label(self.container, padx=5, pady=5) self.msg.grid(column=0, row=0, sticky='new', padx=5, pady=1) self.msg.grid_forget() contentframe = tk.Frame(self.container) contentframe.grid(column=0, row=1, sticky='news', padx=5, pady=1) contentframe.grid_columnconfigure(0, weight=3) contentframe.grid_rowconfigure(0, weight=3) columns = ('website', 'username', 'password', 'date') # columns = ('id', 'level', 'website', 'username', 'password', 'date') self.tree = ttk.Treeview(contentframe, columns=columns, show='headings', selectmode='browse') for column in columns: self.tree.heading(column, text=column.title()) width = 5 if column in ('id', 'level') else 20 self.tree.column(column, minwidth=5, width=width) self.tree.grid(column=0, row=0, sticky='news', padx=5, pady=5) self.linkframe = tk.Frame(self.container) self.linkframe.grid(column=0, row=2, sticky='new', padx=5, pady=5) for i in range(4): self.linkframe.columnconfigure(i, weight=3, uniform='links') self.add_label = tk.Label(self.linkframe, text='Add', fg='blue', cursor='hand2') self.add_label.grid(column=0, row=0, sticky='new', padx=5, pady=5) self.add_label.bind('<Enter>', lambda event: self.on_enter(self.add_label)) self.add_label.bind('<Leave>', lambda event: self.on_exit(self.add_label)) self.edit_label = tk.Label(self.linkframe, text='Edit', fg='blue', cursor='hand2') self.edit_label.grid(column=1, row=0, sticky='new', padx=5, pady=5) self.edit_label.bind('<Enter>', lambda event: self.on_enter(self.edit_label)) self.edit_label.bind('<Leave>', lambda event: self.on_exit(self.edit_label)) self.delete_label = tk.Label(self.linkframe, text='Delete', fg='blue', cursor='hand2') self.delete_label.grid(column=2, row=0, sticky='new', padx=5, pady=5) self.delete_label.bind('<Enter>', lambda event: self.on_enter(self.delete_label)) self.delete_label.bind('<Leave>', lambda event: self.on_exit(self.delete_label)) self.exit_label = tk.Label(self.linkframe, text='Quit', fg='firebrick', cursor='hand2') self.exit_label.grid(column=3, row=0, sticky='new', padx=5, pady=5) self.exit_label.bind('<Enter>', lambda event: self.on_enter(self.exit_label)) self.exit_label.bind('<Leave>', lambda event: self.on_quit(self.exit_label)) def on_enter(self, link): link['fg'] = 'red' def on_exit(self, link): link['fg'] = 'blue' def on_quit(self, link): link['fg'] = 'firebrick' class DataForm(Page): ''' Page for the data form ''' def __init__(self, *args, **kwargs): Page.__init__(self, *args, **kwargs) def view(self, parent): container = tk.Frame(parent, padx=200) container.grid(column=0, row=2, sticky='news', padx=5, pady=5) container.grid_columnconfigure(0, weight=1) container.grid_columnconfigure(1, weight=3) self.msg = tk.Label(container, anchor='w', padx=5, pady=5) self.msg.grid(column=0, columnspan=2, row=0, sticky='new', padx=5,pady=5) self.msg.grid_forget() label = tk.Label(container, text='Website:', anchor='w') label.grid(column=0, row=1, sticky='new', padx=5, pady=5) self.website = tk.Entry(container) self.website.grid(column=1, row=1, sticky='new', padx=5, pady=5) label = tk.Label(container, text='Username:', anchor='w') label.grid(column=0, row=2, sticky='new', padx=5, pady=5) self.username = tk.Entry(container) self.username.grid(column=1, row=2, sticky='new', padx=5, pady=5) label = tk.Label(container, text='Password:', anchor='w') label.grid(column=0, row=3, sticky='new', padx=5, pady=5) self.password = tk.Entry(container) self.password.grid(column=1, row=3, sticky='new', padx=5, pady=5) self.gen_btn = tk.Button(container, text='Generate Password') self.gen_btn.grid(column=0, row=4, sticky='new', padx=5, pady=5) self.add_btn = tk.Button(container, text='Add Data') self.add_btn.grid(column=1, row=4, sticky='new', padx=5, pady=5) class Window(tk.Frame): ''' Container class ''' def __init__(self, parent, *args, **kwargs): tk.Frame.__init__(self, *args, **kwargs) parent.columnconfigure(0, weight=1) parent.rowconfigure(0, weight=1) parent.geometry('800x600') parent.resizable(False, False) self.parent = parent self.container = tk.Frame(parent) self.container.grid(column=0, row=0, sticky='news') self.container.columnconfigure(0, weight=1) self.container.rowconfigure(1, weight=0) self.container.rowconfigure(2, weight=3) img = f'{path}/resources/PasswordManager/logo2.png' image = tk.PhotoImage(file=img) image.backup = image label = tk.Label(self.container, image=image) label.grid(column=0, row=0, sticky='new', padx=5, pady=5) class Controller: ''' Controller class handles communictaions between all other classes ''' def __init__(self, data, window): self.data = data self.window = window # Create the database table if not exists self.data.create() # Pages self.loginform = LoginForm() self.loginform.form(self.window.container) self.mainview = MainView() self.dataform = DataForm() # Button Commands self.loginform.btn['command'] = self.login self.loginform.cancel['command'] = self.window.parent.destroy # Binds self.window.parent.bind('<Return>', lambda event: self.login()) self.window.parent.bind('<KP_Enter>', lambda event: self.login()) def _mainview(self, msg=None): ''' Method for calling the main view ''' self.mainview.view(self.window.container) self.mainview.add_label.bind('<Button-1>', lambda event: self.addform()) self.mainview.exit_label.bind('<Button-1>', lambda event: self.window.parent.destroy()) if msg: self.mainview.msg.config(text=msg, bg='darkgreen', fg='lime') self.mainview.msg.grid(column=0, row=0, sticky='new', padx=5, pady=1) self.window.parent.after(3000, self._mainview) else: self.mainview.msg.grid_forget() data = self.data.getall() self.mainview.tree.tag_configure('odd', background='#fffeee') self.mainview.tree.tag_configure('even', background='#eeeeef') self.mainview.tree.tag_configure('admin', background='pink') for index, entry in enumerate(data): if entry[3] == 'admin': self.mainview.tree.insert('', index, values=(entry[2], entry[3], entry[4], entry[5]), tags=('admin', )) elif index % 2 == 0: self.mainview.tree.insert('', index, values=(entry[2], entry[3], entry[4], entry[5]), tags=('even', )) else: self.mainview.tree.insert('', index, values=(entry[2], entry[3], entry[4], entry[5]), tags=('odd', )) # self.mainview.tree.insert('', index, values=(entry[0], entry[1], entry[2], entry[3], entry[4], entry[5])) def addform(self): ''' Method for calling the add data form ''' self.dataform.view(self.window.container) self.dataform.gen_btn['command'] = self.gen self.dataform.add_btn['command'] = self.add self.window.parent.bind('<Return>', lambda event: self.add()) self.window.parent.bind('<KP_Enter>', lambda event: self.add()) def gen(self): ''' Method for generating a 10 character password ''' password = ''.join(sample(characters, k=10)) self.dataform.password.delete(0, tk.END) self.dataform.password.insert(0, password) def add(self): ''' Method for adding data to database ''' website = self.dataform.website.get().strip() username = self.dataform.username.get().strip() password = self.dataform.password.get().strip() error = 0 messages = [] self.dataform.msg['fg'] = 'red' if not website: error += 1 messages.append('Website') if not username: error += 1 messages.append('Username') if not password: error += 1 messages.append('Password') if error > 0: msg = 'fields' if error > 1 else 'field' self.dataform.msg.grid(column=0, columnspan=2, row=0, sticky='new', padx=5,pady=5) self.dataform.msg.config(text=f'Required {msg}: {", ".join(messages)}', bg='pink', fg='red') else: self.data.insert(website=website, username=username, password=password) self.mainview.container.destroy() self.mainview.container = tk.Frame(self.window.container) self.mainview.container.grid(column=0, row=2, sticky='news', padx=5, pady=5) self.mainview.container.grid_columnconfigure(0, weight=3) self.mainview.container.grid_rowconfigure(0, weight=3) self._mainview('Successfully added data.') def login(self): username = self.loginform.username.get().strip() password = self.loginform.password.get().strip() if not username or not password: self.loginform.msg.grid(column=0, columnspan=2, row=0, sticky='new', padx=(280,5), pady=1) self.loginform.msg.config(text='All fields are required', fg='red', bg='pink') else: result = self.data.getuser(username, password) if result: self._mainview('You are now logged in.') else: self.loginform.msg.grid(column=0, columnspan=2, row=0, sticky='new', padx=(280,5), pady=1) self.loginform.msg.config(text=' That username and password\ncombination does not exist.', fg='red', bg='pink') if __name__ == '__main__': root = tk.Tk() controller = Controller(Data(), Window(root)) root.mainloop()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags