Beginning adding OTP verification to client shange screen
This commit is contained in:
BIN
__pycache__/class_account.cpython-312.pyc
Normal file
BIN
__pycache__/class_account.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_base.cpython-312.pyc
Normal file
BIN
__pycache__/class_base.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_client.cpython-312.pyc
Normal file
BIN
__pycache__/class_client.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/class_transaction.cpython-312.pyc
Normal file
BIN
__pycache__/class_transaction.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/config.cpython-312.pyc
Normal file
BIN
__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/database.cpython-312.pyc
Normal file
BIN
__pycache__/database.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/emailer.cpython-312.pyc
Normal file
BIN
__pycache__/emailer.cpython-312.pyc
Normal file
Binary file not shown.
BIN
__pycache__/manager.cpython-312.pyc
Normal file
BIN
__pycache__/manager.cpython-312.pyc
Normal file
Binary file not shown.
15
api.yml
15
api.yml
@@ -112,7 +112,7 @@ paths:
|
|||||||
'404':
|
'404':
|
||||||
description: client_id not found
|
description: client_id not found
|
||||||
/OTP/Generate:
|
/OTP/Generate:
|
||||||
get:
|
post:
|
||||||
tags:
|
tags:
|
||||||
- auth
|
- auth
|
||||||
summary: Generate OTP
|
summary: Generate OTP
|
||||||
@@ -148,6 +148,13 @@ paths:
|
|||||||
required: true
|
required: true
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: string
|
||||||
|
- name: otp_code
|
||||||
|
in: query
|
||||||
|
description: OTP to verify
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
- name: name
|
- name: name
|
||||||
in: query
|
in: query
|
||||||
description: Client Name
|
description: Client Name
|
||||||
@@ -187,8 +194,12 @@ paths:
|
|||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Successful operation
|
description: Successful operation
|
||||||
'400':
|
'404':
|
||||||
description: Invalid Client ID supplied
|
description: Invalid Client ID supplied
|
||||||
|
'403':
|
||||||
|
description: Unauthorised
|
||||||
|
'405':
|
||||||
|
description: OTP not valid
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
- client
|
- client
|
||||||
|
|||||||
BIN
application/__pycache__/config.cpython-312.pyc
Normal file
BIN
application/__pycache__/config.cpython-312.pyc
Normal file
Binary file not shown.
BIN
application/__pycache__/connection.cpython-312.pyc
Normal file
BIN
application/__pycache__/connection.cpython-312.pyc
Normal file
Binary file not shown.
@@ -53,12 +53,12 @@ def get_client(client_id):
|
|||||||
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."}
|
||||||
|
|
||||||
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."""
|
"""Updates the client details for the given client_id."""
|
||||||
try:
|
try:
|
||||||
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)
|
||||||
params = {'client_id': client_id}
|
params = {'client_id': client_id, 'otp_code': otp_code}
|
||||||
if email is not None:
|
if email is not None:
|
||||||
params['email'] = email
|
params['email'] = email
|
||||||
if phone_number is not None:
|
if phone_number is not None:
|
||||||
@@ -147,3 +147,16 @@ def new_transaction(account):
|
|||||||
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."}
|
||||||
|
|
||||||
|
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."}
|
||||||
@@ -3,12 +3,13 @@ import customtkinter
|
|||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
from config import CONFIG
|
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
|
# Global variables
|
||||||
email_entry = None
|
email_entry = None
|
||||||
phone_entry = None
|
phone_entry = None
|
||||||
address_entry = None
|
address_entry = None
|
||||||
|
otp_entry = None
|
||||||
frame = None
|
frame = None
|
||||||
|
|
||||||
#################
|
#################
|
||||||
@@ -66,10 +67,11 @@ def display_client_info():
|
|||||||
|
|
||||||
def edit_details():
|
def edit_details():
|
||||||
"""Opens a new window for editing client 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 = customtkinter.CTkToplevel(root)
|
||||||
edit_window.title("Edit Details")
|
edit_window.title("Edit Details")
|
||||||
edit_window.geometry("300x200")
|
edit_window.geometry("300x300")
|
||||||
|
edit_window.iconbitmap("application/luxbank.ico")
|
||||||
edit_window.attributes('-topmost', True)
|
edit_window.attributes('-topmost', True)
|
||||||
|
|
||||||
email_label = customtkinter.CTkLabel(edit_window, text="Email: ")
|
email_label = customtkinter.CTkLabel(edit_window, text="Email: ")
|
||||||
@@ -87,30 +89,37 @@ def edit_details():
|
|||||||
address_label.pack()
|
address_label.pack()
|
||||||
address_entry.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()
|
save_button.pack()
|
||||||
edit_window.lift()
|
edit_window.lift()
|
||||||
|
|
||||||
def save_details():
|
def save_details():
|
||||||
"""Saves the updated client 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_email = email_entry.get() if email_entry.get() != '' else None
|
||||||
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
|
||||||
try:
|
otp_code = otp_entry.get()
|
||||||
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
|
||||||
result = update_client(client_id, 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()
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
|
messagebox.showerror("Update Failed", result.get('message', 'Unknown error'))
|
||||||
edit_window.destroy()
|
edit_window.destroy()
|
||||||
except Exception as e:
|
|
||||||
messagebox.showerror("Error", f"Could not update details: {e}")
|
|
||||||
|
|
||||||
def populate_table():
|
def populate_table():
|
||||||
"""Populates the accounts table with client accounts."""
|
"""Populates the accounts table with client accounts."""
|
||||||
@@ -160,9 +169,14 @@ welcome_label.pack(pady=20)
|
|||||||
|
|
||||||
display_client_info()
|
display_client_info()
|
||||||
|
|
||||||
|
# Create a logout button
|
||||||
logout_button = customtkinter.CTkButton(root, text="Logout", command=logout)
|
logout_button = customtkinter.CTkButton(root, text="Logout", command=logout)
|
||||||
logout_button.pack(pady=15)
|
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
|
# Create a frame for the table
|
||||||
table_frame = ttk.Frame(root)
|
table_frame = ttk.Frame(root)
|
||||||
table_frame.pack(side='right', fill='both', expand=True)
|
table_frame.pack(side='right', fill='both', expand=True)
|
||||||
|
|||||||
@@ -53,10 +53,13 @@ def change_dark_theme():
|
|||||||
##############
|
##############
|
||||||
|
|
||||||
# Set appearance mode based on configuration
|
# Set appearance mode based on configuration
|
||||||
if CONFIG["preferences"]["dark_theme"] == "dark":
|
if "preferences" in CONFIG and "dark_theme" in CONFIG["preferences"]:
|
||||||
|
if CONFIG["preferences"]["dark_theme"] == "dark":
|
||||||
customtkinter.set_appearance_mode("dark")
|
customtkinter.set_appearance_mode("dark")
|
||||||
else:
|
else:
|
||||||
customtkinter.set_appearance_mode("light")
|
customtkinter.set_appearance_mode("light")
|
||||||
|
else:
|
||||||
|
customtkinter.set_appearance_mode("dark")
|
||||||
|
|
||||||
# Initialize the main window
|
# Initialize the main window
|
||||||
root = customtkinter.CTk()
|
root = customtkinter.CTk()
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"session_cookie": {"session": "UHtXXDwzE9iVXmMpFHD9BYA-ztYORiBP-xfRImGQDJQ"}, "client_id": "31d90aad"}
|
{"session_cookie": {"session": "mMTYW-c_n0BE-l7MENT8A1h2Rg4UUrNRJYl7NvXTcS4"}, "client_id": "31d90aad"}
|
||||||
BIN
flask_session/0f8e743989515f4aaf958d76f346210f
Normal file
BIN
flask_session/0f8e743989515f4aaf958d76f346210f
Normal file
Binary file not shown.
BIN
flask_session/1c0bd59593392e52337d73665704d133
Normal file
BIN
flask_session/1c0bd59593392e52337d73665704d133
Normal file
Binary file not shown.
BIN
flask_session/2029240f6d1128be89ddc32729463129
Normal file
BIN
flask_session/2029240f6d1128be89ddc32729463129
Normal file
Binary file not shown.
BIN
flask_session/2892d6f928e4706b8b53976f24e16df9
Normal file
BIN
flask_session/2892d6f928e4706b8b53976f24e16df9
Normal file
Binary file not shown.
BIN
flask_session/2aeb459d854ed6b531157b1f07263701
Normal file
BIN
flask_session/2aeb459d854ed6b531157b1f07263701
Normal file
Binary file not shown.
BIN
flask_session/4d439b134cc69940f885e01fb69fa2af
Normal file
BIN
flask_session/4d439b134cc69940f885e01fb69fa2af
Normal file
Binary file not shown.
BIN
flask_session/543f6931cd6b44c3c94cadb682baadb6
Normal file
BIN
flask_session/543f6931cd6b44c3c94cadb682baadb6
Normal file
Binary file not shown.
BIN
flask_session/5bd955d64e05f26ba5ef180a04500110
Normal file
BIN
flask_session/5bd955d64e05f26ba5ef180a04500110
Normal file
Binary file not shown.
BIN
flask_session/5d5c04d15f0f8cbf4721083899098bc5
Normal file
BIN
flask_session/5d5c04d15f0f8cbf4721083899098bc5
Normal file
Binary file not shown.
BIN
flask_session/6dbbe99eb2379d46adb417f7cb73998a
Normal file
BIN
flask_session/6dbbe99eb2379d46adb417f7cb73998a
Normal file
Binary file not shown.
BIN
flask_session/93cd60fca3662b3b62fa48162b37f0fc
Normal file
BIN
flask_session/93cd60fca3662b3b62fa48162b37f0fc
Normal file
Binary file not shown.
BIN
flask_session/b374a533064d4f726057d2daf5465b06
Normal file
BIN
flask_session/b374a533064d4f726057d2daf5465b06
Normal file
Binary file not shown.
BIN
flask_session/c2ca2782adffe80ef938353324e18126
Normal file
BIN
flask_session/c2ca2782adffe80ef938353324e18126
Normal file
Binary file not shown.
BIN
flask_session/d1a91b81953dba7179a749524fd7b5d8
Normal file
BIN
flask_session/d1a91b81953dba7179a749524fd7b5d8
Normal file
Binary file not shown.
BIN
flask_session/e80c3442482b04dffebe9de33c2adace
Normal file
BIN
flask_session/e80c3442482b04dffebe9de33c2adace
Normal file
Binary file not shown.
BIN
flask_session/e9087f19cb0516ef0a65e6899b4121b2
Normal file
BIN
flask_session/e9087f19cb0516ef0a65e6899b4121b2
Normal file
Binary file not shown.
@@ -162,9 +162,11 @@ 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, **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):
|
||||||
|
return format_response(False, "Invalid OTP."), 405
|
||||||
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():
|
for client in session.query(Client).all():
|
||||||
|
|||||||
BIN
test_database.db
BIN
test_database.db
Binary file not shown.
Reference in New Issue
Block a user