From b6ef64a766692bb026517ec464a70a0938445484 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 19:40:42 +0200 Subject: [PATCH 01/10] new audit log --- Moonlight/App/Models/Log/LogData.cs | 7 ++++ Moonlight/App/Services/DomainService.cs | 18 +++++++-- .../Services/LogServices/AuditLogService.cs | 26 +++++++++++- Moonlight/App/Services/ServerService.cs | 40 +++++++++++++++---- Moonlight/App/Services/TotpService.cs | 13 ++++-- Moonlight/App/Services/UserService.cs | 22 +++++++--- .../AuditLogEntryChangePassword.razor | 9 +++-- .../AuditLogEntryChangePowerState.razor | 11 ++--- .../AuditLogEntrys/AuditLogEntryLogin.razor | 9 +++-- .../AuditLogEntryRegister.razor | 9 +++-- Moonlight/Shared/Views/Profile/Security.razor | 6 +-- 11 files changed, 130 insertions(+), 40 deletions(-) create mode 100644 Moonlight/App/Models/Log/LogData.cs diff --git a/Moonlight/App/Models/Log/LogData.cs b/Moonlight/App/Models/Log/LogData.cs new file mode 100644 index 00000000..645a666f --- /dev/null +++ b/Moonlight/App/Models/Log/LogData.cs @@ -0,0 +1,7 @@ +namespace Moonlight.App.Models.Log; + +public class LogData +{ + public Type Type { get; set; } + public string Value { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Services/DomainService.cs b/Moonlight/App/Services/DomainService.cs index b2b2b1fb..4bdbf9b3 100644 --- a/Moonlight/App/Services/DomainService.cs +++ b/Moonlight/App/Services/DomainService.cs @@ -169,7 +169,11 @@ public class DomainService })); } - await AuditLogService.Log(AuditLogType.AddDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.AddDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } public async Task UpdateDnsRecord(Domain d, DnsRecord dnsRecord) @@ -199,7 +203,11 @@ public class DomainService })); } - await AuditLogService.Log(AuditLogType.UpdateDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.UpdateDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } public async Task DeleteDnsRecord(Domain d, DnsRecord dnsRecord) @@ -210,7 +218,11 @@ public class DomainService await Client.Zones.DnsRecords.DeleteAsync(domain.SharedDomain.CloudflareId, dnsRecord.Id) ); - await AuditLogService.Log(AuditLogType.DeleteDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.DeleteDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } private Domain EnsureData(Domain domain) diff --git a/Moonlight/App/Services/LogServices/AuditLogService.cs b/Moonlight/App/Services/LogServices/AuditLogService.cs index 7e32f588..ac9c8845 100644 --- a/Moonlight/App/Services/LogServices/AuditLogService.cs +++ b/Moonlight/App/Services/LogServices/AuditLogService.cs @@ -1,4 +1,5 @@ using Moonlight.App.Database.Entities.LogsEntries; +using Moonlight.App.Models.Log; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Services.Sessions; @@ -19,16 +20,18 @@ public class AuditLogService HttpContextAccessor = httpContextAccessor; } - public Task Log(AuditLogType type, params object[] data) + public Task Log(AuditLogType type, Action data) { var ip = GetIp(); + var al = new AuditLogParameters(); + data(al); var entry = new AuditLogEntry() { Ip = ip, Type = type, System = false, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); @@ -62,4 +65,23 @@ public class AuditLogService return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString(); } + + public class AuditLogParameters + { + private List Data = new List(); + + public void Add(object data) + { + Data.Add(new LogData() + { + Type = typeof(T), + Value = data.ToString() + }); + } + + internal string Build() + { + return JsonConvert.SerializeObject(Data); + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index 2f69fd7b..84522e8e 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -96,7 +96,11 @@ public class ServerService Action = rawSignal }); - await AuditLogService.Log(AuditLogType.ChangePowerState, new[] { server.Uuid.ToString(), rawSignal }); + await AuditLogService.Log(AuditLogType.ChangePowerState, x => + { + x.Add(server.Uuid); + x.Add(rawSignal); + }); } public async Task CreateBackup(Server server) @@ -126,7 +130,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.CreateBackup, - new[] { serverData.Uuid.ToString(), backup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(backup.Uuid); + }); return backup; } @@ -164,7 +172,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.RestoreBackup, - new[] { s.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(serverBackup.Uuid); + }); } public async Task DeleteBackup(Server server, ServerBackup serverBackup) @@ -186,7 +198,11 @@ public class ServerService await MessageService.Emit("wings.backups.delete", backup); await AuditLogService.Log(AuditLogType.DeleteBackup, - new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(backup.Uuid); + }); } public async Task DownloadBackup(Server s, ServerBackup serverBackup) @@ -200,7 +216,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.DownloadBackup, - new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(serverBackup.Uuid); + }); return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}"; } @@ -305,7 +325,10 @@ public class ServerService StartOnCompletion = false }); - await AuditLogService.Log(AuditLogType.CreateServer, newServerData.Uuid.ToString()); + await AuditLogService.Log(AuditLogType.CreateServer, x => + { + x.Add(newServerData.Uuid); + }); return newServerData; } @@ -325,7 +348,10 @@ public class ServerService await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/reinstall", null); - await AuditLogService.Log(AuditLogType.ReinstallServer, server.Uuid.ToString()); + await AuditLogService.Log(AuditLogType.ReinstallServer, x => + { + x.Add(server.Uuid); + }); } public async Task SftpServerLogin(int serverId, int id, string password) diff --git a/Moonlight/App/Services/TotpService.cs b/Moonlight/App/Services/TotpService.cs index 0e359fec..caffc7a7 100644 --- a/Moonlight/App/Services/TotpService.cs +++ b/Moonlight/App/Services/TotpService.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Models.Misc; +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Misc; using Moonlight.App.Repositories; using Moonlight.App.Services.LogServices; using Moonlight.App.Services.Sessions; @@ -51,7 +52,10 @@ public class TotpService UserRepository.Update(user); - await AuditLogService.Log(AuditLogType.EnableTotp, user.Email); + await AuditLogService.Log(AuditLogType.EnableTotp, x => + { + x.Add(user.Email); + }); } public async Task EnforceTotpLogin() @@ -70,7 +74,10 @@ public class TotpService UserRepository.Update(user); - await AuditLogService.Log(AuditLogType.DisableTotp, user.Email); + await AuditLogService.Log(AuditLogType.DisableTotp,x => + { + x.Add(user.Email); + }); } private string GenerateSecret() diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index 2cf233ea..c70ae8e9 100644 --- a/Moonlight/App/Services/UserService.cs +++ b/Moonlight/App/Services/UserService.cs @@ -77,7 +77,10 @@ public class UserService }); await MailService.SendMail(user!, "register", values => {}); - await AuditLogService.Log(AuditLogType.Register, user.Email); + await AuditLogService.Log(AuditLogType.Register, x => + { + x.Add(user.Email); + }); return await GenerateToken(user); } @@ -125,7 +128,10 @@ public class UserService if (totpCodeValid) { - await AuditLogService.Log(AuditLogType.Login, email); + await AuditLogService.Log(AuditLogType.Login, x => + { + x.Add(email); + }); return await GenerateToken(user, true); } else @@ -136,7 +142,10 @@ public class UserService } else { - await AuditLogService.Log(AuditLogType.Login, email); + await AuditLogService.Log(AuditLogType.Login, x => + { + x.Add(email); + }); return await GenerateToken(user!, true); } } @@ -160,7 +169,10 @@ public class UserService values.Add("Location", "In your walls"); }); - await AuditLogService.Log(AuditLogType.ChangePassword, user.Email); + await AuditLogService.Log(AuditLogType.ChangePassword, x => + { + x.Add(user.Email); + }); } } @@ -218,7 +230,7 @@ public class UserService var newPassword = StringHelper.GenerateString(16); await ChangePassword(user, newPassword, true); - await AuditLogService.Log(AuditLogType.PasswordReset); + await AuditLogService.Log(AuditLogType.PasswordReset, x => {}); await MailService.SendMail(user, "passwordReset", values => { diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor index b3ffcd8f..f9ee3ac8 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - Password change for @(Data[0]) + Password change for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor index 95400158..9dcafe02 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor @@ -2,6 +2,7 @@ @using Moonlight.App.Helpers @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @using Moonlight.App.Repositories.Servers @inject ServerRepository ServerRepository @@ -18,11 +19,11 @@
@if (Server == null) { - Change power state for @(Data[0]) to @(Data[1]) + Change power state for @(Data[0].Value) to @(Data[1].Value) } else { - Change power state for @(Server.Name) to @(Data[1]) + Change power state for @(Server.Name) to @(Data[1].Value) }
@@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private Server? Server; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - Server = ServerRepository.Get().FirstOrDefault(x => x.Uuid == Guid.Parse(Data[0])); + Server = ServerRepository.Get().FirstOrDefault(x => x.Uuid == Guid.Parse(Data[0].Value)); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor index c215f4df..810a3568 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - New login for @(Data[0]) + New login for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor index 43cc89a3..846f0d86 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - Register for @(Data[0]) + Register for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Views/Profile/Security.razor b/Moonlight/Shared/Views/Profile/Security.razor index e648de9d..db0bf9f8 100644 --- a/Moonlight/Shared/Views/Profile/Security.razor +++ b/Moonlight/Shared/Views/Profile/Security.razor @@ -236,7 +236,7 @@ private async void Enable() { - await AuditLogService.Log(AuditLogType.EnableTotp, "Totp enabled"); + await AuditLogService.Log(AuditLogType.EnableTotp, x => x.Add("Totp enabled")); await TotpService.Enable(); TotpEnabled = await TotpService.GetEnabled(); TotpSecret = await TotpService.GetSecret(); @@ -262,7 +262,7 @@ private async void Disable() { - await AuditLogService.Log(AuditLogType.DisableTotp, "Totp disabled"); + await AuditLogService.Log(AuditLogType.DisableTotp, x => x.Add("Totp disabled")); await TotpService.Disable(); NavigationManager.NavigateTo(NavigationManager.Uri, true); } @@ -286,7 +286,7 @@ { await UserService.ChangePassword(User, Password); - await AuditLogService.Log(AuditLogType.PasswordChange, "The password has been set to a new one"); + await AuditLogService.Log(AuditLogType.PasswordChange, x => x.Add("The password has been set to a new one")); // Reload to make the user login again NavigationManager.NavigateTo(NavigationManager.Uri, true); From 5b807a667d6c4fcb9afe35d63b885f39305c4083 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 19:51:29 +0200 Subject: [PATCH 02/10] error log --- .../Services/LogServices/ErrorLogService.cs | 33 ++++++++++++++++--- Moonlight/App/Services/ServerService.cs | 6 +++- .../App/Services/Sessions/IdentityService.cs | 4 +-- .../ComponentErrorBoundary.razor | 2 +- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Moonlight/App/Services/LogServices/ErrorLogService.cs b/Moonlight/App/Services/LogServices/ErrorLogService.cs index 6c419450..4328c95a 100644 --- a/Moonlight/App/Services/LogServices/ErrorLogService.cs +++ b/Moonlight/App/Services/LogServices/ErrorLogService.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Reflection; using Moonlight.App.Database.Entities.LogsEntries; +using Moonlight.App.Models.Log; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Services.Sessions; using Newtonsoft.Json; @@ -18,15 +19,17 @@ public class ErrorLogService HttpContextAccessor = httpContextAccessor; } - public Task Log(Exception exception, params object[] objects) + public Task Log(Exception exception, Action data) { var ip = GetIp(); + var al = new ErrorLogParameters(); + data(al); var entry = new ErrorLogEntry() { Ip = ip, System = false, - JsonData = !objects.Any() ? "" : JsonConvert.SerializeObject(objects), + JsonData = al.Build(), Class = NameOfCallingClass(), Stacktrace = exception.ToStringDemystified() }; @@ -36,12 +39,15 @@ public class ErrorLogService return Task.CompletedTask; } - public Task LogSystem(Exception exception, params object[] objects) + public Task LogSystem(Exception exception, Action data) { + var al = new ErrorLogParameters(); + data(al); + var entry = new ErrorLogEntry() { System = true, - JsonData = !objects.Any() ? "" : JsonConvert.SerializeObject(objects), + JsonData = al.Build(), Class = NameOfCallingClass(), Stacktrace = exception.ToStringDemystified() }; @@ -87,4 +93,23 @@ public class ErrorLogService return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString(); } + + public class ErrorLogParameters + { + private List Data = new List(); + + public void Add(object data) + { + Data.Add(new LogData() + { + Type = typeof(T), + Value = data.ToString() + }); + } + + internal string Build() + { + return JsonConvert.SerializeObject(Data); + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index 84522e8e..71c37784 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -334,7 +334,11 @@ public class ServerService } catch (Exception e) { - await ErrorLogService.Log(e, new[] { newServerData.Uuid.ToString(), node.Id.ToString() }); + await ErrorLogService.Log(e, x => + { + x.Add(newServerData.Uuid); + x.Add(node.Id); + }); ServerRepository.Delete(newServerData); diff --git a/Moonlight/App/Services/Sessions/IdentityService.cs b/Moonlight/App/Services/Sessions/IdentityService.cs index bce93828..eaeac7b1 100644 --- a/Moonlight/App/Services/Sessions/IdentityService.cs +++ b/Moonlight/App/Services/Sessions/IdentityService.cs @@ -94,7 +94,7 @@ public class IdentityService } catch (Exception e) { - await ErrorLogService.Log(e); + await ErrorLogService.Log(e, x => {}); return null; } @@ -130,7 +130,7 @@ public class IdentityService } catch (Exception e) { - await ErrorLogService.Log(e); + await ErrorLogService.Log(e, x => {}); return null; } } diff --git a/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor b/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor index d8f29c90..c540c4c5 100644 --- a/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor +++ b/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor @@ -53,7 +53,7 @@ else { receivedExceptions.Add(exception); - await ErrorLogService.Log(exception); + await ErrorLogService.Log(exception, x => {}); await base.OnErrorAsync(exception); } From e80af275f7d0e96874b79d845c99f4d8dbefafa0 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 19:55:11 +0200 Subject: [PATCH 03/10] audit log (I forgot) --- Moonlight/App/Services/LogServices/AuditLogService.cs | 7 +++++-- Moonlight/App/Services/UserService.cs | 10 ++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Moonlight/App/Services/LogServices/AuditLogService.cs b/Moonlight/App/Services/LogServices/AuditLogService.cs index ac9c8845..4b0fdf87 100644 --- a/Moonlight/App/Services/LogServices/AuditLogService.cs +++ b/Moonlight/App/Services/LogServices/AuditLogService.cs @@ -39,13 +39,16 @@ public class AuditLogService return Task.CompletedTask; } - public Task LogSystem(AuditLogType type, params object[] data) + public Task LogSystem(AuditLogType type, Action data) { + var al = new AuditLogParameters(); + data(al); + var entry = new AuditLogEntry() { Type = type, System = true, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index c70ae8e9..d26be75d 100644 --- a/Moonlight/App/Services/UserService.cs +++ b/Moonlight/App/Services/UserService.cs @@ -158,7 +158,10 @@ public class UserService if (isSystemAction) { - await AuditLogService.LogSystem(AuditLogType.ChangePassword, user.Email); + await AuditLogService.LogSystem(AuditLogType.ChangePassword, x=> + { + x.Add(user.Email); + }); } else { @@ -188,7 +191,10 @@ public class UserService if (BCrypt.Net.BCrypt.Verify(password, user.Password)) { - await AuditLogService.LogSystem(AuditLogType.Login, user.Email); + await AuditLogService.LogSystem(AuditLogType.Login, x => + { + x.Add(user.Email); + }); return user; } From c7a31d6e05f2e46333696290244e1aae6bcd7a8c Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 20:06:06 +0200 Subject: [PATCH 04/10] security log --- .../Api/Moonlight/ResourcesController.cs | 5 ++- .../LogServices/SecurityLogService.cs | 34 ++++++++++++++++--- Moonlight/App/Services/OneTimeJwtService.cs | 5 ++- Moonlight/App/Services/ServerService.cs | 5 ++- .../App/Services/Sessions/IdentityService.cs | 5 ++- Moonlight/App/Services/UserService.cs | 29 +++++++++++++--- 6 files changed, 70 insertions(+), 13 deletions(-) diff --git a/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs b/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs index a02762c5..52750c40 100644 --- a/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs +++ b/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs @@ -21,7 +21,10 @@ public class ResourcesController : Controller { if (name.Contains("..")) { - await SecurityLogService.Log(SecurityLogType.PathTransversal, name); + await SecurityLogService.Log(SecurityLogType.PathTransversal, x => + { + x.Add(name); + }); return NotFound(); } diff --git a/Moonlight/App/Services/LogServices/SecurityLogService.cs b/Moonlight/App/Services/LogServices/SecurityLogService.cs index d276a2b9..f58fa198 100644 --- a/Moonlight/App/Services/LogServices/SecurityLogService.cs +++ b/Moonlight/App/Services/LogServices/SecurityLogService.cs @@ -1,4 +1,5 @@ using Moonlight.App.Database.Entities.LogsEntries; +using Moonlight.App.Models.Log; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Services.Sessions; @@ -17,16 +18,18 @@ public class SecurityLogService HttpContextAccessor = httpContextAccessor; } - public Task Log(SecurityLogType type, params object[] data) + public Task Log(SecurityLogType type, Action data) { var ip = GetIp(); + var al = new SecurityLogParameters(); + data(al); var entry = new SecurityLogEntry() { Ip = ip, Type = type, System = false, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); @@ -34,13 +37,16 @@ public class SecurityLogService return Task.CompletedTask; } - public Task LogSystem(SecurityLogType type, params object[] data) + public Task LogSystem(SecurityLogType type, Action data) { + var al = new SecurityLogParameters(); + data(al); + var entry = new SecurityLogEntry() { Type = type, System = true, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); @@ -60,4 +66,24 @@ public class SecurityLogService return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString(); } + + + public class SecurityLogParameters + { + private List Data = new List(); + + public void Add(object data) + { + Data.Add(new LogData() + { + Type = typeof(T), + Value = data.ToString() + }); + } + + internal string Build() + { + return JsonConvert.SerializeObject(Data); + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/OneTimeJwtService.cs b/Moonlight/App/Services/OneTimeJwtService.cs index 871a1b02..0f70d597 100644 --- a/Moonlight/App/Services/OneTimeJwtService.cs +++ b/Moonlight/App/Services/OneTimeJwtService.cs @@ -76,7 +76,10 @@ public class OneTimeJwtService } catch (SignatureVerificationException) { - await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, token); + await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, x => + { + x.Add(token); + }); return null; } catch (Exception e) diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index 71c37784..7969bd78 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -364,7 +364,10 @@ public class ServerService if (server == null) { - await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, serverId); + await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, x => + { + x.Add(id); + }); throw new Exception("Server not found"); } diff --git a/Moonlight/App/Services/Sessions/IdentityService.cs b/Moonlight/App/Services/Sessions/IdentityService.cs index eaeac7b1..f35519e1 100644 --- a/Moonlight/App/Services/Sessions/IdentityService.cs +++ b/Moonlight/App/Services/Sessions/IdentityService.cs @@ -89,7 +89,10 @@ public class IdentityService } catch (SignatureVerificationException) { - await SecurityLogService.Log(SecurityLogType.ManipulatedJwt, token); + await SecurityLogService.Log(SecurityLogType.ManipulatedJwt, x => + { + x.Add(token); + }); return null; } catch (Exception e) diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index d26be75d..60ec0a9d 100644 --- a/Moonlight/App/Services/UserService.cs +++ b/Moonlight/App/Services/UserService.cs @@ -94,7 +94,11 @@ public class UserService if (user == null) { - await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password }); + await SecurityLogService.Log(SecurityLogType.LoginFail, x => + { + x.Add(email); + x.Add(password); + }); throw new DisplayException("Email and password combination not found"); } @@ -103,7 +107,11 @@ public class UserService return user.TotpEnabled; } - await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password }); + await SecurityLogService.Log(SecurityLogType.LoginFail, x => + { + x.Add(email); + x.Add(password); + }); throw new DisplayException("Email and password combination not found");; } @@ -136,7 +144,11 @@ public class UserService } else { - await SecurityLogService.Log(SecurityLogType.LoginFail, new[] { email, password }); + await SecurityLogService.Log(SecurityLogType.LoginFail, x => + { + x.Add(email); + x.Add(password); + }); throw new DisplayException("2FA code invalid"); } } @@ -185,7 +197,10 @@ public class UserService if (user == null) { - await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, id); + await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, x => + { + x.Add(id); + }); throw new Exception("Invalid username"); } @@ -198,7 +213,11 @@ public class UserService return user; } - await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, new[] { id.ToString(), password }); + await SecurityLogService.LogSystem(SecurityLogType.SftpBruteForce, x => + { + x.Add(id); + x.Add(password); + }); throw new Exception("Invalid userid or password"); } From 5d8796299c005d947466b125a6eef567a7997548 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:07:55 +0200 Subject: [PATCH 05/10] force password change after login --- Moonlight/App/Models/Forms/PasswordModel.cs | 10 +++ Moonlight/App/Models/Misc/UserStatus.cs | 3 +- .../Components/Auth/PasswordChangeView.razor | 64 +++++++++++++++++++ Moonlight/Shared/Layouts/MainLayout.razor | 4 ++ Moonlight/resources/lang/de_de.lang | 2 + Moonlight/resources/mail/passwordChange.html | 53 +++++++++++++++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 Moonlight/App/Models/Forms/PasswordModel.cs create mode 100644 Moonlight/Shared/Components/Auth/PasswordChangeView.razor create mode 100644 Moonlight/resources/mail/passwordChange.html diff --git a/Moonlight/App/Models/Forms/PasswordModel.cs b/Moonlight/App/Models/Forms/PasswordModel.cs new file mode 100644 index 00000000..237f6a43 --- /dev/null +++ b/Moonlight/App/Models/Forms/PasswordModel.cs @@ -0,0 +1,10 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms; + +public class PasswordModel +{ + [Required(ErrorMessage = "You need to enter a password")] + [MinLength(8, ErrorMessage = "You need to enter a password with minimum 8 characters in lenght")] + public string Password { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Misc/UserStatus.cs b/Moonlight/App/Models/Misc/UserStatus.cs index 22bf70c6..a270ead5 100644 --- a/Moonlight/App/Models/Misc/UserStatus.cs +++ b/Moonlight/App/Models/Misc/UserStatus.cs @@ -9,5 +9,6 @@ public enum UserStatus Warned, Banned, Disabled, - DataPending + DataPending, + PasswordPending } \ No newline at end of file diff --git a/Moonlight/Shared/Components/Auth/PasswordChangeView.razor b/Moonlight/Shared/Components/Auth/PasswordChangeView.razor new file mode 100644 index 00000000..f57d1aa7 --- /dev/null +++ b/Moonlight/Shared/Components/Auth/PasswordChangeView.razor @@ -0,0 +1,64 @@ +@using Moonlight.App.Services +@using Moonlight.App.Models.Forms +@using Moonlight.App.Services.Sessions +@using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Misc +@using Moonlight.App.Repositories + +@inject SmartTranslateService SmartTranslateService +@inject IdentityService IdentityService +@inject UserService UserService +@inject UserRepository UserRepository +@inject NavigationManager NavigationManager + +
+
+
+
+ + +
+

+ Change your password +

+
+ You need to change your password in order to use moonlight +
+
+ +
+
+ +
+ +
+ +
+
+ +
+
+
+
+
+
+ +@code { + private PasswordModel Password = new(); + private User User; + + private async Task Load(LazyLoader loader) + { + User = await IdentityService.Get(); + } + + private async Task DoChange() + { + await UserService.ChangePassword(User, Password.Password); + User.Status = UserStatus.Unverified; + UserRepository.Update(User); + NavigationManager.NavigateTo(NavigationManager.Uri, true); + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Layouts/MainLayout.razor b/Moonlight/Shared/Layouts/MainLayout.razor index b2de0364..1c2303af 100644 --- a/Moonlight/Shared/Layouts/MainLayout.razor +++ b/Moonlight/Shared/Layouts/MainLayout.razor @@ -79,6 +79,10 @@ { } + else if (User.Status == UserStatus.PasswordPending) + { + + } else { @Body diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index 0cfc0d21..c7b639d8 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -462,3 +462,5 @@ Create subscription;Create subscription Options;Options Amount;Amount Do you really want to delete it?;Do you really want to delete it? +Change your password;Change your password +You need to change your password in order to use moonlight;You need to change your password in order to use moonlight diff --git a/Moonlight/resources/mail/passwordChange.html b/Moonlight/resources/mail/passwordChange.html new file mode 100644 index 00000000..ae3e5a12 --- /dev/null +++ b/Moonlight/resources/mail/passwordChange.html @@ -0,0 +1,53 @@ + + + + + Moonlight password change + + +
+ + + + + + + + + + + + +
+
+
+ + Logo + +
+
+

Hey {{FirstName}}, your password has been changed

+

If this was not you please contact us. Also here is the data we collected.

+

IP: {{Ip}}

+

Device: {{Device}}

+

Location: {{Location}}

+
+ Open Moonlight + +
+
+

You need help?

+

We are happy to help!

+

More information at + endelon.link/support. +

+
+

Copyright 2023 Endelon Hosting

+
+
+ + \ No newline at end of file From 49e75c5a8d9f36fd263e86a5e2f45d15e02f69e6 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:22:54 +0200 Subject: [PATCH 06/10] require name before use (--> user status 7) --- Moonlight/App/Models/Forms/NameModel.cs | 14 ++++ .../Components/Auth/UserDataSetView.razor | 67 +++++++++++++++++++ Moonlight/Shared/Layouts/MainLayout.razor | 4 ++ Moonlight/resources/lang/de_de.lang | 3 + 4 files changed, 88 insertions(+) create mode 100644 Moonlight/App/Models/Forms/NameModel.cs create mode 100644 Moonlight/Shared/Components/Auth/UserDataSetView.razor diff --git a/Moonlight/App/Models/Forms/NameModel.cs b/Moonlight/App/Models/Forms/NameModel.cs new file mode 100644 index 00000000..17d832ab --- /dev/null +++ b/Moonlight/App/Models/Forms/NameModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms; + +public class NameModel +{ + [Required] + [MinLength(2, ErrorMessage = "Do you think, that works?")] + public string FirstName { get; set; } + + [Required] + [MinLength(2, ErrorMessage = "Do you think, that works?")] + public string LastName { get; set; } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Auth/UserDataSetView.razor b/Moonlight/Shared/Components/Auth/UserDataSetView.razor new file mode 100644 index 00000000..d1191ec1 --- /dev/null +++ b/Moonlight/Shared/Components/Auth/UserDataSetView.razor @@ -0,0 +1,67 @@ +@using Microsoft.AspNetCore.Components +@using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Forms +@using Moonlight.App.Models.Misc +@using Moonlight.App.Repositories +@using Moonlight.App.Services +@using Moonlight.App.Services.Sessions + +@inject IdentityService IdentityService +@inject UserRepository UserRepository +@inject SmartTranslateService SmartTranslateService +@inject NavigationManager NavigationManager + +
+
+
+
+ + +
+

+ Enter your information +

+
+ You need to enter your full name in order to use moonlight +
+
+ +
+
+ +
+ +
+ +
+
+ + +
+
+
+
+
+
+ +@code { + private User User; + private NameModel Name = new (); + + private async Task Load(LazyLoader loader) + { + User = await IdentityService.Get(); + } + + private async Task SetName() + { + User.FirstName = Name.FirstName; + User.LastName = Name.LastName; + User.Status = UserStatus.Unverified; + + UserRepository.Update(User); + NavigationManager.NavigateTo(NavigationManager.Uri, true); + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Layouts/MainLayout.razor b/Moonlight/Shared/Layouts/MainLayout.razor index 1c2303af..5345b49a 100644 --- a/Moonlight/Shared/Layouts/MainLayout.razor +++ b/Moonlight/Shared/Layouts/MainLayout.razor @@ -83,6 +83,10 @@ { } + else if (User.Status == UserStatus.DataPending) + { + + } else { @Body diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index c7b639d8..02ca6ef0 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -464,3 +464,6 @@ Amount;Amount Do you really want to delete it?;Do you really want to delete it? Change your password;Change your password You need to change your password in order to use moonlight;You need to change your password in order to use moonlight +You need to enter your full name in order to use moonlight;You need to enter your full name in order to use moonlight +Enter your information;Enter your information +The field FirstName must be a string or array type with a minimum length of '2'.;The field FirstName must be a string or array type with a minimum length of '2'. From bed1c3df05e2c20937c46eef008c482270d33634 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 21:39:26 +0200 Subject: [PATCH 07/10] Update Index.razor --- Moonlight/Shared/Views/Profile/Index.razor | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Moonlight/Shared/Views/Profile/Index.razor b/Moonlight/Shared/Views/Profile/Index.razor index 030e4a3e..b9394503 100644 --- a/Moonlight/Shared/Views/Profile/Index.razor +++ b/Moonlight/Shared/Views/Profile/Index.razor @@ -15,7 +15,9 @@
-

Persönliche Daten

+

+ Personal information +

From a056e454fab34deaef958b08cf9736502b5f61e3 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Mon, 3 Apr 2023 23:52:03 +0200 Subject: [PATCH 08/10] typing indicator resize --- Moonlight/Shared/Views/Support.razor | 6 +++--- Moonlight/wwwroot/assets/css/utils.css | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Moonlight/Shared/Views/Support.razor b/Moonlight/Shared/Views/Support.razor index e674e422..994bc46a 100644 --- a/Moonlight/Shared/Views/Support.razor +++ b/Moonlight/Shared/Views/Support.razor @@ -105,9 +105,9 @@ {
-
-
-
+
+
+
@if (typingUsers.Length > 1) { diff --git a/Moonlight/wwwroot/assets/css/utils.css b/Moonlight/wwwroot/assets/css/utils.css index 872fe2c9..34777500 100644 --- a/Moonlight/wwwroot/assets/css/utils.css +++ b/Moonlight/wwwroot/assets/css/utils.css @@ -39,6 +39,6 @@ div.wave .dot:nth-child(3) { transform: initial; } 30% { - transform: translateY(-15px); + transform: translateY(-8px); } } \ No newline at end of file From 7f10c7576991946f785689bae7c29e7b47e7d3a9 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Tue, 4 Apr 2023 00:43:26 +0200 Subject: [PATCH 09/10] new support chat layout --- .../Shared/Views/Admin/Support/View.razor | 78 ++++++++++--------- Moonlight/Shared/Views/Support.razor | 38 +++++---- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/Moonlight/Shared/Views/Admin/Support/View.razor b/Moonlight/Shared/Views/Admin/Support/View.razor index fcf77c66..3921a686 100644 --- a/Moonlight/Shared/Views/Admin/Support/View.razor +++ b/Moonlight/Shared/Views/Admin/Support/View.razor @@ -22,11 +22,11 @@ {
-
+
-
+
@foreach (var message in Messages) { if (message.IsSystem || message.IsSupport) @@ -99,10 +99,10 @@ @if (typingUsers.Any()) { -
-
-
-
+
+
+
+
@if (typingUsers.Length > 1) { @@ -118,52 +118,56 @@ } } - +
-
- -
- - + + + + + + +
+ + + + + + +
-
-

+
+

User information

-
- - Firstname: @(User.FirstName) - +
+ + Name: @(User.FirstName) @User.LastName +
-
- - Lastname: @(User.LastName) - +
+ + Email: @(User.Email) +
-
- - Email: @(User.Email) - -
-
- +
+ - +
diff --git a/Moonlight/Shared/Views/Support.razor b/Moonlight/Shared/Views/Support.razor index 994bc46a..6a573121 100644 --- a/Moonlight/Shared/Views/Support.razor +++ b/Moonlight/Shared/Views/Support.razor @@ -13,7 +13,7 @@
-
+
@foreach (var message in Messages) { if (message.IsSystem || message.IsSupport) @@ -21,7 +21,7 @@
-
+
Logo
@@ -104,7 +104,7 @@ @if (typingUsers.Any()) { -
+
@@ -120,19 +120,27 @@ } -
-
- -
- - + + + + + + +
+ + + + + + +
From f5e98bf774b4a4046b07d353f38f0ca232c48890 Mon Sep 17 00:00:00 2001 From: Daniel Balk <67603460+Daniel-Balk@users.noreply.github.com> Date: Tue, 4 Apr 2023 01:07:19 +0200 Subject: [PATCH 10/10] removed upload button | changed overview layout --- .../Shared/Views/Admin/Support/Index.razor | 101 +++++++----------- .../Shared/Views/Admin/Support/View.razor | 4 +- Moonlight/Shared/Views/Support.razor | 4 +- 3 files changed, 42 insertions(+), 67 deletions(-) diff --git a/Moonlight/Shared/Views/Admin/Support/Index.razor b/Moonlight/Shared/Views/Admin/Support/Index.razor index 7e1d8b1a..355a863a 100644 --- a/Moonlight/Shared/Views/Admin/Support/Index.razor +++ b/Moonlight/Shared/Views/Admin/Support/Index.razor @@ -14,45 +14,53 @@
-
+
-

+

Open tickets

-
+
+
@if (Users.Any()) { foreach (var user in Users) { -
- - - - -
- - - - @{ - var lastMessage = MessageCache.ContainsKey(user) ? MessageCache[user] : null; - } - - @if (lastMessage == null) - { - No message sent yet - } - else - { - @(lastMessage.Message) - } - -
+
+ + + + + + + + +
+ + + + + + @(user.FirstName) @(user.LastName) + +
+ + @{ + var lastMessage = MessageCache.ContainsKey(user) ? MessageCache[user] : null; + } + + @if (lastMessage == null) + { + No message sent yet + } + else + { + @(lastMessage.Message) + } + +
+
} } else @@ -64,39 +72,6 @@
- -
- -
-

- Actions -

- -
- - - - - -
-
Project Briefing
- - -
- - Check out our - - - - Support Policy - -
- -
- -
-
-
diff --git a/Moonlight/Shared/Views/Admin/Support/View.razor b/Moonlight/Shared/Views/Admin/Support/View.razor index 3921a686..d114d935 100644 --- a/Moonlight/Shared/Views/Admin/Support/View.razor +++ b/Moonlight/Shared/Views/Admin/Support/View.razor @@ -122,11 +122,11 @@
-
+ diff --git a/Moonlight/Shared/Views/Support.razor b/Moonlight/Shared/Views/Support.razor index 6a573121..9ef48cf8 100644 --- a/Moonlight/Shared/Views/Support.razor +++ b/Moonlight/Shared/Views/Support.razor @@ -123,11 +123,11 @@
-
+