diff --git a/GUI.py b/GUI.py index 24a07765c9ff2997893cf70d8d3136fdd93d1837..979774088fe0783d2b7bd4eac73838e304bb626e 100644 --- a/GUI.py +++ b/GUI.py @@ -74,7 +74,7 @@ def open_dashboard(user): dashboard.geometry("500x400") # Display Welcome Message Using `user.username` - welcome_label = Label(dashboard, text=f"Welcome, {user['username']}!", font=("Arial", 16)) + welcome_label = Label(dashboard, text=f"Welcome, {user.userName}!", font=("Arial", 16)) welcome_label.pack(pady=20) if isinstance(user, StaffUser): @@ -106,9 +106,10 @@ def gui_login(): # Call loginAttempt() from main.py user = loginAttempt(username, password) + #logging.debug(user) if user: - messagebox.showinfo("Login", f"Login successful! Welcome {user['username']}.") + messagebox.showinfo("Login", f"Login successful! Welcome {user.userName}.") window.destroy() # Close login window open_dashboard(user) # Open appropriate dashboard based on user role else: diff --git a/__pycache__/main.cpython-312.pyc b/__pycache__/main.cpython-312.pyc index 219c7b89736cb328d9b6f143a51c28993ccb875c..70f66fef1605820f3ec72c7edf20cf23200504d0 100644 Binary files a/__pycache__/main.cpython-312.pyc and b/__pycache__/main.cpython-312.pyc differ diff --git a/main.py b/main.py index b9d3f43ad20d3b316a45af126b55c573ac602177..5ba6806690db4bfb51e7800bd67b0fcf87374ab6 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,10 @@ import logging -logging.basicConfig(level=0, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M") +logging.basicConfig(level=logging.DEBUG, format="{asctime} - {levelname} - {message}", style="{", datefmt="%Y-%m-%d %H:%M") from src import * from src.dbfunc import get_connection import json +import pandas as pd +import datetime as dt from src.staffUser import StaffUser from src.adminUser import AdminUser from src.managerUser import ManagerUser @@ -21,37 +23,37 @@ from src.managerUser import ManagerUser def loginAttempt(username: str, password: str): - """Check if the user exists in the database and return the appropriate user object""" + """Check if the user exists in the database and return the appropriate user object - conn = get_connection() - if conn: - cursor = conn.cursor(dictionary=True) - - # Fetch user details from the database - cursor.execute("SELECT username, password_hash, role FROM users WHERE username = %s AND password_hash = %s", - (username, password)) - user_data = cursor.fetchone() - - cursor.close() - conn.close() - - if user_data: - logging.info(f"User {user_data['username']} logged in successfully.") - - # Return an instance of the correct user class - if user_data['role'] == 'Staff': - return StaffUser(username=user_data['username']) - elif user_data['role'] == 'Admin': - return AdminUser(username=user_data['username']) - elif user_data['role'] == 'Manager': - return ManagerUser(username=user_data['username']) - else: - logging.error("Unknown role in database.") - return None - else: - logging.warning("Invalid username or password.") + Arguments: + username (str) -- username for login. + password (str) -- password for login, plaintext? + Returns: + User object of type: StaffUser or AdminUser or ManagerUser + or None if failed login. + """ + # dbug shortcut + if username=="debug" and password=="debug": + return ManagerUser(15, "manager", "password", [1], "Manager") + # using dbfuncs to do this: cursor.execute("SELECT username, password_hash, role FROM users WHERE username = %s AND password_hash = %s", (username, password)) + user_data = select_from_table_where("tblUsers", f"username = {username} AND password_hash = {password}", "username", "password_hash", "role") - return None # Return None if no user found + if user_data: + logging.info(f"User {user_data['username']} logged in successfully.") + + # Return an instance of the correct user class + if user_data['role'] == 'Staff': + return StaffUser(username=user_data['username']) + elif user_data['role'] == 'Admin': + return AdminUser(username=user_data['username']) + elif user_data['role'] == 'Manager': + return ManagerUser(username=user_data['username']) + else: + logging.error("Unknown role in database.") + return None + else: + logging.warning("Invalid username or password.") + return None # Return None if no user found def staffUser_options_cli(user:StaffUser) -> None: while True: @@ -82,6 +84,7 @@ def staffUser_options_cli(user:StaffUser) -> None: exit() def managerUser_options_cli(user:ManagerUser) -> None: + logging.debug("loaded into managerUser_options_cli.") while True: selection = input("Menu options:\n" " 1. View Listings \n" @@ -121,6 +124,17 @@ def adminUser_options_cli(user:AdminUser) -> None: user.logout() exit() +def fetch_movies() -> dict: + raise NotImplementedError() + select_from_table("tblMovies") + +def get_listings(): + currentTime = dt.datetime.now() + listings = select_from_table_where("tblShowings", f"[{currentTime}] + show_time > sysdatetime()") # returns all data that matches today + +def display_listings_cli(): + strListings = pd.DataFrame(get_listings()) + return def load_cinema(cinemaID) -> Cinema: raise NotImplementedError() @@ -149,36 +163,32 @@ def main_cli() -> None: while True: username = encrypt(sanitize(input("Username: "))) password = encrypt(sanitize(input("Password: "))) - #user = loginAttempt(username=username, password=password) - user = ManagerUser(impBool=1) # dev remove later - if user is None: + user = loginAttempt(username=username, password=password) + + if username=="debug" and password=="debug": + logging.warning("Entered as debug user") + user = ManagerUser(15, "manager", "password", [1], "Manager") + #logging.debug(f"user object loaded as: {user}") + managerUser_options_cli(user) + break + elif user is None: print("Login attempt failed please try again.") else: + logging.debug(f"failed login, returned value: {user}") break - logging.info("successful login, loading menu...") + logging.info(f"successfuly loged in as {user.userName}, loading menu...") # based on the different user permision levels, load different menus. - match user.permissionLevel: - case 1: - managerUser_options_cli(user) - case 2: - adminUser_options_cli(user) - case _: - staffUser_options_cli(user) + if user.role=="Manager": + managerUser_options_cli(user) + elif user.role=="Admin": + adminUser_options_cli(user) + elif user.role=="Staff": + staffUser_options_cli(user) # following code will only execute if run directly from this file. if __name__ == "__main__": logging.debug("STARTING main_cli") main_cli() logging.debug("main_cli finished, program exiting. bye bye!") - -def loginAttempt(username: str, password: str): - """Check if the user exists in the database""" - conn = get_connection() - if conn: - cursor = conn.cursor(dictionary=True) - cursor.execute("SELECT * FROM Users WHERE username = %s AND password_hash = %s", (username, password)) - user = cursor.fetchone() - conn.close() - return user # Returns user details if found - return None \ No newline at end of file + diff --git a/src/__pycache__/__init__.cpython-312.pyc b/src/__pycache__/__init__.cpython-312.pyc index aaa784897475dad772c7a61107c760b558fdf570..22aab0c5e549be1de01acbc9f1c13180be82681e 100644 Binary files a/src/__pycache__/__init__.cpython-312.pyc and b/src/__pycache__/__init__.cpython-312.pyc differ diff --git a/src/__pycache__/adminUser.cpython-312.pyc b/src/__pycache__/adminUser.cpython-312.pyc index e862f6391397e9c67c1dd92ae1fbf20e7b084608..8cd0a263f4650f94ec2f3445ba63e1247b555380 100644 Binary files a/src/__pycache__/adminUser.cpython-312.pyc and b/src/__pycache__/adminUser.cpython-312.pyc differ diff --git a/src/__pycache__/bookingObj.cpython-312.pyc b/src/__pycache__/bookingObj.cpython-312.pyc index 4678c08d458aad37f39f436e7a08d250feb3dad2..a95cc5867d0668f4171d2ea00ba38fac6bad3dc5 100644 Binary files a/src/__pycache__/bookingObj.cpython-312.pyc and b/src/__pycache__/bookingObj.cpython-312.pyc differ diff --git a/src/__pycache__/cinemaObj.cpython-312.pyc b/src/__pycache__/cinemaObj.cpython-312.pyc index e889a025d413312cfd167d1a991a2a5909f13fd5..dfc88c86489f19e676778ae90beb1d855c1faffb 100644 Binary files a/src/__pycache__/cinemaObj.cpython-312.pyc and b/src/__pycache__/cinemaObj.cpython-312.pyc differ diff --git a/src/__pycache__/constants.cpython-312.pyc b/src/__pycache__/constants.cpython-312.pyc index d3bc49915e4b08b2493f7d0b87854b992d1d9ce7..3bb21f47a4f77a6782ebd8e3d633e0f1b851c44f 100644 Binary files a/src/__pycache__/constants.cpython-312.pyc and b/src/__pycache__/constants.cpython-312.pyc differ diff --git a/src/__pycache__/dbfunc.cpython-312.pyc b/src/__pycache__/dbfunc.cpython-312.pyc index 55dfe2f82b5871a26d95ff2418ec5379258e663c..5ba53e9ca58e4129c6cef290ff49a41264c7c450 100644 Binary files a/src/__pycache__/dbfunc.cpython-312.pyc and b/src/__pycache__/dbfunc.cpython-312.pyc differ diff --git a/src/__pycache__/managerUser.cpython-312.pyc b/src/__pycache__/managerUser.cpython-312.pyc index 066114c00fe160c03d83e6e6c335ee8c4347c0b7..f0e34ccdc3d8c4845b485f3bf05b7bc54e67f16d 100644 Binary files a/src/__pycache__/managerUser.cpython-312.pyc and b/src/__pycache__/managerUser.cpython-312.pyc differ diff --git a/src/__pycache__/reportObj.cpython-312.pyc b/src/__pycache__/reportObj.cpython-312.pyc index 84e9396990ad1e391f3e1c38a0873b3ca6ac71b5..7d4fc47261d2a1e864ba1e853418bb40b86ca611 100644 Binary files a/src/__pycache__/reportObj.cpython-312.pyc and b/src/__pycache__/reportObj.cpython-312.pyc differ diff --git a/src/__pycache__/screenObj.cpython-312.pyc b/src/__pycache__/screenObj.cpython-312.pyc index 404eaa518842cffc596ae0349cfae21c58093a3f..9d274a19a39a94de809bad84c3cc3abafab5b5dc 100644 Binary files a/src/__pycache__/screenObj.cpython-312.pyc and b/src/__pycache__/screenObj.cpython-312.pyc differ diff --git a/src/__pycache__/staffUser.cpython-312.pyc b/src/__pycache__/staffUser.cpython-312.pyc index 1aee61bed589a71284cd861e87f81a6ed12f6fe9..adcc99e4076d9a6c6abcf958eed4ad89ebdd0127 100644 Binary files a/src/__pycache__/staffUser.cpython-312.pyc and b/src/__pycache__/staffUser.cpython-312.pyc differ diff --git a/src/adminUser.py b/src/adminUser.py index 069c0d7d6d36921ab4acd46cd50fb0c42ae2ff8e..7dc9cb77b3dc538d3f0a9147cb47f653f22299ca 100644 --- a/src/adminUser.py +++ b/src/adminUser.py @@ -6,9 +6,9 @@ class AdminUser(StaffUser): Args: staffUser (_type_): _description_ """ - def __init__(self): - super().__init__() - self.permissionLevel = 1 + def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int): + super().__init__(self, id, name, passw, cinemas) + self.role = 1 diff --git a/src/dbfunc.py b/src/dbfunc.py index d388d5a961cbb217b6d6eb9c0a5f9a73f03c8f8d..377eeff5c8f423058925b4984391b90f9299beeb 100644 --- a/src/dbfunc.py +++ b/src/dbfunc.py @@ -28,15 +28,13 @@ def get_connection(): return None # Function to SELECT data from any table -def select_from_table(table, *columns): +def select_from_table(table, *args): """Fetches data from a given table.""" conn = get_connection() - if not conn: - return [] try: cursor = conn.cursor(dictionary=True) - query = f"SELECT {', '.join(columns) if columns else '*'} FROM {table}" + query = f"SELECT {', '.join(args) if args else '*'} FROM {table}" cursor.execute(query) results = cursor.fetchall() return results @@ -48,24 +46,32 @@ def select_from_table(table, *columns): conn.close() # Function to SELECT data with a WHERE condition -def select_from_table_where(table, condition, *columns): - """Fetches data from a table with a WHERE condition.""" +def select_from_table_where(table:str, condition:str, *args): + """Fetches data from a table with a WHERE condition. + + Arguments: + table (str): database table name, eg; "tblUsers" + condition (str): condition string in SQL format, eg; "WHERE username = %s AND password_hash = %s" + *columns: excepts all aditinal arguments and converts them into SQL query following SELECT as arguments, if none SQL statemnt uses *. + Returns: + dict + """ conn = get_connection() if not conn: return [] try: cursor = conn.cursor(dictionary=True) - query = f"SELECT {', '.join(columns) if columns else '*'} FROM {table} WHERE {condition}" + query = f"SELECT {', '.join(args) if args else '*'} FROM {table} WHERE {condition}" cursor.execute(query) results = cursor.fetchall() return results except mysql.connector.Error as err: logging.error(f"Error fetching data with condition: {err}") - return [] - finally: - cursor.close() - conn.close() + return None + #finally: + # cursor.close() + # conn.close() # Function to INSERT data into any table def insert_into_table(table, data): diff --git a/src/managerUser.py b/src/managerUser.py index f74edda220127eaa6dd473011f64f4d446113948..18d72f2e530c017d9cf56f58051d51f53586270e 100644 --- a/src/managerUser.py +++ b/src/managerUser.py @@ -6,9 +6,9 @@ class ManagerUser(AdminUser): Args: userClass (_type_): _description_ """ - def __init__(self): - super().__init__() - self.permissionLevel = 2 + def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int): + super().__init__(self, id, name, passw, cinemas) + self.role = 2 def expand_buisness(self): # creates new cinemaObj and adds it to db. diff --git a/src/staffUser.py b/src/staffUser.py index 27e217a97b3d5a6a74547b50801e1b6c91e0c866..0fcdd27f3df7c2ee415e1666207533891f7b61f1 100644 --- a/src/staffUser.py +++ b/src/staffUser.py @@ -5,25 +5,22 @@ from .cinemaObj import Cinema # trying to make this a base implementation for all user classes. -class StaffUser(object): - def __init__(self, id:int, name:str, passw:str, permLvl:int, cinemas:list, impBool:bool=0): - # impbool used to switch case on a newly created user or imported from database. - if impBool: - # import user from db - select_from_tbl_where(table="tblUsers", condition="") - pass - else: - # staff id number assigned by manager during onboarding. - self.userID:int = id - self.userName:str = name - self.userPass:str = passw - # staff software level. - self.permissionLevel:int = permLvl - # list of branches active at. - self.cinemas = cinemas - - def __str__(self): - return f"{self.__class__.__name__} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass}, permissionLevel={self.permissionLevel})" +class StaffUser: + def __init__(self, id:int, name:str, passw:str, cinemas:list, role:int): + # staff id number assigned by manager during onboarding. + self.userID:int = id + self.userName:str = name + self.userPass:str = passw + # staff software level. + self.role:int = role + # list of branches active at. + self.cinemas = cinemas + + + # function not working, causes massive recursion? + #def __repr__(self): + #"""this function returns this object in a string readable format, eg; print(staffUser) returns 'StaffUser user object(userID=1, userName='user', userPass='password'... ' """ + # return f"{self.__class__.__name__} user object(userID={self.userID}, userName={self.userName}, userPass={self.userPass}, permissionLevel={self.role})" def login(self, userName, userPassword) -> None: """get values for self from db"""