Skip to content

Commit 1efe821

Browse files
Merge pull request #35 from Pranav-JJ/main
Added password tags, fixed duplicate emails-password issue
2 parents 9056268 + e46b845 commit 1efe821

File tree

2 files changed

+93
-15
lines changed

2 files changed

+93
-15
lines changed

SRC/DataBase.py

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,19 @@ def create_table(self):
1414
website TEXT NOT NULL,
1515
email TEXT NOT NULL,
1616
username TEXT NOT NULL,
17-
password TEXT NOT NULL
17+
password TEXT NOT NULL,
18+
category TEXT NOT NULL
1819
);''')
1920
except sqlite3.Error as e:
2021
raise DatabaseError(f"Database error: {e}")
2122

22-
def save_data(self, website, email, username, password):
23+
def save_data(self, website, email, username, password, category):
24+
if not all([website, email, username, password, category]):
25+
raise ValueError("All fields must be filled.")
2326
try:
2427
with self.conn:
25-
self.conn.execute("INSERT INTO passwords (website, email, username, password) VALUES (?, ?, ?, ?)",
26-
(website, email, username, password))
28+
self.conn.execute("INSERT INTO passwords (website, email, username, password, category) VALUES (?, ?, ?, ?, ?)",
29+
(website, email, username, password, category))
2730
except sqlite3.Error as e:
2831
raise DatabaseError(f"Failed to save data: {e}")
2932

@@ -38,28 +41,48 @@ def get_all_passwords(self):
3841
raise DatabaseError(f"Failed to retrieve data: {e}")
3942

4043
def update_password(self, old_data, new_data):
44+
if not all(new_data.values()):
45+
raise ValueError("All fields must be filled.")
4146
try:
4247
with self.conn:
4348
cursor = self.conn.cursor()
4449
cursor.execute(
4550
"""
4651
UPDATE passwords
47-
SET website = ?, email = ?, username = ?, password = ?
52+
SET website = ?, email = ?, username = ?, password = ?, category = ?
4853
WHERE website = ? AND email = ? AND username = ? AND password = ?
4954
""",
50-
(new_data['website'], new_data['email'], new_data['username'], new_data['password'],
51-
old_data[0], old_data[1], old_data[2], old_data[3])
55+
(new_data['website'], new_data['email'], new_data['username'], new_data['password'], new_data['category'],
56+
old_data[0], old_data[1], old_data[2], old_data[3])
5257
)
5358
except sqlite3.Error as e:
5459
raise DatabaseError(f"Failed to update password: {e}")
5560

56-
def search_passwords(self, query):
61+
def search_passwords(self, query, category=None):
5762
try:
5863
cursor = self.conn.cursor()
59-
cursor.execute("SELECT website, email, username, password FROM passwords WHERE website LIKE ? OR email LIKE ?",
60-
(f'%{query}%', f'%{query}%'))
64+
if category:
65+
cursor.execute("SELECT website, email, username, password FROM passwords WHERE (website LIKE ? OR email LIKE ?) AND category = ?",
66+
(f'%{query}%', f'%{query}%', category))
67+
else:
68+
cursor.execute("SELECT website, email, username, password FROM passwords WHERE website LIKE ? OR email LIKE ?",
69+
(f'%{query}%', f'%{query}%'))
70+
return cursor.fetchall() or []
71+
except sqlite3.Error as e:
72+
raise DatabaseError(f"Failed to retrieve data: {e}")
73+
74+
def search_passwords_by_categories(self, selected_categories):
75+
try:
76+
cursor = self.conn.cursor()
77+
if not selected_categories:
78+
return []
79+
80+
category_filter = " OR ".join(["category = ?"] * len(selected_categories))
81+
sql_query = f"SELECT website, email, username, password FROM passwords WHERE ({category_filter})"
82+
83+
cursor.execute(sql_query, selected_categories)
6184
results = cursor.fetchall()
62-
return results if results else []
85+
return results if results else []
6386
except sqlite3.Error as e:
6487
raise DatabaseError(f"Failed to retrieve data: {e}")
6588

SRC/Main.py

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,12 @@ def __init__(self):
151151
)
152152
self.appearance_mode_optionemenu.grid(row=7, column=0, padx=20, pady=(10, 10))
153153

154+
# Define categories
155+
self.categories = ["Work", "Personal", "Entertainment", "Finance", "Health"]
156+
157+
# Add category selection in the password entry form
158+
self.category_vars = {category: ctk.BooleanVar() for category in self.categories}
159+
154160
self.content_frame = ctk.CTkFrame(self)
155161
self.content_frame.grid(row=0, column=1, sticky="nsew", padx=20, pady=20)
156162
self.content_frame.grid_columnconfigure(0, weight=1)
@@ -210,6 +216,12 @@ def add_password_form(self, pw_data=None):
210216
button_frame = ctk.CTkFrame(form_frame)
211217
button_frame.pack(fill="x", pady=(20, 0))
212218

219+
category_frame = ctk.CTkFrame(self.content_frame)
220+
category_frame.pack(pady=(10, 0))
221+
222+
for category, var in self.category_vars.items():
223+
ctk.CTkCheckBox(category_frame, text=category, variable=var).pack(side="left", padx=5)
224+
213225
if pw_data is None:
214226
ctk.CTkButton(
215227
button_frame, text="Generate Password", command=self.generate_password
@@ -272,17 +284,31 @@ def generate_password(self):
272284

273285
def save_password(self):
274286
data = {key: widget.get() for key, widget in self.entrywid.items()}
287+
288+
selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]
289+
290+
if not all(data.values()) or not selected_categories:
291+
msgbox.showwarning("Missing Information", "All fields must be filled, and at least one category must be selected.")
292+
return
293+
294+
data['category'] = ', '.join(selected_categories)
295+
275296

276297
if not all(data.values()):
277298
msgbox.showwarning("Missing Information", "All fields must be filled!")
278-
279299
elif not is_valid_email(data['email']):
280300
msgbox.showwarning("Invalid Email", "Invalid email format. Please enter a valid email address.")
281301
elif not is_valid_username(data['username']):
282302
msgbox.showwarning("Invalid Username", "Username can only contain alphanumeric characters, dots, or underscores.")
283303
elif not is_valid_website_url(data['website']):
284304
msgbox.showwarning("Invalid Website URL", "Website URL should be in format https://www.[websitename].[websitedomain]")
285305
else:
306+
existing_passwords = db.get_all_passwords()
307+
for entry in existing_passwords:
308+
if entry[1] == data['email']:
309+
msgbox.showwarning("Duplicate Entry", "This email already exists for this website. Please edit existing email or add another email.")
310+
return
311+
286312
strng = password_strength(data["password"])
287313

288314
for widget in self.content_frame.winfo_children():
@@ -382,6 +408,15 @@ def search_passwords(self):
382408
side="left"
383409
)
384410

411+
self.categories = ['Work', 'Personal', 'Entertainment', 'Finance', 'Other']
412+
self.category_vars = {category: ctk.BooleanVar() for category in self.categories}
413+
self.category_frame = ctk.CTkFrame(self.content_frame)
414+
self.category_frame.pack(pady=(10, 20))
415+
416+
for category, var in self.category_vars.items():
417+
ctk.CTkCheckBox(self.category_frame, text=category, variable=var).pack(side="left")
418+
419+
385420
self.search_results_frame = ctk.CTkScrollableFrame(self.content_frame)
386421
self.search_results_frame.pack(expand=True, fill="both", padx=20, pady=(0, 20))
387422

@@ -390,11 +425,17 @@ def search_passwords(self):
390425

391426
def perform_search(self):
392427
query = self.search_entry.get()
393-
if not query:
394-
msgbox.showwarning("Warning", "Please Enter A Search Query!")
428+
selected_categories = [category for category, var in self.category_vars.items() if var.get()]
429+
430+
if not query and not selected_categories:
431+
msgbox.showwarning("Warning", "Please enter a search query or select at least one category!")
395432
return
396433

397-
self.search_results = db.search_passwords(query)
434+
if query:
435+
self.search_results = db.search_passwords(query, selected_categories)
436+
else:
437+
self.search_results = db.search_passwords_by_categories(selected_categories)
438+
398439
self.current_page = 0
399440

400441
if not self.search_results:
@@ -642,6 +683,15 @@ def edit_password(self, pw_data):
642683
def update_password(self, old_data):
643684
new_data = {key: widget.get() for key, widget in self.entrywid.items()}
644685

686+
# Get selected categories from checkboxes
687+
selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]
688+
689+
if not all(new_data.values()) or not selected_categories:
690+
msgbox.showwarning("Missing Information", "All fields must be filled, and at least one category must be selected.")
691+
return
692+
693+
new_data['category'] = ', '.join(selected_categories)
694+
645695
if not all(new_data.values()):
646696
msgbox.showwarning("Missing Information", "All fields must be filled!")
647697

@@ -653,6 +703,11 @@ def update_password(self, old_data):
653703
msgbox.showwarning("Invalid Website URL", "Website URL should be in format https://www.[websitename].[websitedomain]")
654704

655705
else:
706+
existing_passwords = db.get_all_passwords()
707+
for entry in existing_passwords:
708+
if entry[0] == new_data['website'] and entry[1] == new_data['email'] and entry != old_data:
709+
msgbox.showwarning("Duplicate Entry", "This email already exists for this website. Please edit the existing entry or use a different email.")
710+
return
656711
try:
657712
db.update_password(old_data, new_data)
658713
self.clear_entries()

0 commit comments

Comments
 (0)