-
Notifications
You must be signed in to change notification settings - Fork 0
/
generator.py
260 lines (204 loc) · 10.4 KB
/
generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
"""
This module provides classes for the storage module including.
Classes:
- Generator: A GUI class for the password generator.
- EntryFrame: A GUI class for adding new items to the password manager.
Usage:
1. The password generator allows users to generate strong passwords with various options.
2. The entry frame provides a form for users to add new items to the database
"""
import customtkinter as ctk
import random
import string
import pyperclip
from database import DataBase
from encryption import EncryptionManager
class Generator(ctk.CTkToplevel):
"""
Initialize the Password Generator GUI.
Parameters:
- master: The master widget (toplevel frame) for this GUI.
"""
def __init__(self, master):
super().__init__(master)
self.geometry("490x430")
self.resizable(False, False)
self.textbox = ctk.CTkTextbox(self, width=50, height=10)
self.textbox.grid(row=0, column=0, padx=(20, 0), pady=(20, 0), sticky="nsew")
title = "Generated Password:"
self.textbox.insert("1.0", title + "\n")
self.textbox.insert("2.0", "")
self.copy_button = ctk.CTkButton(master=self.textbox, text="Copy",
command=self.copy_to_clipboard)
self.copy_button.grid(row=3, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_slider_frame = ctk.CTkFrame(self)
self.checkbox_slider_frame.grid(row=0, column=1, padx=(20, 20), pady=(20, 0), sticky="nsew")
checkbox_label = ctk.CTkLabel(master=self.checkbox_slider_frame,
text="Password Strength")
checkbox_label.grid(row=0, column=0, padx=(20, 0), pady=(20, 0), columnspan=2)
self.length_slider_label = ctk.CTkLabel(master=self.checkbox_slider_frame,
text="Password Length:")
self.length_slider_label.grid(row=1, column=0, padx=20, pady=(20, 0), sticky="w")
self.length_var = ctk.IntVar()
self.length_slider = ctk.CTkSlider(master=self.checkbox_slider_frame,
from_=8, to=48,
variable=self.length_var,
width=200)
self.length_slider.grid(row=2, column=0, padx=20, pady=(20, 0), sticky="w")
self.length_var.set(8) # Set default value
self.length_display_label = ctk.CTkLabel(master=self.checkbox_slider_frame,
text="Selected Length: 8")
self.length_display_label.grid(row=3, column=0, padx=20, pady=(10, 0), sticky="w")
# update the label when the slider value changes
self.length_slider.bind("<B1-Motion>", lambda event: self.update_length_display())
self.length_slider.bind("<ButtonRelease-1>", lambda event: self.update_length_display())
self.generate_button = ctk.CTkButton(master=self.checkbox_slider_frame,
text="Generate", command=self.generate_new_password)
self.generate_button.grid(row=4, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_1_var = ctk.BooleanVar()
self.checkbox_2_var = ctk.BooleanVar()
self.checkbox_3_var = ctk.BooleanVar()
self.checkbox_4_var = ctk.BooleanVar()
self.checkbox_1 = ctk.CTkCheckBox(master=self.checkbox_slider_frame,
text="Lowercase letters", variable=self.checkbox_1_var)
self.checkbox_1.grid(row=5, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_2 = ctk.CTkCheckBox(master=self.checkbox_slider_frame,
text="Uppercase letters", variable=self.checkbox_2_var)
self.checkbox_2.grid(row=6, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_3 = ctk.CTkCheckBox(master=self.checkbox_slider_frame,
text="Numbers", variable=self.checkbox_3_var)
self.checkbox_3.grid(row=7, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_4 = ctk.CTkCheckBox(master=self.checkbox_slider_frame,
text="Symbols", variable=self.checkbox_4_var)
self.checkbox_4.grid(row=8, column=0, padx=20, pady=(20, 0), sticky="w")
self.checkbox_1_var.set(True)
def generate_password(self, length=8,
use_lowercase=True,
use_uppercase=True,
use_numbers=True,
use_symbols=True):
"""
Generate a random password based on specified parameters.
Parameters:
- length (int): Length of the generated password.
- use_lowercase (bool): Include lowercase letters in the password.
- use_uppercase (bool): Include uppercase letters in the password.
- use_numbers (bool): Include numbers in the password.
- use_symbols (bool): Include symbols in the password.
Returns:
- password(string): The generated password.
"""
characters = ""
password = ""
if use_lowercase:
characters += string.ascii_lowercase
password += random.choice(string.ascii_lowercase)
if use_uppercase:
characters += string.ascii_uppercase
password += random.choice(string.ascii_uppercase)
if use_numbers:
characters += string.digits
password += random.choice(string.digits)
if use_symbols:
characters += string.punctuation
password += random.choice(string.punctuation)
remaining_length = length - len(password)
password += "".join(random.choice(characters) for _ in range(remaining_length))
password_list = list(password)
random.shuffle(password_list)
password = "".join(password_list)
return password
def generate_new_password(self):
"""
Generate and display a new password based on user preferences.
Uses generate_password method.
"""
if not any([self.checkbox_1_var.get(),
self.checkbox_2_var.get(),
self.checkbox_3_var.get(),
self.checkbox_4_var.get()]):
self.textbox.delete("2.0", "end-1c")
self.textbox.insert("2.0", "Please select at least one option.")
else:
try:
use_lowercase = self.checkbox_1_var.get()
use_uppercase = self.checkbox_2_var.get()
use_numbers = self.checkbox_3_var.get()
use_symbols = self.checkbox_4_var.get()
generated_password = self.generate_password(
length=self.length_var.get(),
use_lowercase=use_lowercase,
use_uppercase=use_uppercase,
use_numbers=use_numbers,
use_symbols=use_symbols)
self.textbox.delete("2.0", "end-1c") # Clear the existing generated password
self.textbox.insert("2.0", generated_password)
except IndexError:
pass
def copy_to_clipboard(self):
"""
Copy the password to the clipboard.
"""
password = self.textbox.get("2.0", "end-1c")
pyperclip.copy(password)
def update_length_display(self):
"""
Update the display of the selected password length.
"""
selected_length = self.length_var.get()
self.length_display_label.configure(text=f"Selected Length: {selected_length}")
class EntryFrame(ctk.CTkToplevel):
"""
Initialize the EntryFrame for adding new items inside the user's database
Parameters:
- master: The master(toplevel window) for this EntryFrame.
- refresh_callback: Callback function to refresh the scrollable frame inside Storage module
- user_id: The ID associated with the user_id from the database, obtained during login
"""
def __init__(self, master, refresh_callback, user_id):
super().__init__(master)
self.title("New Entry")
self.resizable(False, False)
self.user_id = user_id
self.name_label = ctk.CTkLabel(self, text="Name:")
self.name_label.grid(row=0, column=0, padx=10, pady=10, sticky="e")
self.name_entry = ctk.CTkEntry(self)
self.name_entry.grid(row=0, column=1, padx=10, pady=10, sticky="e")
self.username_label = ctk.CTkLabel(self, text="Username:")
self.username_label.grid(row=1, column=0, padx=10, pady=10, sticky="e")
self.username_entry = ctk.CTkEntry(self)
self.username_entry.grid(row=1, column=1, padx=10, pady=10, sticky="e")
self.password_label = ctk.CTkLabel(self, text="Password:")
self.password_label.grid(row=2, column=0, padx=10, pady=10, sticky="e")
self.password_entry = ctk.CTkEntry(self, show="*")
self.password_entry.grid(row=2, column=1, padx=10, pady=10, sticky="e")
self.website_label = ctk.CTkLabel(self, text="Website:")
self.website_label.grid(row=3, column=0, padx=10, pady=10, sticky="e")
self.website_entry = ctk.CTkEntry(self)
self.website_entry.grid(row=3, column=1, padx=10, pady=10, sticky="e")
self.save_button = ctk.CTkButton(self, text="Save",
command=lambda: self.save_entry(refresh_callback))
self.save_button.grid(row=4, column=0, columnspan=2, pady=10)
def save_entry(self, refresh_callback):
"""
Save the entry details to the database and refresh the display.
Parameters:
- refresh_callback: Callback function to refresh the display.
"""
if self.user_id is not None:
with DataBase() as db:
encryption_key_tuple = db.storage_retrieve_encryption_key(self.user_id)
encryption_key = encryption_key_tuple[0]
encryption_manager = EncryptionManager(encryption_key)
iv, encrypted_password = encryption_manager.encrypt(self.password_entry.get())
values = (
self.name_entry.get(),
self.username_entry.get(),
encrypted_password,
self.website_entry.get(),
iv,
self.user_id
)
db.generator_save_user_data(values)
#calling create_account_buttons() from storage module to refresh the buttons
refresh_callback()