From 1cd0f0f96f17e956ccd888b97bd798e335e56531 Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Wed, 19 Jul 2023 20:07:57 +0200 Subject: [PATCH] Added security logs. Removed unsued log models. Added dynamisc config load system for development --- Moonlight/App/Database/DataContext.cs | 7 +- .../Entities/LogsEntries/AuditLogEntry.cs | 13 - .../Entities/LogsEntries/ErrorLogEntry.cs | 12 - .../Entities/LogsEntries/SecurityLogEntry.cs | 13 - .../App/Database/Entities/SecurityLog.cs | 8 + ...RemovedOldLogsAndAddedErrorLog.Designer.cs | 1068 +++++++++++++++++ ...18123232_RemovedOldLogsAndAddedErrorLog.cs | 111 ++ .../Migrations/DataContextModelSnapshot.cs | 107 +- Moonlight/App/Helpers/Logger.cs | 63 + Moonlight/App/Models/Misc/AuditLogType.cs | 27 - Moonlight/App/Models/Misc/SecurityLogType.cs | 9 - Moonlight/App/Perms/Permissions.cs | 7 + .../LogEntries/AuditLogEntryRepository.cs | 32 - .../LogEntries/ErrorLogEntryRepository.cs | 32 - .../LogEntries/SecurityLogEntryRepository.cs | 32 - Moonlight/App/Services/ConfigService.cs | 24 +- Moonlight/App/Services/UserService.cs | 3 + Moonlight/Moonlight.csproj | 4 + Moonlight/Program.cs | 4 - Moonlight/Properties/launchSettings.json | 38 +- .../AuditLogEntryChangePassword.razor | 58 - .../AuditLogEntryChangePowerState.razor | 58 - .../AuditLogEntrys/AuditLogEntryLogin.razor | 58 - .../AuditLogEntryRegister.razor | 58 - .../Navigations/AdminSecurityNavigation.razor | 5 + .../Shared/Views/Admin/Security/Logs.razor | 47 + 26 files changed, 1362 insertions(+), 536 deletions(-) delete mode 100644 Moonlight/App/Database/Entities/LogsEntries/AuditLogEntry.cs delete mode 100644 Moonlight/App/Database/Entities/LogsEntries/ErrorLogEntry.cs delete mode 100644 Moonlight/App/Database/Entities/LogsEntries/SecurityLogEntry.cs create mode 100644 Moonlight/App/Database/Entities/SecurityLog.cs create mode 100644 Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs create mode 100644 Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.cs delete mode 100644 Moonlight/App/Models/Misc/AuditLogType.cs delete mode 100644 Moonlight/App/Models/Misc/SecurityLogType.cs delete mode 100644 Moonlight/App/Repositories/LogEntries/AuditLogEntryRepository.cs delete mode 100644 Moonlight/App/Repositories/LogEntries/ErrorLogEntryRepository.cs delete mode 100644 Moonlight/App/Repositories/LogEntries/SecurityLogEntryRepository.cs delete mode 100644 Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor delete mode 100644 Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor delete mode 100644 Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor delete mode 100644 Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor create mode 100644 Moonlight/Shared/Views/Admin/Security/Logs.razor diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index 25547eb4..b2caec37 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -1,9 +1,7 @@ using Microsoft.EntityFrameworkCore; using Moonlight.App.Database.Entities; -using Moonlight.App.Database.Entities.LogsEntries; using Moonlight.App.Database.Entities.Notification; using Moonlight.App.Database.Interceptors; -using Moonlight.App.Models.Misc; using Moonlight.App.Services; namespace Moonlight.App.Database; @@ -27,10 +25,6 @@ public class DataContext : DbContext public DbSet ServerVariables { get; set; } public DbSet Users { get; set; } public DbSet LoadingMessages { get; set; } - public DbSet AuditLog { get; set; } - public DbSet ErrorLog { get; set; } - public DbSet SecurityLog { get; set; } - public DbSet SharedDomains { get; set; } public DbSet Domains { get; set; } public DbSet Revokes { get; set; } @@ -47,6 +41,7 @@ public class DataContext : DbContext public DbSet SupportChatMessages { get; set; } public DbSet IpBans { get; set; } public DbSet PermissionGroups { get; set; } + public DbSet SecurityLogs { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { diff --git a/Moonlight/App/Database/Entities/LogsEntries/AuditLogEntry.cs b/Moonlight/App/Database/Entities/LogsEntries/AuditLogEntry.cs deleted file mode 100644 index 5b6f8085..00000000 --- a/Moonlight/App/Database/Entities/LogsEntries/AuditLogEntry.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Moonlight.App.Models.Misc; - -namespace Moonlight.App.Database.Entities.LogsEntries; - -public class AuditLogEntry -{ - public int Id { get; set; } - public AuditLogType Type { get; set; } - public string JsonData { get; set; } = ""; - public bool System { get; set; } - public string Ip { get; set; } = ""; - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/LogsEntries/ErrorLogEntry.cs b/Moonlight/App/Database/Entities/LogsEntries/ErrorLogEntry.cs deleted file mode 100644 index ea9b7ee4..00000000 --- a/Moonlight/App/Database/Entities/LogsEntries/ErrorLogEntry.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Moonlight.App.Database.Entities.LogsEntries; - -public class ErrorLogEntry -{ - public int Id { get; set; } - public string Stacktrace { get; set; } = ""; - public bool System { get; set; } - public string JsonData { get; set; } = ""; - public string Ip { get; set; } = ""; - public string Class { get; set; } = ""; - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/LogsEntries/SecurityLogEntry.cs b/Moonlight/App/Database/Entities/LogsEntries/SecurityLogEntry.cs deleted file mode 100644 index 9d1750bb..00000000 --- a/Moonlight/App/Database/Entities/LogsEntries/SecurityLogEntry.cs +++ /dev/null @@ -1,13 +0,0 @@ -using Moonlight.App.Models.Misc; - -namespace Moonlight.App.Database.Entities.LogsEntries; - -public class SecurityLogEntry -{ - public int Id { get; set; } - public bool System { get; set; } - public string Ip { get; set; } = ""; - public SecurityLogType Type { get; set; } - public string JsonData { get; set; } = ""; - public DateTime CreatedAt { get; set; } = DateTime.UtcNow; -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/SecurityLog.cs b/Moonlight/App/Database/Entities/SecurityLog.cs new file mode 100644 index 00000000..4d83890b --- /dev/null +++ b/Moonlight/App/Database/Entities/SecurityLog.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Database.Entities; + +public class SecurityLog +{ + public int Id { get; set; } + public string Text { get; set; } = ""; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; +} \ No newline at end of file diff --git a/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs b/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs new file mode 100644 index 00000000..63c7352f --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.Designer.cs @@ -0,0 +1,1068 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Moonlight.App.Database; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20230718123232_RemovedOldLogsAndAddedErrorLog")] + partial class RemovedOldLogsAndAddedErrorLog + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 64); + + modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ApiKey") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ApiUrl") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Host") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("CloudPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Data") + .HasColumnType("bigint"); + + b.Property("Ip") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NodeId") + .HasColumnType("int"); + + b.Property("Ongoing") + .HasColumnType("tinyint(1)"); + + b.HasKey("Id"); + + b.HasIndex("NodeId"); + + b.ToTable("DdosAttacks"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Default") + .HasColumnType("tinyint(1)"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.ToTable("DockerImages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("SharedDomainId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("OwnerId"); + + b.HasIndex("SharedDomainId"); + + b.ToTable("Domains"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Allocations") + .HasColumnType("int"); + + b.Property("BackgroundImageUrl") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ConfigFiles") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InstallDockerImage") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InstallEntrypoint") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InstallScript") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Startup") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StartupDetection") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StopCommand") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TagsJson") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Uuid") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.ToTable("Images"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("DefaultValue") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.ToTable("ImageVariables"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.IpBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Ip") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("IpBans"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("LoadingMessages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("WebSpaceId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WebSpaceId"); + + b.ToTable("Databases"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Markdown") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Title") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("NewsEntries"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Fqdn") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HttpPort") + .HasColumnType("int"); + + b.Property("MoonlightDaemonPort") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SftpPort") + .HasColumnType("int"); + + b.Property("Ssl") + .HasColumnType("tinyint(1)"); + + b.Property("Token") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("TokenId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Nodes"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("NodeId") + .HasColumnType("int"); + + b.Property("Port") + .HasColumnType("int"); + + b.Property("ServerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NodeId"); + + b.HasIndex("ServerId"); + + b.ToTable("NodeAllocations"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Action") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NotificationClientId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("NotificationClientId"); + + b.ToTable("NotificationActions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("UserId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("NotificationClients"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.PermissionGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("longblob"); + + b.HasKey("Id"); + + b.ToTable("PermissionGroups"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Identifier") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Revokes"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("SecurityLogs"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ArchiveId") + .HasColumnType("int"); + + b.Property("Cpu") + .HasColumnType("int"); + + b.Property("Disk") + .HasColumnType("bigint"); + + b.Property("DockerImageIndex") + .HasColumnType("int"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Installing") + .HasColumnType("tinyint(1)"); + + b.Property("IsArchived") + .HasColumnType("tinyint(1)"); + + b.Property("IsCleanupException") + .HasColumnType("tinyint(1)"); + + b.Property("MainAllocationId") + .HasColumnType("int"); + + b.Property("Memory") + .HasColumnType("bigint"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("NodeId") + .HasColumnType("int"); + + b.Property("OverrideStartup") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("Suspended") + .HasColumnType("tinyint(1)"); + + b.Property("Uuid") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveId"); + + b.HasIndex("ImageId"); + + b.HasIndex("MainAllocationId"); + + b.HasIndex("NodeId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Servers"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Bytes") + .HasColumnType("bigint"); + + b.Property("Created") + .HasColumnType("tinyint(1)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ServerId") + .HasColumnType("int"); + + b.Property("Uuid") + .HasColumnType("char(36)"); + + b.HasKey("Id"); + + b.HasIndex("ServerId"); + + b.ToTable("ServerBackups"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ServerId") + .HasColumnType("int"); + + b.Property("Value") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("ServerId"); + + b.ToTable("ServerVariables"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SharedDomain", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CloudflareId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("SharedDomains"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.StatisticsData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Chart") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Date") + .HasColumnType("datetime(6)"); + + b.Property("Value") + .HasColumnType("double"); + + b.HasKey("Id"); + + b.ToTable("Statistics"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Currency") + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("LimitsJson") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Price") + .HasColumnType("double"); + + b.Property("StripePriceId") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("StripeProductId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Attachment") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Content") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("QuestionType") + .HasColumnType("int"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportChatMessages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Admin") + .HasColumnType("tinyint(1)"); + + b.Property("City") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Country") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("CurrentSubscriptionId") + .HasColumnType("int"); + + b.Property("DiscordId") + .HasColumnType("bigint unsigned"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("HasRated") + .HasColumnType("tinyint(1)"); + + b.Property("LastIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastVisitedAt") + .HasColumnType("datetime(6)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("PermissionGroupId") + .HasColumnType("int"); + + b.Property("Permissions") + .IsRequired() + .HasColumnType("longblob"); + + b.Property("Rating") + .HasColumnType("int"); + + b.Property("RegisterIp") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ServerListLayoutJson") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("StreamerMode") + .HasColumnType("tinyint(1)"); + + b.Property("SubscriptionExpires") + .HasColumnType("datetime(6)"); + + b.Property("SubscriptionSince") + .HasColumnType("datetime(6)"); + + b.Property("SupportPending") + .HasColumnType("tinyint(1)"); + + b.Property("TokenValidTime") + .HasColumnType("datetime(6)"); + + b.Property("TotpEnabled") + .HasColumnType("tinyint(1)"); + + b.Property("TotpSecret") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UpdatedAt") + .HasColumnType("datetime(6)"); + + b.HasKey("Id"); + + b.HasIndex("CurrentSubscriptionId"); + + b.HasIndex("PermissionGroupId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CloudPanelId") + .HasColumnType("int"); + + b.Property("Domain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("VHostTemplate") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("CloudPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("WebSpaces"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => + { + b.HasOne("Moonlight.App.Database.Entities.Node", "Node") + .WithMany() + .HasForeignKey("NodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Node"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => + { + b.HasOne("Moonlight.App.Database.Entities.Image", null) + .WithMany("DockerImages") + .HasForeignKey("ImageId"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain") + .WithMany() + .HasForeignKey("SharedDomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Owner"); + + b.Navigation("SharedDomain"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => + { + b.HasOne("Moonlight.App.Database.Entities.Image", null) + .WithMany("Variables") + .HasForeignKey("ImageId"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => + { + b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") + .WithMany("Databases") + .HasForeignKey("WebSpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("WebSpace"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => + { + b.HasOne("Moonlight.App.Database.Entities.Node", null) + .WithMany("Allocations") + .HasForeignKey("NodeId"); + + b.HasOne("Moonlight.App.Database.Entities.Server", null) + .WithMany("Allocations") + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => + { + b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient") + .WithMany() + .HasForeignKey("NotificationClientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("NotificationClient"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => + { + b.HasOne("Moonlight.App.Database.Entities.ServerBackup", "Archive") + .WithMany() + .HasForeignKey("ArchiveId"); + + b.HasOne("Moonlight.App.Database.Entities.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId"); + + b.HasOne("Moonlight.App.Database.Entities.Node", "Node") + .WithMany() + .HasForeignKey("NodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Archive"); + + b.Navigation("Image"); + + b.Navigation("MainAllocation"); + + b.Navigation("Node"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b => + { + b.HasOne("Moonlight.App.Database.Entities.Server", null) + .WithMany("Backups") + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b => + { + b.HasOne("Moonlight.App.Database.Entities.Server", null) + .WithMany("Variables") + .HasForeignKey("ServerId"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Sender") + .WithMany() + .HasForeignKey("SenderId"); + + b.Navigation("Recipient"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => + { + b.HasOne("Moonlight.App.Database.Entities.Subscription", "CurrentSubscription") + .WithMany() + .HasForeignKey("CurrentSubscriptionId"); + + b.HasOne("Moonlight.App.Database.Entities.PermissionGroup", "PermissionGroup") + .WithMany() + .HasForeignKey("PermissionGroupId"); + + b.Navigation("CurrentSubscription"); + + b.Navigation("PermissionGroup"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => + { + b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") + .WithMany() + .HasForeignKey("CloudPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CloudPanel"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => + { + b.Navigation("DockerImages"); + + b.Navigation("Variables"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => + { + b.Navigation("Allocations"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => + { + b.Navigation("Allocations"); + + b.Navigation("Backups"); + + b.Navigation("Variables"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => + { + b.Navigation("Databases"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.cs b/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.cs new file mode 100644 index 00000000..4dbf8103 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230718123232_RemovedOldLogsAndAddedErrorLog.cs @@ -0,0 +1,111 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class RemovedOldLogsAndAddedErrorLog : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "AuditLog"); + + migrationBuilder.DropTable( + name: "ErrorLog"); + + migrationBuilder.DropTable( + name: "SecurityLog"); + + migrationBuilder.CreateTable( + name: "SecurityLogs", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Text = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SecurityLogs", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "SecurityLogs"); + + migrationBuilder.CreateTable( + name: "AuditLog", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Ip = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + JsonData = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + System = table.Column(type: "tinyint(1)", nullable: false), + Type = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_AuditLog", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "ErrorLog", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Class = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Ip = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + JsonData = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Stacktrace = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + System = table.Column(type: "tinyint(1)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ErrorLog", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "SecurityLog", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Ip = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + JsonData = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + System = table.Column(type: "tinyint(1)", nullable: false), + Type = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SecurityLog", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs index b14e3239..5d934c5d 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -241,95 +241,6 @@ namespace Moonlight.App.Database.Migrations b.ToTable("LoadingMessages"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("JsonData") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("System") - .HasColumnType("tinyint(1)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("AuditLog"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Class") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("JsonData") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Stacktrace") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("System") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.ToTable("ErrorLog"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("JsonData") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("System") - .HasColumnType("tinyint(1)"); - - b.Property("Type") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.ToTable("SecurityLog"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => { b.Property("Id") @@ -509,6 +420,24 @@ namespace Moonlight.App.Database.Migrations b.ToTable("Revokes"); }); + modelBuilder.Entity("Moonlight.App.Database.Entities.SecurityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Text") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("SecurityLogs"); + }); + modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => { b.Property("Id") diff --git a/Moonlight/App/Helpers/Logger.cs b/Moonlight/App/Helpers/Logger.cs index 8221e082..df88bfcb 100644 --- a/Moonlight/App/Helpers/Logger.cs +++ b/Moonlight/App/Helpers/Logger.cs @@ -1,46 +1,70 @@ using System.Diagnostics; using System.Reflection; +using Moonlight.App.Database; +using Moonlight.App.Services; +using Moonlight.App.Services.Files; using Serilog; namespace Moonlight.App.Helpers; public static class Logger { + // The private static instance of the config service, because we have no di here + private static ConfigService ConfigService = new(new StorageService()); + #region String method calls public static void Verbose(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Verbose("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } public static void Info(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Information("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } public static void Debug(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Debug("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } public static void Error(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Error("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } public static void Warn(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Warning("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } public static void Fatal(string message, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Fatal("{Message}", message); + + if(channel == "security") + LogSecurityInDb(message); } #endregion @@ -49,36 +73,54 @@ public static class Logger { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Verbose(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } public static void Info(Exception exception, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Information(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } public static void Debug(Exception exception, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Debug(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } public static void Error(Exception exception, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Error(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } public static void Warn(Exception exception, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Warning(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } public static void Fatal(Exception exception, string channel = "default") { Log.ForContext("SourceContext", GetNameOfCallingClass()) .Fatal(exception, ""); + + if(channel == "security") + LogSecurityInDb(exception); } #endregion @@ -105,4 +147,25 @@ public static class Logger return fullName; } + + + private static void LogSecurityInDb(Exception exception) + { + LogSecurityInDb(exception.ToStringDemystified()); + } + private static void LogSecurityInDb(string text) + { + Task.Run(() => + { + var dataContext = new DataContext(ConfigService); + + dataContext.SecurityLogs.Add(new() + { + Text = text + }); + + dataContext.SaveChanges(); + dataContext.Dispose(); + }); + } } \ No newline at end of file diff --git a/Moonlight/App/Models/Misc/AuditLogType.cs b/Moonlight/App/Models/Misc/AuditLogType.cs deleted file mode 100644 index a2ccf6d4..00000000 --- a/Moonlight/App/Models/Misc/AuditLogType.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Moonlight.App.Models.Misc; - -public enum AuditLogType -{ - Login, - Register, - ChangePassword, - ChangePowerState, - CreateBackup, - RestoreBackup, - DeleteBackup, - DownloadBackup, - CreateServer, - ReinstallServer, - CancelSubscription, - ApplySubscriptionCode, - EnableTotp, - DisableTotp, - AddDomainRecord, - UpdateDomainRecord, - DeleteDomainRecord, - PasswordReset, - CleanupEnabled, - CleanupDisabled, - CleanupTriggered, - PasswordChange, -} \ No newline at end of file diff --git a/Moonlight/App/Models/Misc/SecurityLogType.cs b/Moonlight/App/Models/Misc/SecurityLogType.cs deleted file mode 100644 index 74ea78c1..00000000 --- a/Moonlight/App/Models/Misc/SecurityLogType.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Moonlight.App.Models.Misc; - -public enum SecurityLogType -{ - ManipulatedJwt, - PathTransversal, - SftpBruteForce, - LoginFail -} \ No newline at end of file diff --git a/Moonlight/App/Perms/Permissions.cs b/Moonlight/App/Perms/Permissions.cs index 96701835..9a3fbd78 100644 --- a/Moonlight/App/Perms/Permissions.cs +++ b/Moonlight/App/Perms/Permissions.cs @@ -393,6 +393,13 @@ public static class Permissions Name = "Admin security permission groups", Description = "View, add and delete permission groups" }; + + public static Permission AdminSecurityLogs = new() + { + Index = 58, + Name = "Admin security logs", + Description = "View the security logs" + }; public static Permission? FromString(string name) { diff --git a/Moonlight/App/Repositories/LogEntries/AuditLogEntryRepository.cs b/Moonlight/App/Repositories/LogEntries/AuditLogEntryRepository.cs deleted file mode 100644 index cfefef2e..00000000 --- a/Moonlight/App/Repositories/LogEntries/AuditLogEntryRepository.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities.LogsEntries; - -namespace Moonlight.App.Repositories.LogEntries; - -public class AuditLogEntryRepository : IDisposable -{ - private readonly DataContext DataContext; - - public AuditLogEntryRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public AuditLogEntry Add(AuditLogEntry entry) - { - var x = DataContext.AuditLog.Add(entry); - DataContext.SaveChanges(); - return x.Entity; - } - - public DbSet Get() - { - return DataContext.AuditLog; - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Repositories/LogEntries/ErrorLogEntryRepository.cs b/Moonlight/App/Repositories/LogEntries/ErrorLogEntryRepository.cs deleted file mode 100644 index adda4f92..00000000 --- a/Moonlight/App/Repositories/LogEntries/ErrorLogEntryRepository.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities.LogsEntries; - -namespace Moonlight.App.Repositories.LogEntries; - -public class ErrorLogEntryRepository : IDisposable -{ - private readonly DataContext DataContext; - - public ErrorLogEntryRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public ErrorLogEntry Add(ErrorLogEntry errorLogEntry) - { - var x = DataContext.ErrorLog.Add(errorLogEntry); - DataContext.SaveChanges(); - return x.Entity; - } - - public DbSet Get() - { - return DataContext.ErrorLog; - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Repositories/LogEntries/SecurityLogEntryRepository.cs b/Moonlight/App/Repositories/LogEntries/SecurityLogEntryRepository.cs deleted file mode 100644 index 17a15201..00000000 --- a/Moonlight/App/Repositories/LogEntries/SecurityLogEntryRepository.cs +++ /dev/null @@ -1,32 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities.LogsEntries; - -namespace Moonlight.App.Repositories.LogEntries; - -public class SecurityLogEntryRepository : IDisposable -{ - private readonly DataContext DataContext; - - public SecurityLogEntryRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public SecurityLogEntry Add(SecurityLogEntry securityLogEntry) - { - var x = DataContext.SecurityLog.Add(securityLogEntry); - DataContext.SaveChanges(); - return x.Entity; - } - - public DbSet Get() - { - return DataContext.SecurityLog; - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/ConfigService.cs b/Moonlight/App/Services/ConfigService.cs index 4a9c0d7e..1de055a1 100644 --- a/Moonlight/App/Services/ConfigService.cs +++ b/Moonlight/App/Services/ConfigService.cs @@ -8,6 +8,7 @@ namespace Moonlight.App.Services; public class ConfigService { private readonly StorageService StorageService; + private readonly string Path; private ConfigV1 Configuration; public bool DebugMode { get; private set; } = false; @@ -18,6 +19,11 @@ public class ConfigService StorageService = storageService; StorageService.EnsureCreated(); + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ML_CONFIG_PATH"))) + Path = Environment.GetEnvironmentVariable("ML_CONFIG_PATH")!; + else + Path = PathBuilder.File("storage", "configs", "config.json"); + Reload(); // Env vars @@ -40,18 +46,16 @@ public class ConfigService public void Reload() { - var path = PathBuilder.File("storage", "configs", "config.json"); - - if (!File.Exists(path)) + if (!File.Exists(Path)) { - File.WriteAllText(path, "{}"); + File.WriteAllText(Path, "{}"); } Configuration = JsonConvert.DeserializeObject( - File.ReadAllText(path) + File.ReadAllText(Path) ) ?? new ConfigV1(); - File.WriteAllText(path, JsonConvert.SerializeObject(Configuration, Formatting.Indented)); + File.WriteAllText(Path, JsonConvert.SerializeObject(Configuration, Formatting.Indented)); } public void Save(ConfigV1 configV1) @@ -62,14 +66,12 @@ public class ConfigService public void Save() { - var path = PathBuilder.File("storage", "configs", "config.json"); - - if (!File.Exists(path)) + if (!File.Exists(Path)) { - File.WriteAllText(path, "{}"); + File.WriteAllText(Path, "{}"); } - File.WriteAllText(path, JsonConvert.SerializeObject(Configuration, Formatting.Indented)); + File.WriteAllText(Path, JsonConvert.SerializeObject(Configuration, Formatting.Indented)); Reload(); } diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index 77c26316..6045d49e 100644 --- a/Moonlight/App/Services/UserService.cs +++ b/Moonlight/App/Services/UserService.cs @@ -54,7 +54,10 @@ public class UserService throw new DisplayException("This operation was disabled"); if (await TempMailService.IsTempMail(email)) + { + Logger.Warn($"A user tried to use a blacklisted domain to register. Email: '{email}'", "security"); throw new DisplayException("This email is blacklisted"); + } // Check if the email is already taken var emailTaken = UserRepository.Get().FirstOrDefault(x => x.Email == email) != null; diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index 078f2ddc..e8a71f2d 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -80,6 +80,10 @@ <_ContentIncludedByDefault Remove="Shared\Views\Admin\AaPanels\Index.razor" /> <_ContentIncludedByDefault Remove="Shared\Views\Admin\Databases\Index.razor" /> <_ContentIncludedByDefault Remove="Shared\Components\StateLogic\OnlyAdmin.razor" /> + <_ContentIncludedByDefault Remove="Shared\Components\AuditLogEntrys\AuditLogEntryChangePassword.razor" /> + <_ContentIncludedByDefault Remove="Shared\Components\AuditLogEntrys\AuditLogEntryChangePowerState.razor" /> + <_ContentIncludedByDefault Remove="Shared\Components\AuditLogEntrys\AuditLogEntryLogin.razor" /> + <_ContentIncludedByDefault Remove="Shared\Components\AuditLogEntrys\AuditLogEntryRegister.razor" /> diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 60c742bd..bd2c59ec 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -15,7 +15,6 @@ using Moonlight.App.Helpers.Wings; using Moonlight.App.LogMigrator; using Moonlight.App.Repositories; using Moonlight.App.Repositories.Domains; -using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Repositories.Servers; using Moonlight.App.Services; using Moonlight.App.Services.Addon; @@ -167,9 +166,6 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddScoped(typeof(Repository<>)); // Services diff --git a/Moonlight/Properties/launchSettings.json b/Moonlight/Properties/launchSettings.json index be9982ad..75db4aaf 100644 --- a/Moonlight/Properties/launchSettings.json +++ b/Moonlight/Properties/launchSettings.json @@ -1,6 +1,8 @@ { - "profiles": { - "Moonlight": { + "profiles": + { + "Default": + { "commandName": "Project", "launchBrowser": true, "environmentVariables": { @@ -10,41 +12,29 @@ "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", "dotnetRunMessages": true }, - "Sql Debug": { + "Live DB": + { "commandName": "Project", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", - "ML_SQL_DEBUG": "true", - "ML_DEBUG": "true" + "ML_DEBUG": "true", + "ML_CONFIG_PATH": "storage\\configs\\live_config.json" }, "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", "dotnetRunMessages": true }, - "Discord Bot": { + "Dev DB 1": + { "commandName": "Project", - "launchBrowser": false, - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "ML_SQL_DEBUG": "true", - "ML_DEBUG": "true" - }, - "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", - "dotnetRunMessages": true - }, - "Watch": { - "commandName": "Executable", - "executablePath": "dotnet", - "workingDirectory": "$(ProjectDir)", - "hotReloadEnabled": true, - "hotReloadProfile": "aspnetcore", - "commandLineArgs": "watch run", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development", - "ML_DEBUG": "true" + "ML_DEBUG": "true", + "ML_CONFIG_PATH": "storage\\configs\\dev_1_config.json" }, - "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118" + "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", + "dotnetRunMessages": true } } } \ No newline at end of file diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor deleted file mode 100644 index f9ee3ac8..00000000 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor +++ /dev/null @@ -1,58 +0,0 @@ -@using Moonlight.App.Database.Entities.LogsEntries -@using Moonlight.App.Helpers -@using Moonlight.App.Repositories -@using Newtonsoft.Json -@using Moonlight.App.Database.Entities -@using Moonlight.App.Models.Log - -@inject UserRepository UserRepository - -
-
-
-
- -
-
-
-
-
- @if (User == null) - { - Password change for @(Data[0].Value) - } - else - { - Password change for @(User.Email) - } -
-
-
@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)
-
-
-
-
- -@code -{ - [Parameter] - public AuditLogEntry Entry { get; set; } - - private User? User; - private LogData[] Data; - - protected override void OnInitialized() - { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); - - await InvokeAsync(StateHasChanged); - } - } -} \ No newline at end of file diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor deleted file mode 100644 index 9dcafe02..00000000 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor +++ /dev/null @@ -1,58 +0,0 @@ -@using Moonlight.App.Database.Entities.LogsEntries -@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 - -
-
-
-
- -
-
-
-
-
- @if (Server == null) - { - Change power state for @(Data[0].Value) to @(Data[1].Value) - } - else - { - Change power state for @(Server.Name) to @(Data[1].Value) - } -
-
-
@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)
-
-
-
-
- -@code -{ - [Parameter] - public AuditLogEntry Entry { get; set; } - - private Server? Server; - private LogData[] Data; - - protected override void OnInitialized() - { - 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].Value)); - - await InvokeAsync(StateHasChanged); - } - } -} \ No newline at end of file diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor deleted file mode 100644 index 810a3568..00000000 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor +++ /dev/null @@ -1,58 +0,0 @@ -@using Moonlight.App.Database.Entities.LogsEntries -@using Moonlight.App.Helpers -@using Moonlight.App.Repositories -@using Newtonsoft.Json -@using Moonlight.App.Database.Entities -@using Moonlight.App.Models.Log - -@inject UserRepository UserRepository - -
-
-
-
- -
-
-
-
-
- @if (User == null) - { - New login for @(Data[0].Value) - } - else - { - New login for @(User.Email) - } -
-
-
@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)
-
-
-
-
- -@code -{ - [Parameter] - public AuditLogEntry Entry { get; set; } - - private User? User; - private LogData[] Data; - - protected override void OnInitialized() - { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); - - await InvokeAsync(StateHasChanged); - } - } -} \ No newline at end of file diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor deleted file mode 100644 index 846f0d86..00000000 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor +++ /dev/null @@ -1,58 +0,0 @@ -@using Moonlight.App.Database.Entities.LogsEntries -@using Moonlight.App.Helpers -@using Moonlight.App.Repositories -@using Newtonsoft.Json -@using Moonlight.App.Database.Entities -@using Moonlight.App.Models.Log - -@inject UserRepository UserRepository - -
-
-
-
- -
-
-
-
-
- @if (User == null) - { - Register for @(Data[0].Value) - } - else - { - Register for @(User.Email) - } -
-
-
@(Formatter.FormatDate(Entry.CreatedAt)), @(Entry.System ? "System" : Entry.Ip)
-
-
-
-
- -@code -{ - [Parameter] - public AuditLogEntry Entry { get; set; } - - private User? User; - private LogData[] Data; - - protected override void OnInitialized() - { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; - } - - protected override async Task OnAfterRenderAsync(bool firstRender) - { - if (firstRender) - { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); - - await InvokeAsync(StateHasChanged); - } - } -} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Navigations/AdminSecurityNavigation.razor b/Moonlight/Shared/Components/Navigations/AdminSecurityNavigation.razor index 85589958..a05b47af 100644 --- a/Moonlight/Shared/Components/Navigations/AdminSecurityNavigation.razor +++ b/Moonlight/Shared/Components/Navigations/AdminSecurityNavigation.razor @@ -21,6 +21,11 @@ Permission groups + diff --git a/Moonlight/Shared/Views/Admin/Security/Logs.razor b/Moonlight/Shared/Views/Admin/Security/Logs.razor new file mode 100644 index 00000000..2a7d1958 --- /dev/null +++ b/Moonlight/Shared/Views/Admin/Security/Logs.razor @@ -0,0 +1,47 @@ +@page "/admin/security/logs" + +@using Moonlight.App.Repositories +@using Moonlight.App.Database.Entities +@using BlazorTable +@using Moonlight.Shared.Components.Navigations +@using Moonlight.App.Services + +@inject Repository SecurityLogRepository +@inject SmartTranslateService SmartTranslateService + +@attribute [PermissionRequired(nameof(Permissions.AdminSecurityLogs))] + + + +
+
+ + Security logs + +
+
+ +
+ + + + +
+
+
+
+
+ +@code +{ + private SecurityLog[] SecurityLogs; + + private Task Load(LazyLoader arg) + { + SecurityLogs = SecurityLogRepository + .Get() + .ToArray(); + + return Task.CompletedTask; + } +} \ No newline at end of file