using BCrypt.Net; using MySql.Data.MySqlClient; using System; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace SkyTeam { public partial class LogInPage : Page { public LogInPage() { InitializeComponent(); } private void AdminLink_Click(object sender, RoutedEventArgs e) { // Quelle: Im Unterricht gemacht if (Application.Current.MainWindow is MainWindow mainWindow) { mainWindow.MainFrame.Navigate(new AdminLoginPage()); } } private void LogInButton_Click(object sender, RoutedEventArgs e) { string email = BenutzernameTextBox.Text; string password = PasswortTextBox.Password; // Quelle: Im Unterricht gemacht // Basis Validierung auf leere Felder if (string.IsNullOrEmpty(email) || string.IsNullOrEmpty(password)) { MessageBox.Show("Bitte Email und Passwort eingeben."); return; } string query = @" SELECT Id, Vorname, Rolle, PasswortHash FROM users WHERE Email = @email"; try { using (MySqlConnection conn = new MySqlConnection(DatenbankServices.GetConnection())) { conn.Open(); using (MySqlCommand cmd = new MySqlCommand(query, conn)) { cmd.Parameters.AddWithValue("@email", email); using (MySqlDataReader reader = cmd.ExecuteReader()) { if (!reader.Read()) { MessageBox.Show("Benutzer wurde nicht gefunden."); return; } // Quelle: Stack Overflow "How to verify a BCrypt hash" // Man kann gehashte Passwörter NICHT direkt im SQL Query vergleichen // (z.B. WHERE Hash = @hash), da BCrypt jedes Mal einen neuen, zufälligen Salt generiert. // Wir müssen erst den gespeicherten Hash aus der DB laden und dann die Verify Methode // der BCrypt-Bibliothek nutzen, um das Klartext passwort damit zu prüfen string storedHash = reader.GetString("PasswortHash"); if (!BCrypt.Net.BCrypt.Verify(password, storedHash)) { MessageBox.Show("Falsches Passwort."); return; } // Quelle: AI Assistant (chat gpt) // Idee: Globales State-Management über eine statische Klasse (SessionManager) // Kommentar: Anstatt die User ID mühsam über jeden Seitenaufruf hinweg in den Konstruktoren // weiterzureichen, hat die KI vorgeschlagen, eine statische SessionManager Klasse zu nutzen. // So sind User-ID, Name und Rolle global für die gesamte Laufzeit abrufbar. SessionManager.CurrentUserId = reader.GetInt32("Id"); SessionManager.CurrentUserName = reader.GetString("Vorname"); SessionManager.Role = reader.GetString("Rolle"); } } ((MainWindow)Application.Current.MainWindow) .MainFrame.Navigate(new NavigationPage()); } } catch (Exception ex) { MessageBox.Show("Datenbankfehler: " + ex.Message); } } private void anmeldungsButton_Click(object sender, RoutedEventArgs e) { // Quelle: Im Unterricht gemacht ((MainWindow)Application.Current.MainWindow) .MainFrame.Navigate(new RegistrationPage()); } private void Page_Loaded(object sender, RoutedEventArgs e) { // Quelle: Im Unterricht gemacht // Setzt den Cursor direkt beim Laden der Seite ins Benutzernamen-Feld. BenutzernameTextBox.Focus(); } private void BenutzernameTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { // Quelle: Stack Overflow "WPF Move focus on enter key" // Kommentar: Ein UX-Feature (User Experience). Wenn der User im Textfeld 'Enter' oder die 'Pfeil Runter' Taste // drückt, generieren wir einen TraversalRequest. Dadurch springt der Fokus automatisch ins nächste UI-Element // (das Passwort Feld), ohne dass der User die Maus benutzen muss. if (e.Key == Key.Down || e.Key == Key.Enter) { TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next); (sender as UIElement).MoveFocus(request); e.Handled = true; } } } }