Beginning adding OTP verification to client shange screen

This commit is contained in:
Lucas Mathews
2024-05-28 17:49:31 +02:00
parent 5d44aef65f
commit 870dd1435f
33 changed files with 72 additions and 29 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

15
api.yml
View File

@@ -112,7 +112,7 @@ paths:
'404':
description: client_id not found
/OTP/Generate:
get:
post:
tags:
- auth
summary: Generate OTP
@@ -148,6 +148,13 @@ paths:
required: true
schema:
type: string
- name: otp_code
in: query
description: OTP to verify
required: true
schema:
type: integer
format: int32
- name: name
in: query
description: Client Name
@@ -187,8 +194,12 @@ paths:
responses:
'200':
description: Successful operation
'400':
'404':
description: Invalid Client ID supplied
'403':
description: Unauthorised
'405':
description: OTP not valid
get:
tags:
- client

Binary file not shown.

Binary file not shown.

View File

@@ -53,12 +53,12 @@ def get_client(client_id):
print(f"RequestException: {e}")
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
def update_client(client_id, email=None, phone_number=None, address=None):
def update_client(client_id, otp_code, email=None, phone_number=None, address=None):
"""Updates the client details for the given client_id."""
try:
with open('application\\session_data.json', 'r') as f:
session_data = json.load(f)
params = {'client_id': client_id}
params = {'client_id': client_id, 'otp_code': otp_code}
if email is not None:
params['email'] = email
if phone_number is not None:
@@ -147,3 +147,16 @@ def new_transaction(account):
except requests.exceptions.RequestException as e:
print(f"RequestException: {e}")
return {'success': False, 'message': "Could not connect to the server. Please try again later."}
def generate_otp():
"""Generates a new OTP for the current client, which is sent by Email."""
try:
with open('application\\session_data.json', 'r') as f:
session_data = json.load(f)
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.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"RequestException: {e}")
return {'success': False, 'message': "Could not connect to the server. Please try again later."}

View File

@@ -3,12 +3,13 @@ import customtkinter
import json
import os
from config import CONFIG
from connection import logout_client, get_client, update_client, get_accounts, format_balance
from connection import logout_client, get_client, update_client, get_accounts, format_balance, generate_otp
# Global variables
email_entry = None
phone_entry = None
address_entry = None
otp_entry = None
frame = None
#################
@@ -66,10 +67,11 @@ def display_client_info():
def edit_details():
"""Opens a new window for editing client details."""
global edit_window, email_entry, phone_entry, address_entry
global edit_window, email_entry, phone_entry, address_entry, otp_entry
edit_window = customtkinter.CTkToplevel(root)
edit_window.title("Edit Details")
edit_window.geometry("300x200")
edit_window.geometry("300x300")
edit_window.iconbitmap("application/luxbank.ico")
edit_window.attributes('-topmost', True)
email_label = customtkinter.CTkLabel(edit_window, text="Email: ")
@@ -87,31 +89,38 @@ def edit_details():
address_label.pack()
address_entry.pack()
save_button = customtkinter.CTkButton(edit_window, text="Save", command=save_details)
# Add MFA verify button and text 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_entry = customtkinter.CTkEntry(edit_window)
mfa_label.pack()
otp_entry.pack()
save_button = customtkinter.CTkButton(edit_window, text="Verify MFA and Save", command=save_details)
save_button.pack()
edit_window.lift()
def save_details():
"""Saves the updated client details."""
global edit_window, email_entry, phone_entry, address_entry
global edit_window, otp_entry, email_entry, phone_entry, address_entry
new_email = email_entry.get() if email_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
try:
with open('application\\session_data.json', 'r') as f:
session_data = json.load(f)
client_id = session_data['client_id']
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
return
result = update_client(client_id, new_email, new_phone, new_address)
if result['success']:
display_client_info()
else:
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
edit_window.destroy()
except Exception as e:
messagebox.showerror("Error", f"Could not update details: {e}")
otp_code = otp_entry.get()
with open('application\\session_data.json', 'r') as f:
session_data = json.load(f)
client_id = session_data['client_id']
if not messagebox.askyesno("Confirmation", "Are you sure you want to update the details?"):
return
result = update_client(client_id, otp_code, new_email, new_phone, new_address)
if result['success']:
display_client_info()
else:
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
edit_window.destroy()
def populate_table():
"""Populates the accounts table with client accounts."""
try:
@@ -160,9 +169,14 @@ welcome_label.pack(pady=20)
display_client_info()
# Create a logout button
logout_button = customtkinter.CTkButton(root, text="Logout", command=logout)
logout_button.pack(pady=15)
# Create the MFA button
mfa_button = customtkinter.CTkButton(root, text="MFA", command=generate_otp)
mfa_button.pack(pady=15, side='left')
# Create a frame for the table
table_frame = ttk.Frame(root)
table_frame.pack(side='right', fill='both', expand=True)

View File

@@ -53,10 +53,13 @@ def change_dark_theme():
##############
# Set appearance mode based on configuration
if CONFIG["preferences"]["dark_theme"] == "dark":
customtkinter.set_appearance_mode("dark")
if "preferences" in CONFIG and "dark_theme" in CONFIG["preferences"]:
if CONFIG["preferences"]["dark_theme"] == "dark":
customtkinter.set_appearance_mode("dark")
else:
customtkinter.set_appearance_mode("light")
else:
customtkinter.set_appearance_mode("light")
customtkinter.set_appearance_mode("dark")
# Initialize the main window
root = customtkinter.CTk()

View File

@@ -1 +1 @@
{"session_cookie": {"session": "UHtXXDwzE9iVXmMpFHD9BYA-ztYORiBP-xfRImGQDJQ"}, "client_id": "31d90aad"}
{"session_cookie": {"session": "mMTYW-c_n0BE-l7MENT8A1h2Rg4UUrNRJYl7NvXTcS4"}, "client_id": "31d90aad"}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -162,9 +162,11 @@ def get_client(client_id:str):
return format_response(False, "Client not found."), 404
@login_required
def update_client(client_id:str, **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."""
current_client_id, is_admin = get_current_client()
if not verify_otp(current_client_id, otp_code):
return format_response(False, "Invalid OTP."), 405
if not is_admin and client_id != current_client_id:
return format_response(False, "You can only view your own client information."), 403
for client in session.query(Client).all():

Binary file not shown.