diff --git a/ChronoFlow.Controller/Class1.cs b/ChronoFlow.Controller/Class1.cs deleted file mode 100644 index 32f4c9e..0000000 --- a/ChronoFlow.Controller/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ChronoFlow.Controller; - -public class Class1 -{ -} \ No newline at end of file diff --git a/ChronoFlow.Model/Class1.cs b/ChronoFlow.Model/Class1.cs deleted file mode 100644 index fa0ba4c..0000000 --- a/ChronoFlow.Model/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ChronoFlow.Model; - -public class Class1 -{ -} \ No newline at end of file diff --git a/ChronoFlow.Model/User.cs b/ChronoFlow.Model/User.cs index 8d2e916..c72a780 100644 --- a/ChronoFlow.Model/User.cs +++ b/ChronoFlow.Model/User.cs @@ -23,5 +23,6 @@ namespace ChronoFlow.Model OriginalUsername = ""; } public DateTime LetzterLogin { get; set; } = DateTime.MinValue; + public DateTime VorletzterLogin { get; set; } } } \ No newline at end of file diff --git a/ChronoFlow.Persistence/Class1.cs b/ChronoFlow.Persistence/Class1.cs deleted file mode 100644 index 970277d..0000000 --- a/ChronoFlow.Persistence/Class1.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace ChronoFlow.Persistence; - -public class Class1 -{ -} \ No newline at end of file diff --git a/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs b/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs index 18f8cf3..7eaac05 100644 --- a/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs +++ b/ChronoFlow.Persistence/SqliteZeiterfassungsService.cs @@ -23,6 +23,8 @@ namespace ChronoFlow.Persistence // IMMER prüfen, auch nach neuem Erstellen PrüfeUndErweitereDatenbank(); + + _ = StelleDatenbankstrukturSicherAsync(); // Async-Aufruf ignorieren } private void ErstelleDatenbank() @@ -92,6 +94,8 @@ namespace ChronoFlow.Persistence AddColumnIfMissing(connection, "Benutzer", "Mitarbeitennummer", "TEXT"); AddColumnIfMissing(connection, "Benutzer", "Abteilung", "TEXT"); AddColumnIfMissing(connection, "Benutzer", "MussPasswortAendern", "INTEGER DEFAULT 1"); + AddColumnIfMissing(connection, "Benutzer", "LetzterLogin", "TEXT"); + AddColumnIfMissing(connection, "Benutzer", "VorletzterLogin", "TEXT"); AddColumnIfMissing(connection, "Zeiteintraege", "LetzteBearbeitung", "TEXT"); } @@ -158,11 +162,24 @@ namespace ChronoFlow.Persistence connection.Open(); var cmd = connection.CreateCommand(); - cmd.CommandText = "SELECT Id, Username, Password, Role, Mitarbeitennummer, Abteilung, MussPasswortAendern FROM Benutzer;"; + cmd.CommandText = @" + SELECT Id, Username, Password, Role, Mitarbeitennummer, Abteilung, MussPasswortAendern, LetzterLogin, VorletzterLogin + FROM Benutzer; + "; using var reader = cmd.ExecuteReader(); while (reader.Read()) { + // Absicherungen für mögliche NULL- oder ungültige Werte: + var letzterLogin = DateTime.MinValue; + var vorletzterLogin = DateTime.MinValue; + + if (!reader.IsDBNull(7)) + DateTime.TryParse(reader.GetString(7), out letzterLogin); + + if (!reader.IsDBNull(8)) + DateTime.TryParse(reader.GetString(8), out vorletzterLogin); + benutzerListe.Add(new User { Id = reader.GetInt32(0), @@ -172,6 +189,8 @@ namespace ChronoFlow.Persistence Mitarbeiternummer = reader.IsDBNull(4) ? "" : reader.GetString(4), Abteilung = reader.IsDBNull(5) ? "" : reader.GetString(5), MussPasswortAendern = reader.GetInt32(6) == 1, + LetzterLogin = letzterLogin, + VorletzterLogin = vorletzterLogin, OriginalUsername = reader.GetString(1) }); } @@ -179,6 +198,7 @@ namespace ChronoFlow.Persistence return benutzerListe; } + public void UpdateBenutzer(User benutzer) { using var connection = new SqliteConnection($"Data Source={_dbPath}"); @@ -467,6 +487,26 @@ VALUES int rowsAffected = cmd.ExecuteNonQuery(); Console.WriteLine($"🔒 Passwort für Benutzer '{username}' zurückgesetzt (Rows affected: {rowsAffected})"); } + + public void UpdateLoginZeiten(User user) + { + using var connection = new SqliteConnection($"Data Source={_dbPath}"); + connection.Open(); + + var cmd = connection.CreateCommand(); + cmd.CommandText = @" + UPDATE Benutzer + SET LetzterLogin = $LetzterLogin, + VorletzterLogin = $VorletzterLogin + WHERE Username = $Username; + "; + + cmd.Parameters.AddWithValue("$LetzterLogin", user.LetzterLogin.ToString("o")); + cmd.Parameters.AddWithValue("$VorletzterLogin", user.VorletzterLogin.ToString("o")); + cmd.Parameters.AddWithValue("$Username", user.Username); + + cmd.ExecuteNonQuery(); + } public async Task> GetEintraegeFuerMitarbeiterAsync(string name) { @@ -504,6 +544,43 @@ VALUES return eintraege; } + public async Task StelleDatenbankstrukturSicherAsync() + { + using var connection = new SqliteConnection($"Data Source={_dbPath}"); + await connection.OpenAsync(); + + //Überprüfung ob die Spalte "Voletzter Login" bereits besteht + var checkCmd = connection.CreateCommand(); + checkCmd.CommandText = "PRAGMA table_info(Benutzer);"; + + var reader = await checkCmd.ExecuteReaderAsync(); + bool spalteExistiert = false; + + while (await reader.ReadAsync()) + { + if (reader.GetString(1).Equals("Vorletzer Login", StringComparison.OrdinalIgnoreCase)) + { + spalteExistiert = true; + break; + } + } + + await reader.DisposeAsync(); + + if (!spalteExistiert) + { + var alterCmd = connection.CreateCommand(); + alterCmd.CommandText = "ALTER TABLE Benutzer ADD COLUMN VorletzterLogin TEXT;"; + await alterCmd.ExecuteNonQueryAsync(); + + Console.WriteLine("🛠 Spalte 'VorletzterLogin' wurde zur Tabelle 'Benutzer' hinzugefügt."); + } + else + { + Console.WriteLine("✅ Spalte 'VorletzterLogin' ist bereits vorhanden."); + } + } + public async Task UpdateStatusUndKommentarAsync(int id, bool erledigt, string mitarbeiterKommentar) { using var connection = new SqliteConnection($"Data Source={_dbPath}"); diff --git a/ChronoFlow.View/Admin/AlleProjekteView.axaml b/ChronoFlow.View/Admin/AlleProjekteView.axaml index eb3f9db..1f13717 100644 --- a/ChronoFlow.View/Admin/AlleProjekteView.axaml +++ b/ChronoFlow.View/Admin/AlleProjekteView.axaml @@ -3,29 +3,60 @@ xmlns:model1="clr-namespace:ChronoFlow.Model;assembly=ChronoFlow.Model" x:Class="ChronoFlow.View.Admin.AlleProjekteView"> - + + + - + + + - - - - - - -