login_system.py
unknown
plain_text
a month ago
17 kB
3
Indexable
#!/usr/bin/env python3 import tkinter as tk from tkinter import ttk, messagebox, simpledialog import mysql.connector from datetime import datetime import os import hashlib import re from parkmanager import ParkingManagerApp # Database Configuration DB_CONFIG = { "host": "localhost", "user": "root", "password": "", "database": "parkfinder", } # --- Configuration for Locked Company --- def load_locked_company(): """Load the locked company from file; default to 'olpcc' if not found.""" if os.path.exists("locked_company.txt"): try: with open("locked_company.txt", "r") as f: company = f.read().strip() if company: return company except Exception as e: print("Error reading locked_company.txt:", e) return "OLPCC" def save_locked_company(company): """Save the locked company to a file for persistence.""" try: with open("locked_company.txt", "w") as f: f.write(company) print(f"Successfully saved company: {company} to locked_company.txt") return True except Exception as e: print("Error writing locked_company.txt:", e) return False def hash_password(password): """Create a SHA-256 hash of the password.""" return hashlib.sha256(password.encode()).hexdigest() class LoginWindow(tk.Tk): def __init__(self): super().__init__() self.title("Parking Management System - Login") self.geometry("400x500") self.resizable(False, False) # Center the window self.update_idletasks() width = self.winfo_width() height = self.winfo_height() x = (self.winfo_screenwidth() // 2) - (width // 2) y = (self.winfo_screenheight() // 2) - (height // 2) self.geometry(f'+{x}+{y}') self.create_widgets() # Load the locked company self.locked_company = load_locked_company() self.update_company_display() # Fetch companies for the dropdown self.load_companies() def create_widgets(self): # Main frame main_frame = ttk.Frame(self, padding=20) main_frame.pack(fill="both", expand=True) # Title title_label = ttk.Label(main_frame, text="Parking Management System", font=("Arial", 16, "bold")) title_label.pack(pady=(0, 20)) # Login frame login_frame = ttk.LabelFrame(main_frame, text="Staff Login", padding=10) login_frame.pack(fill="both", expand=True, padx=10, pady=10) # Username ttk.Label(login_frame, text="Username:").pack(anchor="w", pady=(10, 5)) self.username_entry = ttk.Entry(login_frame, width=30) self.username_entry.pack(fill="x", pady=(0, 10)) # Password ttk.Label(login_frame, text="Password:").pack(anchor="w", pady=(5, 5)) self.password_entry = ttk.Entry(login_frame, width=30, show="*") self.password_entry.pack(fill="x", pady=(0, 10)) # Company selection ttk.Label(login_frame, text="Company:").pack(anchor="w", pady=(5, 5)) self.company_frame = ttk.Frame(login_frame) self.company_frame.pack(fill="x", pady=(0, 10)) self.company_label = ttk.Label(self.company_frame, text="Loading companies...", font=("Arial", 10)) self.company_label.pack(side="left", fill="x", expand=True) self.change_company_btn = ttk.Button(self.company_frame, text="Change", command=self.select_company) self.change_company_btn.pack(side="right") # Login button self.login_button = ttk.Button(login_frame, text="Login", command=self.login) self.login_button.pack(pady=20) # Register link register_frame = ttk.Frame(main_frame) register_frame.pack(fill="x", pady=10) register_label = ttk.Label(register_frame, text="Don't have an account?") register_label.pack(side="left") register_link = ttk.Label(register_frame, text="Register", foreground="blue", cursor="hand2") register_link.pack(side="left", padx=5) register_link.bind("<Button-1>", self.show_register) # Status bar self.status_var = tk.StringVar() self.status_var.set("Ready") status_bar = ttk.Label(self, textvariable=self.status_var, relief="sunken", anchor="w") status_bar.pack(side="bottom", fill="x") def update_company_display(self): """Update the company label with the current locked company""" if hasattr(self, 'company_label'): self.company_label.config(text=f"Current: {self.locked_company}") def load_companies(self): """Load companies from the database for the dropdown""" try: conn = mysql.connector.connect(**DB_CONFIG) cursor = conn.cursor() cursor.execute("SELECT id, company_name FROM parking_lots") self.companies = [(row[0], row[1]) for row in cursor.fetchall()] conn.close() if not self.companies: self.status_var.set("Warning: No companies found in database") else: self.update_company_display() except mysql.connector.Error as err: self.status_var.set(f"Error: {err}") self.companies = [] def select_company(self): """Open a dialog to select a company""" if not hasattr(self, 'companies') or not self.companies: messagebox.showerror("Error", "No companies available to select") return # Create a new window with a dropdown to select a company top = tk.Toplevel(self) top.title("Select Company") top.geometry("300x200") top.resizable(False, False) # Center the window top.update_idletasks() width = top.winfo_width() height = top.winfo_height() x = (top.winfo_screenwidth() // 2) - (width // 2) y = (top.winfo_screenheight() // 2) - (height // 2) top.geometry(f'+{x}+{y}') ttk.Label(top, text="Select a company:", font=("Arial", 12)).pack(pady=(20, 10), padx=10) # Create StringVar with the current company as default company_var = tk.StringVar() # Find the current company name in the list current_company_name = None for company_id, company_name in self.companies: if company_name == self.locked_company: current_company_name = company_name break if current_company_name: company_var.set(current_company_name) else: company_var.set(self.companies[0][1]) # Default to first company # Create the dropdown with company names only company_names = [name for _, name in self.companies] combobox = ttk.Combobox(top, textvariable=company_var, values=company_names, state="readonly", width=25) combobox.pack(pady=10, padx=10) def on_confirm(): selected_company_name = company_var.get() if selected_company_name: # Update the locked company self.locked_company = selected_company_name # Save to file save_locked_company(selected_company_name) # Update the label self.update_company_display() messagebox.showinfo("Success", f"Company set to {selected_company_name}") top.destroy() button_frame = ttk.Frame(top) button_frame.pack(pady=20) confirm_button = ttk.Button(button_frame, text="Confirm", command=on_confirm) confirm_button.pack(side="left", padx=5) cancel_button = ttk.Button(button_frame, text="Cancel", command=top.destroy) cancel_button.pack(side="left", padx=5) # Make the window modal top.transient(self) top.grab_set() self.wait_window(top) def login(self): username = self.username_entry.get().strip() password = self.password_entry.get() if not username or not password: messagebox.showerror("Login Error", "Please enter both username and password") return try: conn = mysql.connector.connect(**DB_CONFIG) cursor = conn.cursor(dictionary=True) # Check if user exists and password matches hashed_password = hash_password(password) cursor.execute( "SELECT * FROM staff WHERE username = %s AND password = %s", (username, hashed_password) ) staff = cursor.fetchone() if not staff: messagebox.showerror("Login Error", "Invalid username or password") conn.close() return # Record login time in staffrecords now = datetime.now().strftime("%Y-%m-%d %H:%M:%S") cursor.execute( "INSERT INTO staffrecords (staff_id, time_in, company) VALUES (%s, %s, %s)", (staff['id'], now, self.locked_company) ) conn.commit() # Get the record ID for logout record_id = cursor.lastrowid conn.close() # Hide login window self.withdraw() # Create user info dictionary user_info = { 'id': staff['id'], 'name': staff['name'], 'username': staff['username'], 'role': staff['role'] } # Launch main application app = ParkingManagerApp(user=user_info, record_id=record_id) # Set logout callback to show login window again app.set_logout_callback(self.on_logout) # Pass the locked company to the main app app.locked_company = self.locked_company app.mainloop() except mysql.connector.Error as err: messagebox.showerror("Database Error", f"Error: {err}") def on_logout(self): """Callback function when user logs out of main app""" # Clear login fields self.username_entry.delete(0, tk.END) self.password_entry.delete(0, tk.END) # Show login window again self.deiconify() self.username_entry.focus() def show_register(self, event=None): self.withdraw() # Hide login window register_window = RegisterWindow(self) register_window.mainloop() class RegisterWindow(tk.Toplevel): def __init__(self, parent): super().__init__(parent) self.parent = parent self.title("Parking Management System - Register") self.geometry("400x500") self.resizable(False, False) # Center the window self.update_idletasks() width = self.winfo_width() height = self.winfo_height() x = (self.winfo_screenwidth() // 2) - (width // 2) y = (self.winfo_screenheight() // 2) - (height // 2) self.geometry(f'+{x}+{y}') self.protocol("WM_DELETE_WINDOW", self.on_close) self.create_widgets() def create_widgets(self): # Main frame main_frame = ttk.Frame(self, padding=20) main_frame.pack(fill="both", expand=True) # Title title_label = ttk.Label(main_frame, text="Staff Registration", font=("Arial", 16, "bold")) title_label.pack(pady=(0, 20)) # Register frame register_frame = ttk.LabelFrame(main_frame, text="Create Account", padding=10) register_frame.pack(fill="both", expand=True, padx=10, pady=10) # Full Name ttk.Label(register_frame, text="Full Name:").pack(anchor="w", pady=(10, 5)) self.name_entry = ttk.Entry(register_frame, width=30) self.name_entry.pack(fill="x", pady=(0, 10)) # Username ttk.Label(register_frame, text="Username:").pack(anchor="w", pady=(5, 5)) self.username_entry = ttk.Entry(register_frame, width=30) self.username_entry.pack(fill="x", pady=(0, 10)) # Password ttk.Label(register_frame, text="Password:").pack(anchor="w", pady=(5, 5)) self.password_entry = ttk.Entry(register_frame, width=30, show="*") self.password_entry.pack(fill="x", pady=(0, 10)) # Confirm Password ttk.Label(register_frame, text="Confirm Password:").pack(anchor="w", pady=(5, 5)) self.confirm_password_entry = ttk.Entry(register_frame, width=30, show="*") self.confirm_password_entry.pack(fill="x", pady=(0, 10)) # Role selection ttk.Label(register_frame, text="Role:").pack(anchor="w", pady=(5, 5)) self.role_var = tk.StringVar(value="attendant") role_frame = ttk.Frame(register_frame) role_frame.pack(fill="x", pady=(0, 10)) ttk.Radiobutton(role_frame, text="Attendant", variable=self.role_var, value="attendant").pack(side="left", padx=(0, 10)) ttk.Radiobutton(role_frame, text="Admin", variable=self.role_var, value="admin").pack(side="left") # Register button self.register_button = ttk.Button(register_frame, text="Register", command=self.register) self.register_button.pack(pady=20) # Login link login_frame = ttk.Frame(main_frame) login_frame.pack(fill="x", pady=10) login_label = ttk.Label(login_frame, text="Already have an account?") login_label.pack(side="left") login_link = ttk.Label(login_frame, text="Login", foreground="blue", cursor="hand2") login_link.pack(side="left", padx=5) login_link.bind("<Button-1>", self.show_login) # Status bar self.status_var = tk.StringVar() self.status_var.set("Ready") status_bar = ttk.Label(self, textvariable=self.status_var, relief="sunken", anchor="w") status_bar.pack(side="bottom", fill="x") def register(self): name = self.name_entry.get().strip() username = self.username_entry.get().strip() password = self.password_entry.get() confirm_password = self.confirm_password_entry.get() role = self.role_var.get() # Validate inputs if not name or not username or not password: messagebox.showerror("Registration Error", "Please fill in all fields") return if password != confirm_password: messagebox.showerror("Registration Error", "Passwords do not match") return if len(password) < 6: messagebox.showerror("Registration Error", "Password must be at least 6 characters") return if not re.match(r'^[a-zA-Z0-9_]+$', username): messagebox.showerror("Registration Error", "Username can only contain letters, numbers, and underscores") return try: conn = mysql.connector.connect(**DB_CONFIG) cursor = conn.cursor() # Check if username already exists cursor.execute("SELECT id FROM staff WHERE username = %s", (username,)) if cursor.fetchone(): messagebox.showerror("Registration Error", "Username already exists") conn.close() return # Hash the password hashed_password = hash_password(password) # Insert new staff cursor.execute( "INSERT INTO staff (name, username, password, role) VALUES (%s, %s, %s, %s)", (name, username, hashed_password, role) ) conn.commit() conn.close() messagebox.showinfo("Registration Successful", "Your account has been created. You can now login.") self.show_login() except mysql.connector.Error as err: messagebox.showerror("Database Error", f"Error: {err}") def show_login(self, event=None): self.destroy() self.parent.deiconify() # Show login window def on_close(self): self.parent.deiconify() # Show login window when register window is closed self.destroy() if __name__ == "__main__": login_app = LoginWindow() login_app.mainloop()
Editor is loading...
Leave a Comment