adds login generator as OOP and MVC

This commit is contained in:
waldek 2022-04-22 12:22:46 +02:00
parent b4b40f1790
commit 1b48d3f0e0
1 changed files with 333 additions and 1 deletions

View File

@ -2760,7 +2760,339 @@ if __name__ == "__main__":
### Improve the login generator
TODO convert the login generator to a class
First the library...
```python
Oimport string
import random
import json
def load_file(filepath):
words = []
with open(filepath, "r") as fp:
data = fp.readlines()
for line in data:
word = line.strip()
words.append(word)
return words
class Login(object):
ADJECTIVES = load_file("adjectives.txt")
ANIMALS = load_file("subjects.txt")
def __init__(self, site=None):
self.site = site
self.generate_password()
self.generate_username()
def __str__(self):
msg = "site: {} - username: {} with password: {}".format(self.site, self.username, self.password)
return msg
def generate_password(self, length=16, complex=False):
if complex:
db = list(string.ascii_letters + string.digits + string.punctuation)
else:
db = list(string.ascii_letters)
password = []
for i in range(0, length):
char = random.choice(db)
password.append(char)
password = "".join(password)
self.password = password
def generate_username(self):
"""generates a random username from a list of animals and adjectives"""
adj = random.choice(self.__class__.ADJECTIVES)
sbj = random.choice(self.__class__.ANIMALS)
username = f"{adj.capitalize()}{sbj.capitalize()}"
self.username = username
def set_password(self, password):
self.password = password
def set_username(self, username):
self.username = username
def verify_password(self, password):
if password == self.password:
return True
return False
def verify_username(self, username):
if username == self.username:
return True
return False
def verify_login(self, username, password):
# if password == self.password and username == self.username:
if self.verify_password(password) and self.verify_username(username):
return True
return False
class Database(object):
def __init__(self, path="db.json"):
self.path = path
self.data = []
def add(self, login):
if isinstance(login, Login):
self.data.append(login)
def get_all(self):
return self.data
def get_by_index(self, index):
if index in range(0, len(self.data)):
return self.data[index]
def save_to_disk(self):
with open(self.path, "w") as fp:
json.dump(self.data, fp , default=vars)
def load_from_disk(self):
with open(self.path, "r") as fp:
data = json.load(fp)
for item in data:
l = Login(item["site"])
l.set_password(item["password"])
l.set_username(item["username"])
self.data.append(l)
if __name__ == "__main__":
db = Database()
db.load_from_disk()
for login in db.data:
print(login)
login.generate_password()
db.save_to_disk()
```
Now the command line interface with a **bad** separation of responsibilities.
```python
from login_lib_OOP import Login, Database
class CommandLineInterface(object):
def __init__(self, db):
self.db = db
def ask_for_int(self, msg):
while True:
result = input(msg)
if result.isdigit():
number = int(result)
break
print("only intergers please...")
return number
def ask_for_bool(self, msg):
while True:
result = input(msg).lower()
if result.startswith("y"):
status = True
break
elif result.startswith("n"):
status = False
break
print("answer with y(es)/n(o) please...")
return status
def ask_for_view(self):
msg = "do you want to view your logins?"
status = self.ask_for_bool(msg)
def ask_for_add_logins(self):
msg = "how many logins do you want to add?"
number = self.ask_for_int(msg)
for i in range(0, number):
l = Login("undefined")
self.db.add(l)
def view_logins(self):
for login in self.db.data:
print("\t{}: {}".format(self.db.data.index(login), login))
def main_menu(self):
actions = ["show logins", "add logins", "save to disk","load from disk", "quit"]
for action in actions:
print("{}: {}".format(actions.index(action), action))
msg = "what do you want to do?"
action = self.ask_for_int(msg)
if action == 0:
self.view_logins()
elif action == 1:
self.ask_for_add_logins()
elif action == 2:
self.db.save_to_disk()
elif action == 3:
self.db.load_from_disk()
elif action == 4:
return False
return True
def run(self):
while True:
status = self.main_menu()
if not status:
break
if __name__ == "__main__":
db = Database()
app = CommandLineInterface(db)
app.run()
```
Now a minimal **MVC** version...
```python
from login_lib_OOP import Login, Database
class Controller(object):
def __init__(self, model):
self.model = model
def set_view(self, view):
self.view = view
def add_multiple_logins(self, number):
for i in range(0, number):
l = Login()
self.model.add(l)
self.view.show_message("added {}".format(l))
def get_all_logins(self):
data = self.model.get_all()
self.view.show_message("there are {} logins in your database".format(len(data)))
for login in data:
msg = "{}: {}".format(data.index(login), login)
self.view.show_data(msg)
def get_one_login(self, index):
login = self.model.get_all()[index]
return login
def load(self):
self.model.load_from_disk()
number = len(self.model.get_all())
self.view.show_message("loaded {} logins from disk".format(number))
def save(self):
self.model.save_to_disk()
number = len(self.model.get_all())
self.view.show_message("saved {} logins to disk".format(number))
class CommandLineInterface(object):
def __init__(self, controller):
self.controller = controller
def ask_for_int(self, msg):
while True:
result = input(msg)
if result.isdigit():
number = int(result)
break
print("only intergers please...")
return number
def ask_for_bool(self, msg):
while True:
result = input(msg).lower()
if result.startswith("y"):
status = True
break
elif result.startswith("n"):
status = False
break
print("answer with y(es)/n(o) please...")
return status
def ask_for_login_index(self):
msg = "which login do you want to modify?"
number = self.ask_for_int(msg)
return number
def show_data(self, msg):
print("\t{}".format(msg))
def show_message(self, msg):
print("MSG: {}".format(msg))
def show_header(self, msg):
print(msg)
print(len(msg) * "-")
def main_menu(self):
self.show_header("main menu:")
actions = ["show logins", "add logins", "save to disk", "load from disk", "modify a login", "quit"]
for action in actions:
print("{}: {}".format(actions.index(action), action))
msg = "what do you want to do?"
action = self.ask_for_int(msg)
if action == 0:
self.controller.get_all_logins()
elif action == 1:
msg = "how many logins do you want?"
number = self.ask_for_int(msg)
self.controller.add_multiple_logins(number)
elif action == 2:
self.controller.save()
elif action == 3:
self.controller.load()
elif action == 4:
self.sub_menu_modify()
elif action == 5:
return False
return True
def sub_menu_modify(self):
self.show_header("modify entry:")
msg = "which login do you want to modify?"
number = self.ask_for_int(msg)
login = self.controller.get_one_login(number)
msg = "do you want to change the site name?"
status = self.ask_for_bool(msg)
if status:
login.site = input("for which site is this login?")
self.show_message("set site to: {}".format(login.site))
msg = "do you want to renew the username?"
status = self.ask_for_bool(msg)
if status:
login.generate_username()
self.show_message("set username to: {}".format(login.username))
msg = "do you want to renew the password?"
status = self.ask_for_bool(msg)
if status:
login.generate_password()
self.show_message("set password to: {}".format(login.password))
msg = "save changes?"
status = self.ask_for_bool(msg)
if status:
self.controller.save()
def run(self):
while True:
status = self.main_menu()
if not status:
break
if __name__ == "__main__":
model = Database()
controller = Controller(model)
view = CommandLineInterface(controller)
controller.set_view(view)
view.run()
```
### Improve the task manager