continue development
This commit is contained in:
2
api.yml
2
api.yml
@@ -135,7 +135,7 @@ paths:
|
|||||||
'404':
|
'404':
|
||||||
description: client_id not found
|
description: client_id not found
|
||||||
/Client:
|
/Client:
|
||||||
put:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- client
|
- client
|
||||||
summary: Update an existing client
|
summary: Update an existing client
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -57,9 +57,6 @@ def display_account_info(account_id):
|
|||||||
label_key.grid(row=0, column=i*2, sticky='w', padx=10)
|
label_key.grid(row=0, column=i*2, sticky='w', padx=10)
|
||||||
label_value.grid(row=0, column=i*2+1, sticky='w', padx=10)
|
label_value.grid(row=0, column=i*2+1, sticky='w', padx=10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### Layout ###
|
### Layout ###
|
||||||
##############
|
##############
|
||||||
@@ -87,6 +84,16 @@ display_account_info(account_id)
|
|||||||
table_frame = customtkinter.CTkFrame(root)
|
table_frame = customtkinter.CTkFrame(root)
|
||||||
table_frame.pack(fill=tk.BOTH, expand=True)
|
table_frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
# Add buttons for adding a new transaction, requesting the OTP, and editing the account details
|
||||||
|
button_frame = customtkinter.CTkFrame(root)
|
||||||
|
button_frame.pack(fill=tk.X, pady=10)
|
||||||
|
add_transaction_button = customtkinter.CTkButton(button_frame, text="Add Transaction", command=add_transaction)
|
||||||
|
add_transaction_button.grid(row=0, column=0, padx=10)
|
||||||
|
request_otp_button = customtkinter.CTkButton(button_frame, text="Request OTP", command=request_otp)
|
||||||
|
request_otp_button.grid(row=0, column=1, padx=10)
|
||||||
|
edit_account_details_button = customtkinter.CTkButton(button_frame, text="Edit Account Details", command=edit_account_details)
|
||||||
|
edit_account_details_button.grid(row=0, column=2, padx=10)
|
||||||
|
|
||||||
# Create the transactions table
|
# Create the transactions table
|
||||||
transactions_table = ttk.Treeview(table_frame, columns=("Transaction ID", "Transaction Type", "Amount", "Timestamp", "Description", "Account ID", "Recipient Account ID"), show="headings")
|
transactions_table = ttk.Treeview(table_frame, columns=("Transaction ID", "Transaction Type", "Amount", "Timestamp", "Description", "Account ID", "Recipient Account ID"), show="headings")
|
||||||
transactions_table.pack(fill=tk.BOTH, expand=True)
|
transactions_table.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ dark_theme = dark
|
|||||||
theme = dark-blue
|
theme = dark-blue
|
||||||
|
|
||||||
[client]
|
[client]
|
||||||
default_id = 31d90aad
|
default_id = d18e5ae0
|
||||||
default_password = Happymeal1
|
default_password = Happymeal1
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import requests
|
|||||||
from requests.models import Response
|
from requests.models import Response
|
||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
import json
|
import json
|
||||||
|
from tkinter import messagebox
|
||||||
|
|
||||||
##############
|
##############
|
||||||
### System ###
|
### System ###
|
||||||
@@ -65,9 +66,14 @@ def update_client(client_id, otp_code, email=None, phone_number=None, address=No
|
|||||||
params['phone_number'] = phone_number
|
params['phone_number'] = phone_number
|
||||||
if address is not None:
|
if address is not None:
|
||||||
params['address'] = address
|
params['address'] = address
|
||||||
response = requests.put(CONFIG["server"]["url"] + "/Client", cookies=session_data['session_cookie'], params=params)
|
response = requests.post(CONFIG["server"]["url"] + "/Client", cookies=session_data['session_cookie'], params=params)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.json()
|
return response.json()
|
||||||
|
except requests.exceptions.HTTPError as e:
|
||||||
|
if response.status_code == 400:
|
||||||
|
return {'success': False, 'message': "Invalid OTP."}
|
||||||
|
print(f"HTTPError: {e}")
|
||||||
|
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
print(f"RequestException: {e}")
|
print(f"RequestException: {e}")
|
||||||
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
|
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
|
||||||
@@ -154,9 +160,11 @@ def generate_otp():
|
|||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
client_id = session_data['client_id']
|
client_id = session_data['client_id']
|
||||||
response = requests.post(CONFIG["server"]["url"] + "/OTP/Generate", cookies=session_data['session_cookie'], params={'client_id': client_id})
|
response = requests.post(f"{CONFIG['server']['url']}/OTP/Generate", cookies=session_data['session_cookie'], params={'client_id': client_id})
|
||||||
|
if response.status_code == 200:
|
||||||
|
messagebox.showinfo("OTP", "OTP has been sent to your email.")
|
||||||
|
else:
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
return response.json()
|
|
||||||
except requests.exceptions.RequestException as e:
|
except requests.exceptions.RequestException as e:
|
||||||
print(f"RequestException: {e}")
|
print(f"RequestException: {e}")
|
||||||
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
|
messagebox.showerror("Error", f"Could not generate OTP: {e}")
|
||||||
@@ -5,6 +5,7 @@ import os
|
|||||||
from config import CONFIG
|
from config import CONFIG
|
||||||
from connection import logout_client, get_client, update_client, get_accounts, format_balance, generate_otp
|
from connection import logout_client, get_client, update_client, get_accounts, format_balance, generate_otp
|
||||||
|
|
||||||
|
|
||||||
# Global variables
|
# Global variables
|
||||||
email_entry = None
|
email_entry = None
|
||||||
phone_entry = None
|
phone_entry = None
|
||||||
@@ -31,6 +32,16 @@ def logout():
|
|||||||
else:
|
else:
|
||||||
messagebox.showerror("Logout failed", json_response['message'])
|
messagebox.showerror("Logout failed", json_response['message'])
|
||||||
|
|
||||||
|
def exit_application():
|
||||||
|
"""Logs out the client and exits the application."""
|
||||||
|
response = logout_client()
|
||||||
|
json_response = response.json()
|
||||||
|
if json_response['success']:
|
||||||
|
messagebox.showinfo("Logout", "You have been logged out.")
|
||||||
|
root.quit()
|
||||||
|
else:
|
||||||
|
messagebox.showerror("Logout failed", json_response['message'])
|
||||||
|
|
||||||
def display_client_info():
|
def display_client_info():
|
||||||
"""Displays the client's information on the dashboard."""
|
"""Displays the client's information on the dashboard."""
|
||||||
global frame
|
global frame
|
||||||
@@ -70,7 +81,7 @@ def edit_details():
|
|||||||
global edit_window, email_entry, phone_entry, address_entry, otp_entry
|
global edit_window, email_entry, phone_entry, address_entry, otp_entry
|
||||||
edit_window = customtkinter.CTkToplevel(root)
|
edit_window = customtkinter.CTkToplevel(root)
|
||||||
edit_window.title("Edit Details")
|
edit_window.title("Edit Details")
|
||||||
edit_window.geometry("300x300")
|
edit_window.geometry("300x350")
|
||||||
edit_window.iconbitmap("application/luxbank.ico")
|
edit_window.iconbitmap("application/luxbank.ico")
|
||||||
edit_window.attributes('-topmost', True)
|
edit_window.attributes('-topmost', True)
|
||||||
|
|
||||||
@@ -89,16 +100,17 @@ def edit_details():
|
|||||||
address_label.pack()
|
address_label.pack()
|
||||||
address_entry.pack()
|
address_entry.pack()
|
||||||
|
|
||||||
# Add MFA verify button and text box
|
customtkinter.CTkLabel(edit_window, text=" ").pack() # Add space under the address box
|
||||||
mfa_button = customtkinter.CTkButton(edit_window, text="Get OTP Code", command=generate_otp)
|
|
||||||
mfa_button.pack()
|
|
||||||
|
|
||||||
mfa_label = customtkinter.CTkLabel(edit_window, text="OTP Code: ")
|
otp_button = customtkinter.CTkButton(edit_window, text="Get OTP Code", command=generate_otp)
|
||||||
|
otp_button.pack()
|
||||||
|
|
||||||
|
otp_label = customtkinter.CTkLabel(edit_window, text="OTP Code: ")
|
||||||
otp_entry = customtkinter.CTkEntry(edit_window)
|
otp_entry = customtkinter.CTkEntry(edit_window)
|
||||||
mfa_label.pack()
|
otp_label.pack()
|
||||||
otp_entry.pack()
|
otp_entry.pack()
|
||||||
|
|
||||||
save_button = customtkinter.CTkButton(edit_window, text="Verify MFA and Save", command=save_details)
|
save_button = customtkinter.CTkButton(edit_window, text="Verify OTP and Save", command=save_details)
|
||||||
save_button.pack()
|
save_button.pack()
|
||||||
edit_window.lift()
|
edit_window.lift()
|
||||||
|
|
||||||
@@ -109,17 +121,32 @@ def save_details():
|
|||||||
new_phone = phone_entry.get() if phone_entry.get() != '' else None
|
new_phone = phone_entry.get() if phone_entry.get() != '' else None
|
||||||
new_address = address_entry.get() if address_entry.get() != '' else None
|
new_address = address_entry.get() if address_entry.get() != '' else None
|
||||||
otp_code = otp_entry.get()
|
otp_code = otp_entry.get()
|
||||||
|
|
||||||
|
if not otp_code:
|
||||||
|
messagebox.showerror("Error", "OTP code must be entered.")
|
||||||
|
return
|
||||||
|
|
||||||
with open('application\\session_data.json', 'r') as f:
|
with open('application\\session_data.json', 'r') as f:
|
||||||
session_data = json.load(f)
|
session_data = json.load(f)
|
||||||
client_id = session_data['client_id']
|
client_id = session_data['client_id']
|
||||||
|
|
||||||
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
|
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
try:
|
||||||
result = update_client(client_id, otp_code, new_email, new_phone, new_address)
|
result = update_client(client_id, otp_code, new_email, new_phone, new_address)
|
||||||
if result['success']:
|
if result['success']:
|
||||||
display_client_info()
|
display_client_info()
|
||||||
|
messagebox.showinfo("Success", "Details updated successfully.")
|
||||||
|
edit_window.destroy()
|
||||||
|
else:
|
||||||
|
if result['message'] == "Invalid OTP.":
|
||||||
|
messagebox.showerror("Error", "MFA details not correct. Please try again.")
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
|
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
|
||||||
edit_window.destroy()
|
except Exception as e:
|
||||||
|
messagebox.showerror("Error", f"An error occurred: {e}")
|
||||||
|
|
||||||
|
|
||||||
def populate_table():
|
def populate_table():
|
||||||
"""Populates the accounts table with client accounts."""
|
"""Populates the accounts table with client accounts."""
|
||||||
@@ -169,13 +196,21 @@ welcome_label.pack(pady=20)
|
|||||||
|
|
||||||
display_client_info()
|
display_client_info()
|
||||||
|
|
||||||
# Create a logout button
|
# Create a frame for buttons
|
||||||
logout_button = customtkinter.CTkButton(root, text="Logout", command=logout)
|
button_frame = customtkinter.CTkFrame(root)
|
||||||
logout_button.pack(pady=15)
|
button_frame.pack(pady=15, side='top')
|
||||||
|
|
||||||
# Create the MFA button
|
# Create the OTP button
|
||||||
mfa_button = customtkinter.CTkButton(root, text="MFA", command=generate_otp)
|
otp_button = customtkinter.CTkButton(button_frame, text="Get OTP Code", command=generate_otp)
|
||||||
mfa_button.pack(pady=15, side='left')
|
otp_button.pack(side='left', padx=5)
|
||||||
|
|
||||||
|
# Create the logout button
|
||||||
|
logout_button = customtkinter.CTkButton(button_frame, text="Logout", command=logout)
|
||||||
|
logout_button.pack(side='left', padx=5)
|
||||||
|
|
||||||
|
# Create the exit button
|
||||||
|
exit_button = customtkinter.CTkButton(button_frame, text="Exit", command=exit_application)
|
||||||
|
exit_button.pack(side='left', padx=5)
|
||||||
|
|
||||||
# Create a frame for the table
|
# Create a frame for the table
|
||||||
table_frame = ttk.Frame(root)
|
table_frame = ttk.Frame(root)
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"session_cookie": {"session": "mMTYW-c_n0BE-l7MENT8A1h2Rg4UUrNRJYl7NvXTcS4"}, "client_id": "31d90aad"}
|
{"session_cookie": {"session": "CjjpiVUxx009emp27lUSxMpJ4Dt1sUi3fV-_VILXFrw"}, "client_id": "d18e5ae0"}
|
||||||
38
emailer.py
38
emailer.py
@@ -1,35 +1,47 @@
|
|||||||
# Lucas Mathews - Fontys Student ID: 5023572
|
import smtplib
|
||||||
# Banking System Emailer
|
import ssl
|
||||||
|
|
||||||
import smtplib, ssl
|
|
||||||
from config import CONFIG # Import Config
|
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
from email.mime.multipart import MIMEMultipart
|
from email.mime.multipart import MIMEMultipart
|
||||||
|
from config import CONFIG
|
||||||
|
|
||||||
context = ssl.create_default_context() # Create a secure SSL context
|
|
||||||
|
|
||||||
email = "l.mathews@student.fontys.nl" # These three lines are for testing purposes
|
class EmailSendingError(Exception):
|
||||||
subject = "Test Email"
|
"""Custom exception raised when an error occurs during email sending."""
|
||||||
body = "This is a test email."
|
def __init__(self, message, original_error=None):
|
||||||
|
super().__init__(message)
|
||||||
|
self.original_error = original_error
|
||||||
|
|
||||||
|
|
||||||
def send_email(receiver_email, subject, body):
|
def send_email(receiver_email, subject, body):
|
||||||
"""Sends an email to the specified receiver email address."""
|
"""Sends an email to the specified receiver email address."""
|
||||||
sender_email = CONFIG["smtp"]["sender_email"]
|
sender_email = CONFIG["smtp"]["sender_email"]
|
||||||
|
|
||||||
message = MIMEMultipart() # Create a multipart message and set headers
|
message = MIMEMultipart()
|
||||||
message["From"] = f"{CONFIG["smtp"]["sender_name"]} <{CONFIG["smtp"]["sender_email"]}>"
|
message["From"] = f"{CONFIG['smtp']['sender_name']} <{sender_email}>"
|
||||||
message["To"] = receiver_email
|
message["To"] = receiver_email
|
||||||
message["Subject"] = subject
|
message["Subject"] = subject
|
||||||
|
|
||||||
message.attach(MIMEText(body, "plain")) # Add body to email
|
message.attach(MIMEText(body, "plain"))
|
||||||
|
|
||||||
text = message.as_string()
|
text = message.as_string()
|
||||||
|
|
||||||
|
context = ssl.create_default_context()
|
||||||
|
try:
|
||||||
with smtplib.SMTP_SSL(CONFIG["smtp"]["host"], CONFIG["smtp"]["port"], context=context) as server:
|
with smtplib.SMTP_SSL(CONFIG["smtp"]["host"], CONFIG["smtp"]["port"], context=context) as server:
|
||||||
server.login(CONFIG["smtp"]["username"], CONFIG["smtp"]["password"])
|
server.login(CONFIG["smtp"]["username"], CONFIG["smtp"]["password"])
|
||||||
server.sendmail(sender_email, receiver_email, text)
|
server.sendmail(sender_email, receiver_email, text)
|
||||||
print(f"Email sent to {receiver_email}.")
|
print(f"Email sent to {receiver_email}.")
|
||||||
server.quit()
|
except Exception as e:
|
||||||
|
error_message = f"Failed to send email to {receiver_email}: {e}"
|
||||||
|
print(error_message)
|
||||||
|
raise EmailSendingError(error_message)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
email = "l.mathews@student.fontys.nl"
|
||||||
|
subject = "Test Email"
|
||||||
|
body = "This is a test email."
|
||||||
|
try:
|
||||||
send_email(email, subject, body)
|
send_email(email, subject, body)
|
||||||
|
except EmailSendingError:
|
||||||
|
print("Email sending failed.")
|
||||||
|
|||||||
53
manager.py
53
manager.py
@@ -4,6 +4,7 @@
|
|||||||
from class_client import Client
|
from class_client import Client
|
||||||
from class_account import Account
|
from class_account import Account
|
||||||
from class_transaction import Transaction
|
from class_transaction import Transaction
|
||||||
|
from emailer import EmailSendingError # Import the EmailSendingError class to handle email sending errors
|
||||||
from flask import jsonify, session as flask_session # Imports the Flask modules
|
from flask import jsonify, session as flask_session # Imports the Flask modules
|
||||||
import hashlib # For password hashing
|
import hashlib # For password hashing
|
||||||
import datetime # For timestamps
|
import datetime # For timestamps
|
||||||
@@ -133,17 +134,27 @@ def admin_required(f):
|
|||||||
return decorated_function
|
return decorated_function
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def generate_otp(client_id:str):
|
def generate_otp(client_id: str):
|
||||||
"""Generates a one time password for a client and sends it to their email address. Returns a success message if the OTP is generated and an error message otherwise."""
|
"""Generates a one-time password for a client and sends it to their email address. Returns a success message if the OTP is generated and an error message otherwise."""
|
||||||
current_client_id, is_admin = get_current_client()
|
current_client_id, is_admin = get_current_client()
|
||||||
if not is_admin and client_id != current_client_id:
|
if not is_admin and client_id != current_client_id:
|
||||||
return format_response(False, "You can only generate OTPs for your own client account."), 403
|
return format_response(False, "You can only generate OTPs for your own client account."), 403
|
||||||
|
|
||||||
email = get_email(client_id)
|
email = get_email(client_id)
|
||||||
if email:
|
if email:
|
||||||
password = int(random.randint(100000, 999999)) # Generate a 6-digit OTP
|
password = int(random.randint(100000, 999999)) # Generate a 6-digit OTP
|
||||||
send_email(email, "Luxbank One Time Password", f"Your one time password is: {password}"), 200
|
try:
|
||||||
|
send_email(email, "Luxbank One Time Password", f"Your one-time password is: {password}")
|
||||||
otps[client_id] = (password, time.time()) # Store the OTP and the current time
|
otps[client_id] = (password, time.time()) # Store the OTP and the current time
|
||||||
return format_response(True, "Client not found."), 404
|
return format_response(True, "OTP generated and sent successfully."), 200
|
||||||
|
except EmailSendingError as e:
|
||||||
|
print(f"Error sending email: {e}")
|
||||||
|
error_message = "Error sending email. Please try again later."
|
||||||
|
if e.original_error:
|
||||||
|
error_message += f" Original error: {str(e.original_error)}"
|
||||||
|
return format_response(False, error_message), 500
|
||||||
|
else:
|
||||||
|
return format_response(False, "Email address not found for the client."), 404
|
||||||
|
|
||||||
|
|
||||||
##############
|
##############
|
||||||
@@ -162,37 +173,25 @@ def get_client(client_id:str):
|
|||||||
return format_response(False, "Client not found."), 404
|
return format_response(False, "Client not found."), 404
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def update_client(client_id:str, otp_code:int, **kwargs):
|
def update_client(client_id: str, otp_code: int, **kwargs):
|
||||||
"""Updates a client in the database. If the client is not found, returns an error message."""
|
"""Updates a client in the database. If the client is not found, returns an error message."""
|
||||||
current_client_id, is_admin = get_current_client()
|
current_client_id, is_admin = get_current_client()
|
||||||
if not verify_otp(current_client_id, otp_code):
|
if not verify_otp(current_client_id, otp_code):
|
||||||
return format_response(False, "Invalid OTP."), 405
|
return format_response(False, "Invalid OTP."), 400 # Changed to 400 Bad Request
|
||||||
if not is_admin and client_id != current_client_id:
|
if not is_admin and client_id != current_client_id:
|
||||||
return format_response(False, "You can only view your own client information."), 403
|
return format_response(False, "You can only view your own client information."), 403
|
||||||
for client in session.query(Client).all():
|
|
||||||
if client.client_id == client_id:
|
client = session.query(Client).filter_by(client_id=client_id).first()
|
||||||
name = kwargs.get("name", None)
|
if client:
|
||||||
birthdate = kwargs.get("birthdate", None)
|
for field in ['name', 'birthdate', 'address', 'phone_number', 'email', 'notes']:
|
||||||
address = kwargs.get("address", None)
|
if field in kwargs and kwargs[field] is not None:
|
||||||
phone_number = kwargs.get("phone_number", None)
|
setattr(client, field, kwargs[field])
|
||||||
email = kwargs.get("email", None)
|
|
||||||
notes = kwargs.get("notes", None)
|
|
||||||
if name:
|
|
||||||
client.name = name
|
|
||||||
if birthdate:
|
|
||||||
client.birthdate = birthdate
|
|
||||||
if address:
|
|
||||||
client.address = address
|
|
||||||
if phone_number:
|
|
||||||
client.phone_number = phone_number
|
|
||||||
if email:
|
|
||||||
client.email = email
|
|
||||||
if notes:
|
|
||||||
client.notes = notes
|
|
||||||
session.commit()
|
session.commit()
|
||||||
return format_response(True, f"client_id: {client_id} has been updated."), 200
|
return format_response(True, f"Client ID: {client_id} has been updated."), 200
|
||||||
|
|
||||||
return format_response(False, "Client not found."), 404
|
return format_response(False, "Client not found."), 404
|
||||||
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def change_password(client_id:str, password:str, new_password:str, otp:int):
|
def change_password(client_id:str, password:str, new_password:str, otp:int):
|
||||||
"""Changes the password for a client in the database. If the client is not found, returns an error message."""
|
"""Changes the password for a client in the database. If the client is not found, returns an error message."""
|
||||||
|
|||||||
BIN
test_database.db
BIN
test_database.db
Binary file not shown.
@@ -1,14 +1,7 @@
|
|||||||
# Lucas Mathews - Fontys Student ID: 5023572
|
# Lucas Mathews - Fontys Student ID: 5023572
|
||||||
# Banking System Test Database Generator
|
# Banking System Test Database Generator
|
||||||
|
|
||||||
# This program generates a test database for the banking system. The database contains 50 clients, each with 2 accounts. Each account has 40 transactions.
|
ADMIN_EMAIL = "lmath56@hotmail.com"
|
||||||
# The first client is an administrator. The password for the administrator account is "Happymeal1". The program uses the Faker library to generate fake
|
|
||||||
# data for the clients, accounts, and transactions. The random library is used to generate random data for the accounts and transactions. The program
|
|
||||||
# creates a new SQLite database called test_database.db and writes the test data to the database. The client ID of the administrator account and the
|
|
||||||
# password for the administrator account.
|
|
||||||
|
|
||||||
ADMIN_EMAIL = "lmath56@hotmail.com" # Email address of the administrator account
|
|
||||||
|
|
||||||
|
|
||||||
from sqlalchemy import create_engine
|
from sqlalchemy import create_engine
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
@@ -21,95 +14,111 @@ import random
|
|||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import uuid
|
import uuid
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
def generate_hash(): # Creates a hash for a password
|
|
||||||
|
def generate_hash():
|
||||||
seed = str(random.random()).encode('utf-8')
|
seed = str(random.random()).encode('utf-8')
|
||||||
return hashlib.sha512(seed).hexdigest()
|
return hashlib.sha512(seed).hexdigest()
|
||||||
|
|
||||||
def generate_uuid(): # Generates a unique identifier for transactions
|
def generate_uuid():
|
||||||
return str(uuid.uuid4())
|
return str(uuid.uuid4())
|
||||||
|
|
||||||
def generate_uuid_short(): # Generates a short uuid for accounts and clients
|
def generate_uuid_short():
|
||||||
return str(uuid.uuid4())[:8]
|
return str(uuid.uuid4())[:8]
|
||||||
|
|
||||||
def timestamp(): # Returns the current timestamp
|
def current_timestamp():
|
||||||
return (datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
|
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
engine = create_engine('sqlite:///test_database.db')# Create a new engine for the test database
|
def random_date(start, end):
|
||||||
Base.metadata.create_all(engine) # Create all tables in the test database
|
return start + timedelta(seconds=random.randint(0, int((end - start).total_seconds())))
|
||||||
Session = sessionmaker(bind=engine) # Create a new sessionmaker bound to the test engine
|
|
||||||
session = Session() # Create a new session
|
|
||||||
|
|
||||||
fake = Faker() # Create a Faker instance
|
def timestamp_this_year():
|
||||||
|
start = datetime(datetime.now().year, 1, 1)
|
||||||
|
end = datetime(datetime.now().year, 12, 31, 23, 59, 59)
|
||||||
|
return random_date(start, end).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
all_account_ids = [] # List to store all account IDs
|
def timestamp_this_century():
|
||||||
|
start = datetime(2000, 1, 1)
|
||||||
|
end = datetime(2099, 12, 31, 23, 59, 59)
|
||||||
|
return random_date(start, end).strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
for i in range(50): # Generate 50 clients
|
|
||||||
is_administrator = 1 if i == 0 else 0 # Set the first client as an administrator
|
engine = create_engine('sqlite:///test_database.db')
|
||||||
# Set the password hash for the first account so that the password is "Happymeal1"
|
Base.metadata.create_all(engine)
|
||||||
|
Session = sessionmaker(bind=engine)
|
||||||
|
session = Session()
|
||||||
|
|
||||||
|
fake = Faker()
|
||||||
|
all_account_ids = []
|
||||||
|
|
||||||
|
for i in range(50):
|
||||||
|
is_administrator = 1 if i == 0 else 0
|
||||||
password_hash = "7835062ec36ed529fe22cc63baf3ec18d347dacb21c9801da8ba0848cc18efdf1e51717dd5b1240f7556aca3947aa0722452858be6002c1d46b1f1c311b0e9d8" if i == 0 else generate_hash()
|
password_hash = "7835062ec36ed529fe22cc63baf3ec18d347dacb21c9801da8ba0848cc18efdf1e51717dd5b1240f7556aca3947aa0722452858be6002c1d46b1f1c311b0e9d8" if i == 0 else generate_hash()
|
||||||
client_id = generate_uuid_short()
|
client_id = generate_uuid_short()
|
||||||
all_account_ids.append(client_id) # Add the client ID to the list of account IDs
|
|
||||||
client = Client(
|
client = Client(
|
||||||
client_id=client_id,
|
client_id=client_id,
|
||||||
name="ADMIN" if i == 0 else fake.name(),
|
name="ADMIN" if i == 0 else fake.name(),
|
||||||
birthdate="ADMIN" if i == 0 else fake.date_of_birth(minimum_age=18, maximum_age=90),
|
birthdate="ADMIN" if i == 0 else timestamp_this_century(),
|
||||||
opening_timestamp=timestamp() if i == 0 else fake.date_this_century(),
|
opening_timestamp=current_timestamp() if i == 0 else timestamp_this_century(),
|
||||||
address="ADMIN" if i == 0 else fake.address(),
|
address="ADMIN" if i == 0 else fake.address(),
|
||||||
phone_number="ADMIN" if i == 0 else fake.phone_number(),
|
phone_number="ADMIN" if i == 0 else fake.phone_number(),
|
||||||
email=ADMIN_EMAIL if i == 0 else fake.email(),
|
email=ADMIN_EMAIL if i == 0 else fake.email(),
|
||||||
administrator=is_administrator,
|
administrator=is_administrator,
|
||||||
hash=password_hash,
|
hash=password_hash,
|
||||||
notes=fake.text(max_nb_chars=50), # Generate fake notes
|
notes=fake.text(max_nb_chars=50),
|
||||||
enabled=1,
|
enabled=1,
|
||||||
accounts=[]) # Empty list for accounts, you can add accounts later)
|
accounts=[]
|
||||||
|
)
|
||||||
session.add(client)
|
session.add(client)
|
||||||
|
|
||||||
for j in range(2):# Each client has 2 accounts
|
for j in range(2):
|
||||||
account_id = generate_uuid_short()
|
account_id = generate_uuid_short()
|
||||||
balance = 1000 # Initialize balance to 1000
|
balance = 1000
|
||||||
|
|
||||||
for k in range(40): # Each account has 40 transactions
|
|
||||||
if not all_account_ids: # Skip creating a transaction if there are no accounts yet
|
|
||||||
continue
|
|
||||||
|
|
||||||
|
for k in range(40):
|
||||||
transaction_type = random.choice(['Deposit', 'Withdrawal'])
|
transaction_type = random.choice(['Deposit', 'Withdrawal'])
|
||||||
amount = random.randint(1, 200)
|
amount = random.randint(1, 200)
|
||||||
|
|
||||||
if transaction_type == 'Withdrawal' and balance - amount < 0: # Skip withdrawal if it would make balance negative
|
if transaction_type == 'Withdrawal' and balance - amount < 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if transaction_type == 'Deposit': # Update balance based on transaction type
|
if transaction_type == 'Deposit':
|
||||||
balance += amount
|
balance += amount
|
||||||
elif transaction_type == 'Withdrawal':
|
else:
|
||||||
balance -= amount
|
balance -= amount
|
||||||
|
|
||||||
transaction = Transaction(
|
transaction = Transaction(
|
||||||
transaction_id=generate_uuid(),
|
transaction_id=generate_uuid(),
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
recipient_account_id=random.choice(all_account_ids),
|
recipient_account_id=random.choice(all_account_ids) if all_account_ids else account_id,
|
||||||
transaction_type=transaction_type,
|
transaction_type=transaction_type,
|
||||||
amount=amount,
|
amount=amount,
|
||||||
timestamp=fake.date_this_year(),
|
timestamp=timestamp_this_year(),
|
||||||
description=fake.text(max_nb_chars=50)
|
description=fake.text(max_nb_chars=20)
|
||||||
)
|
)
|
||||||
session.add(transaction)
|
session.add(transaction)
|
||||||
|
|
||||||
account = Account(
|
account = Account(
|
||||||
account_id=account_id,
|
account_id=account_id,
|
||||||
client_id=client_id,
|
client_id=client_id,
|
||||||
description=fake.text(max_nb_chars=200),
|
description=fake.text(max_nb_chars=20),
|
||||||
open_timestamp=fake.date_this_century(),
|
open_timestamp=timestamp_this_year(),
|
||||||
account_type=random.choice(['Spending', 'Savings']),
|
account_type=random.choice(['Spending', 'Savings']),
|
||||||
balance=balance, # Set balance to calculated balance
|
balance=balance,
|
||||||
enabled=1,
|
enabled=1,
|
||||||
notes=fake.text(max_nb_chars=50),
|
notes=fake.text(max_nb_chars=50),
|
||||||
transactions=[])
|
transactions=[]
|
||||||
|
)
|
||||||
session.add(account)
|
session.add(account)
|
||||||
all_account_ids.append(account_id)
|
all_account_ids.append(account_id)
|
||||||
|
|
||||||
session.commit() # Commit the session to write the test data to the database
|
session.commit()
|
||||||
|
|
||||||
print(f"The client_id of the administrator account of this test database is: {all_account_ids[0]}. The password is: Happymeal1")
|
# Retrieve the client_id of the administrator account from the session
|
||||||
|
admin_client_id = session.query(Client.client_id).filter(Client.administrator == 1).first()[0]
|
||||||
|
|
||||||
session.close() # Close the session
|
# Print the client_id of the administrator account
|
||||||
|
print(f"The client_id of the administrator account of this test database is: {admin_client_id}. The password is: Happymeal1")
|
||||||
|
|
||||||
|
session.close()
|
||||||
Reference in New Issue
Block a user