From 6807f2b6e6e81f0847953bd32e0f392e08698fcb Mon Sep 17 00:00:00 2001 From: "a.beging@eas-solutions.de" Date: Wed, 29 Apr 2026 15:57:30 +0200 Subject: [PATCH] Enhance audit logging: add new audit types for password reset and prospect image actions, and update related services to log these events Co-authored-by: Copilot --- .../Enums/AuditType.cs | 27 ++++++++++++++++++- FoodsharingSiegen.Server/Auth/AuthService.cs | 8 ++++++ FoodsharingSiegen.Server/Data/AuditHelper.cs | 10 +++++++ .../Data/Service/ProspectService.cs | 13 +++++++++ .../Data/Service/UserService.cs | 10 +++++-- .../Pages/ForgotPassword.razor | 2 ++ FoodsharingSiegen.Server/Pages/Users.razor.cs | 4 +++ 7 files changed, 71 insertions(+), 3 deletions(-) diff --git a/FoodsharingSiegen.Contracts/Enums/AuditType.cs b/FoodsharingSiegen.Contracts/Enums/AuditType.cs index f0a0b77..6d034fe 100644 --- a/FoodsharingSiegen.Contracts/Enums/AuditType.cs +++ b/FoodsharingSiegen.Contracts/Enums/AuditType.cs @@ -62,7 +62,32 @@ namespace FoodsharingSiegen.Contracts.Enums /// /// The remove interaction audit type /// - RemoveInteraction = 100 + RemoveInteraction = 100, + + /// + /// The delete prospect images audit type + /// + DeleteProspectImages = 110, + + /// + /// The view prospect images audit type + /// + ViewProspectImages = 120, + + /// + /// The upload prospect image audit type + /// + UploadProspectImage = 130, + + /// + /// The request password reset audit type + /// + RequestPasswordReset = 140, + + /// + /// The change own password audit type + /// + ChangeOwnPassword = 150 #endregion Prospects } diff --git a/FoodsharingSiegen.Server/Auth/AuthService.cs b/FoodsharingSiegen.Server/Auth/AuthService.cs index 6ff91c4..b2318ab 100644 --- a/FoodsharingSiegen.Server/Auth/AuthService.cs +++ b/FoodsharingSiegen.Server/Auth/AuthService.cs @@ -251,6 +251,14 @@ namespace FoodsharingSiegen.Server.Auth user.ResetToken = resetToken; user.ResetTokenExpiry = DateTime.UtcNow.AddMinutes(30); + Context.Audits?.Add(new Audit + { + Created = DateTime.Now, + Type = AuditType.RequestPasswordReset, + UserID = user.Id, + Data1 = user.Mail + }); + await Context.SaveChangesAsync(); var resetLink = $"{baseUri.TrimEnd('/')}/reset-password/{resetToken}"; diff --git a/FoodsharingSiegen.Server/Data/AuditHelper.cs b/FoodsharingSiegen.Server/Data/AuditHelper.cs index 5425cbe..f86df7b 100644 --- a/FoodsharingSiegen.Server/Data/AuditHelper.cs +++ b/FoodsharingSiegen.Server/Data/AuditHelper.cs @@ -37,6 +37,16 @@ namespace FoodsharingSiegen.Server.Data return $"hat dem Neuling {audit.Data1} folgendes hinzugefügt: {audit.Data2}"; case AuditType.RemoveInteraction: return $"hat eine Interaktion bei {audit.Data1} gelöscht."; + case AuditType.DeleteProspectImages: + return $"hat die Bilder von {audit.Data1} gelöscht."; + case AuditType.ViewProspectImages: + return $"hat die Bilder von {audit.Data1} angesehen."; + case AuditType.UploadProspectImage: + return $"hat ein Bild für {audit.Data1} hochgeladen."; + case AuditType.RequestPasswordReset: + return $"hat ein Passwort-Reset für {audit.Data1} angefordert."; + case AuditType.ChangeOwnPassword: + return $"hat das eigene Passwort geändert."; case AuditType.None: default: return $"{audit.Data1}, {audit.Data2}"; diff --git a/FoodsharingSiegen.Server/Data/Service/ProspectService.cs b/FoodsharingSiegen.Server/Data/Service/ProspectService.cs index 055f345..02ca414 100644 --- a/FoodsharingSiegen.Server/Data/Service/ProspectService.cs +++ b/FoodsharingSiegen.Server/Data/Service/ProspectService.cs @@ -290,6 +290,8 @@ namespace FoodsharingSiegen.Server.Data.Service await Context.ProspectImages!.AddAsync(image); await Context.SaveChangesAsync(); + await AuditService.Insert(AuditType.UploadProspectImage, prospect.Name); + return new(); } catch (Exception e) @@ -308,6 +310,16 @@ namespace FoodsharingSiegen.Server.Data.Service .OrderBy(x => x.Created) .ToListAsync(); + var prospectName = await Context.Prospects! + .Where(x => x.Id == prospectId) + .Select(x => x.Name) + .FirstOrDefaultAsync(); + + if (!string.IsNullOrEmpty(prospectName)) + { + await AuditService.Insert(AuditType.ViewProspectImages, prospectName); + } + return new(images); } catch (Exception e) @@ -329,6 +341,7 @@ namespace FoodsharingSiegen.Server.Data.Service if (prospect != null) { prospect.VerificationToken = null; // Clear token when images are deleted + await AuditService.Insert(AuditType.DeleteProspectImages, prospect.Name); } await Context.SaveChangesAsync(); diff --git a/FoodsharingSiegen.Server/Data/Service/UserService.cs b/FoodsharingSiegen.Server/Data/Service/UserService.cs index 4527a05..5b4b7f6 100644 --- a/FoodsharingSiegen.Server/Data/Service/UserService.cs +++ b/FoodsharingSiegen.Server/Data/Service/UserService.cs @@ -151,8 +151,14 @@ namespace FoodsharingSiegen.Server.Data.Service if (saveR < 1) return new(new Exception("Fehler beim Speichern")); - var auditData = CurrentUser?.Id == user.Id ? "sich selbst" : user.Mail; - await AuditService.Insert(AuditType.SetUserPassword, auditData); + if (CurrentUser?.Id == user.Id) + { + await AuditService.Insert(AuditType.ChangeOwnPassword); + } + else + { + await AuditService.Insert(AuditType.SetUserPassword, user.Mail); + } return new(); } diff --git a/FoodsharingSiegen.Server/Pages/ForgotPassword.razor b/FoodsharingSiegen.Server/Pages/ForgotPassword.razor index 8cbd374..3a56bc9 100644 --- a/FoodsharingSiegen.Server/Pages/ForgotPassword.razor +++ b/FoodsharingSiegen.Server/Pages/ForgotPassword.razor @@ -20,6 +20,8 @@ {
Wenn ein Benutzerkonto mit dieser E-Mail-Adresse existiert, wurde eine E-Mail mit weiteren Anweisungen versendet. +

+ Hinweis: Bitte überprüfe auch deinen Spam-Ordner, falls du künftige E-Mails nicht im regulären Posteingang findest.
Zurück zum Login diff --git a/FoodsharingSiegen.Server/Pages/Users.razor.cs b/FoodsharingSiegen.Server/Pages/Users.razor.cs index 9504d7e..f487841 100644 --- a/FoodsharingSiegen.Server/Pages/Users.razor.cs +++ b/FoodsharingSiegen.Server/Pages/Users.razor.cs @@ -126,6 +126,10 @@ namespace FoodsharingSiegen.Server.Pages await ConfirmDialog.ShowAsync(ModalService, "Bestätigen", $"Soll eine E-Mail zum Festlegen des Passworts an {user.Mail} gesendet werden?", async () => { await AuthService.InitiateInitialPasswordSetup(user.Mail, NavigationManager.BaseUri); + if (Notification != null) + { + await Notification.Success("E-Mail gesendet. Bitte weise den Benutzer darauf hin, auch den Spam-Ordner zu prüfen."); + } }); }