mansi14883md/AI-Keystroke-Security-System
1
1import os2import tkinter as tk3from tkinter import messagebox, ttk4 5from backend_utils import (6 delete_user_profile,7 export_attempt_history,8 get_attempt_history,9 get_dashboard_stats,10 get_user_overview,11 set_setting,12)13 14 15EXPORT_FILE = os.path.join("data", "exported_attempt_history.csv")16 17 18class AdminDashboard:19 def __init__(self, root: tk.Tk) -> None:20 self.root = root21 self.root.title("Admin Dashboard")22 self.root.geometry("920x620")23 self.root.configure(bg="#081420")24 25 self.threshold_var = tk.StringVar()26 self.failed_attempts_var = tk.StringVar()27 self.cooldown_var = tk.StringVar()28 29 self.build_gui()30 self.refresh_all()31 32 def build_gui(self) -> None:33 tk.Label(34 self.root,35 text="Admin Dashboard",36 font=("Arial", 24, "bold"),37 fg="#f1faee",38 bg="#081420",39 pady=14,40 ).pack()41 42 summary_frame = tk.Frame(self.root, bg="#102235")43 summary_frame.pack(fill="x", padx=18, pady=10)44 self.summary_label = tk.Label(summary_frame, text="", font=("Arial", 12), fg="#caf0f8", bg="#102235", justify="left", pady=12)45 self.summary_label.pack(anchor="w", padx=16)46 47 settings_frame = tk.Frame(self.root, bg="#102235")48 settings_frame.pack(fill="x", padx=18, pady=6)49 tk.Label(settings_frame, text="Decision Threshold", fg="#f1faee", bg="#102235", font=("Arial", 11, "bold")).grid(row=0, column=0, padx=10, pady=10, sticky="w")50 tk.Entry(settings_frame, textvariable=self.threshold_var, width=8).grid(row=0, column=1, padx=6)51 tk.Label(settings_frame, text="Max Failed Attempts", fg="#f1faee", bg="#102235", font=("Arial", 11, "bold")).grid(row=0, column=2, padx=10, pady=10, sticky="w")52 tk.Entry(settings_frame, textvariable=self.failed_attempts_var, width=8).grid(row=0, column=3, padx=6)53 tk.Label(settings_frame, text="Cooldown Seconds", fg="#f1faee", bg="#102235", font=("Arial", 11, "bold")).grid(row=0, column=4, padx=10, pady=10, sticky="w")54 tk.Entry(settings_frame, textvariable=self.cooldown_var, width=8).grid(row=0, column=5, padx=6)55 tk.Button(settings_frame, text="Save Security Settings", command=self.save_settings, bg="#00b4d8", fg="white", relief="flat", padx=12).grid(row=0, column=6, padx=12)56 tk.Button(settings_frame, text="Export Attempt Report", command=self.export_report, bg="#1f8a70", fg="white", relief="flat", padx=12).grid(row=0, column=7, padx=12)57 58 content = tk.Frame(self.root, bg="#081420")59 content.pack(fill="both", expand=True, padx=18, pady=10)60 61 users_frame = tk.Frame(content, bg="#102235")62 users_frame.pack(side="left", fill="both", expand=True, padx=(0, 8))63 tk.Label(users_frame, text="Registered Users", font=("Arial", 14, "bold"), fg="#f1faee", bg="#102235").pack(pady=10)64 self.users_tree = ttk.Treeview(users_frame, columns=("samples", "threshold", "updated"), show="headings", height=16)65 self.users_tree.heading("samples", text="Samples")66 self.users_tree.heading("threshold", text="Threshold")67 self.users_tree.heading("updated", text="Updated")68 self.users_tree.column("samples", width=80, anchor="center")69 self.users_tree.column("threshold", width=90, anchor="center")70 self.users_tree.column("updated", width=180, anchor="center")71 self.users_tree.pack(fill="both", expand=True, padx=12, pady=8)72 tk.Button(users_frame, text="Delete Selected User", command=self.delete_selected_user, bg="#c1121f", fg="white", relief="flat", padx=12).pack(pady=(0, 12))73 74 attempts_frame = tk.Frame(content, bg="#102235")75 attempts_frame.pack(side="right", fill="both", expand=True, padx=(8, 0))76 tk.Label(attempts_frame, text="Attempt History", font=("Arial", 14, "bold"), fg="#f1faee", bg="#102235").pack(pady=10)77 self.attempts_tree = ttk.Treeview(attempts_frame, columns=("time", "user", "result", "confidence"), show="headings", height=16)78 self.attempts_tree.heading("time", text="Timestamp")79 self.attempts_tree.heading("user", text="User")80 self.attempts_tree.heading("result", text="Result")81 self.attempts_tree.heading("confidence", text="Confidence")82 self.attempts_tree.column("time", width=170)83 self.attempts_tree.column("user", width=90, anchor="center")84 self.attempts_tree.column("result", width=110, anchor="center")85 self.attempts_tree.column("confidence", width=90, anchor="center")86 self.attempts_tree.pack(fill="both", expand=True, padx=12, pady=8)87 88 def refresh_all(self) -> None:89 stats = get_dashboard_stats()90 self.summary_label.config(91 text=(92 f"Total Users: {stats['total_users']} "93 f"Total Attempts: {stats['total_attempts']} "94 f"Granted: {stats['granted_attempts']} "95 f"Denied: {stats['denied_attempts']} "96 f"Avg Confidence: {stats['average_confidence'] * 100:.2f}%"97 )98 )99 self.threshold_var.set(str(stats["decision_threshold"]))100 self.failed_attempts_var.set(str(stats["max_failed_attempts"]))101 self.cooldown_var.set(str(stats["cooldown_seconds"]))102 103 for item in self.users_tree.get_children():104 self.users_tree.delete(item)105 for user in get_user_overview():106 self.users_tree.insert("", "end", iid=user["username"], values=(user["sample_count"], f"{user['threshold']:.2f}", user["updated_at"] or "-"))107 108 for item in self.attempts_tree.get_children():109 self.attempts_tree.delete(item)110 for attempt in get_attempt_history(limit=20):111 self.attempts_tree.insert(112 "",113 "end",114 values=(115 attempt["timestamp"],116 attempt["username"],117 attempt["result"],118 f"{float(attempt['confidence']) * 100:.2f}%",119 ),120 )121 122 def save_settings(self) -> None:123 try:124 threshold = float(self.threshold_var.get())125 max_attempts = int(self.failed_attempts_var.get())126 cooldown = int(self.cooldown_var.get())127 except ValueError:128 messagebox.showwarning("Invalid Values", "Please enter valid numeric security settings.")129 return130 131 set_setting("decision_threshold", threshold)132 set_setting("max_failed_attempts", max_attempts)133 set_setting("cooldown_seconds", cooldown)134 self.refresh_all()135 messagebox.showinfo("Saved", "Security settings updated successfully.")136 137 def export_report(self) -> None:138 path = export_attempt_history(EXPORT_FILE)139 messagebox.showinfo("Exported", f"Attempt history exported to:\n{os.path.abspath(path)}")140 141 def delete_selected_user(self) -> None:142 selected = self.users_tree.selection()143 if not selected:144 messagebox.showwarning("No Selection", "Please select a user first.")145 return146 username = selected[0]147 if not messagebox.askyesno("Confirm Delete", f"Delete user '{username}' and all typing samples?"):148 return149 delete_user_profile(username)150 self.refresh_all()151 152 153def main() -> None:154 root = tk.Tk()155 AdminDashboard(root)156 root.mainloop()157 158 159if __name__ == "__main__":160 main()161 