Skip to content

Commit

Permalink
Merge pull request #35 from Pranav-JJ/main
Browse files Browse the repository at this point in the history
Added password tags, fixed duplicate emails-password issue
  • Loading branch information
SpreadSheets600 authored Oct 28, 2024
2 parents 9056268 + e46b845 commit 1efe821
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 15 deletions.
45 changes: 34 additions & 11 deletions SRC/DataBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,19 @@ def create_table(self):
website TEXT NOT NULL,
email TEXT NOT NULL,
username TEXT NOT NULL,
password TEXT NOT NULL
password TEXT NOT NULL,
category TEXT NOT NULL
);''')
except sqlite3.Error as e:
raise DatabaseError(f"Database error: {e}")

def save_data(self, website, email, username, password):
def save_data(self, website, email, username, password, category):
if not all([website, email, username, password, category]):
raise ValueError("All fields must be filled.")
try:
with self.conn:
self.conn.execute("INSERT INTO passwords (website, email, username, password) VALUES (?, ?, ?, ?)",
(website, email, username, password))
self.conn.execute("INSERT INTO passwords (website, email, username, password, category) VALUES (?, ?, ?, ?, ?)",
(website, email, username, password, category))
except sqlite3.Error as e:
raise DatabaseError(f"Failed to save data: {e}")

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

def update_password(self, old_data, new_data):
if not all(new_data.values()):
raise ValueError("All fields must be filled.")
try:
with self.conn:
cursor = self.conn.cursor()
cursor.execute(
"""
UPDATE passwords
SET website = ?, email = ?, username = ?, password = ?
SET website = ?, email = ?, username = ?, password = ?, category = ?
WHERE website = ? AND email = ? AND username = ? AND password = ?
""",
(new_data['website'], new_data['email'], new_data['username'], new_data['password'],
old_data[0], old_data[1], old_data[2], old_data[3])
(new_data['website'], new_data['email'], new_data['username'], new_data['password'], new_data['category'],
old_data[0], old_data[1], old_data[2], old_data[3])
)
except sqlite3.Error as e:
raise DatabaseError(f"Failed to update password: {e}")

def search_passwords(self, query):
def search_passwords(self, query, category=None):
try:
cursor = self.conn.cursor()
cursor.execute("SELECT website, email, username, password FROM passwords WHERE website LIKE ? OR email LIKE ?",
(f'%{query}%', f'%{query}%'))
if category:
cursor.execute("SELECT website, email, username, password FROM passwords WHERE (website LIKE ? OR email LIKE ?) AND category = ?",
(f'%{query}%', f'%{query}%', category))
else:
cursor.execute("SELECT website, email, username, password FROM passwords WHERE website LIKE ? OR email LIKE ?",
(f'%{query}%', f'%{query}%'))
return cursor.fetchall() or []
except sqlite3.Error as e:
raise DatabaseError(f"Failed to retrieve data: {e}")

def search_passwords_by_categories(self, selected_categories):
try:
cursor = self.conn.cursor()
if not selected_categories:
return []

category_filter = " OR ".join(["category = ?"] * len(selected_categories))
sql_query = f"SELECT website, email, username, password FROM passwords WHERE ({category_filter})"

cursor.execute(sql_query, selected_categories)
results = cursor.fetchall()
return results if results else []
return results if results else []
except sqlite3.Error as e:
raise DatabaseError(f"Failed to retrieve data: {e}")

Expand Down
63 changes: 59 additions & 4 deletions SRC/Main.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ def __init__(self):
)
self.appearance_mode_optionemenu.grid(row=7, column=0, padx=20, pady=(10, 10))

# Define categories
self.categories = ["Work", "Personal", "Entertainment", "Finance", "Health"]

# Add category selection in the password entry form
self.category_vars = {category: ctk.BooleanVar() for category in self.categories}

self.content_frame = ctk.CTkFrame(self)
self.content_frame.grid(row=0, column=1, sticky="nsew", padx=20, pady=20)
self.content_frame.grid_columnconfigure(0, weight=1)
Expand Down Expand Up @@ -210,6 +216,12 @@ def add_password_form(self, pw_data=None):
button_frame = ctk.CTkFrame(form_frame)
button_frame.pack(fill="x", pady=(20, 0))

category_frame = ctk.CTkFrame(self.content_frame)
category_frame.pack(pady=(10, 0))

for category, var in self.category_vars.items():
ctk.CTkCheckBox(category_frame, text=category, variable=var).pack(side="left", padx=5)

if pw_data is None:
ctk.CTkButton(
button_frame, text="Generate Password", command=self.generate_password
Expand Down Expand Up @@ -272,17 +284,31 @@ def generate_password(self):

def save_password(self):
data = {key: widget.get() for key, widget in self.entrywid.items()}

selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]

if not all(data.values()) or not selected_categories:
msgbox.showwarning("Missing Information", "All fields must be filled, and at least one category must be selected.")
return

data['category'] = ', '.join(selected_categories)


if not all(data.values()):
msgbox.showwarning("Missing Information", "All fields must be filled!")

elif not is_valid_email(data['email']):
msgbox.showwarning("Invalid Email", "Invalid email format. Please enter a valid email address.")
elif not is_valid_username(data['username']):
msgbox.showwarning("Invalid Username", "Username can only contain alphanumeric characters, dots, or underscores.")
elif not is_valid_website_url(data['website']):
msgbox.showwarning("Invalid Website URL", "Website URL should be in format https://www.[websitename].[websitedomain]")
else:
existing_passwords = db.get_all_passwords()
for entry in existing_passwords:
if entry[1] == data['email']:
msgbox.showwarning("Duplicate Entry", "This email already exists for this website. Please edit existing email or add another email.")
return

strng = password_strength(data["password"])

for widget in self.content_frame.winfo_children():
Expand Down Expand Up @@ -382,6 +408,15 @@ def search_passwords(self):
side="left"
)

self.categories = ['Work', 'Personal', 'Entertainment', 'Finance', 'Other']
self.category_vars = {category: ctk.BooleanVar() for category in self.categories}
self.category_frame = ctk.CTkFrame(self.content_frame)
self.category_frame.pack(pady=(10, 20))

for category, var in self.category_vars.items():
ctk.CTkCheckBox(self.category_frame, text=category, variable=var).pack(side="left")


self.search_results_frame = ctk.CTkScrollableFrame(self.content_frame)
self.search_results_frame.pack(expand=True, fill="both", padx=20, pady=(0, 20))

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

def perform_search(self):
query = self.search_entry.get()
if not query:
msgbox.showwarning("Warning", "Please Enter A Search Query!")
selected_categories = [category for category, var in self.category_vars.items() if var.get()]

if not query and not selected_categories:
msgbox.showwarning("Warning", "Please enter a search query or select at least one category!")
return

self.search_results = db.search_passwords(query)
if query:
self.search_results = db.search_passwords(query, selected_categories)
else:
self.search_results = db.search_passwords_by_categories(selected_categories)

self.current_page = 0

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

# Get selected categories from checkboxes
selected_categories = [cat for cat, var in self.category_vars.items() if var.get()]

if not all(new_data.values()) or not selected_categories:
msgbox.showwarning("Missing Information", "All fields must be filled, and at least one category must be selected.")
return

new_data['category'] = ', '.join(selected_categories)

if not all(new_data.values()):
msgbox.showwarning("Missing Information", "All fields must be filled!")

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

else:
existing_passwords = db.get_all_passwords()
for entry in existing_passwords:
if entry[0] == new_data['website'] and entry[1] == new_data['email'] and entry != old_data:
msgbox.showwarning("Duplicate Entry", "This email already exists for this website. Please edit the existing entry or use a different email.")
return
try:
db.update_password(old_data, new_data)
self.clear_entries()
Expand Down

0 comments on commit 1efe821

Please sign in to comment.