diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index c8575c4..3e2875f 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -2,6 +2,7 @@ using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities.LogsEntries; using Moonlight.App.Database.Entities.Notification; +using Moonlight.App.Models.Misc; using Moonlight.App.Services; namespace Moonlight.App.Database; @@ -34,14 +35,13 @@ public class DataContext : DbContext public DbSet SharedDomains { get; set; } public DbSet Domains { get; set; } - public DbSet Subscriptions { get; set; } - public DbSet SubscriptionLimits { get; set; } public DbSet Revokes { get; set; } public DbSet NotificationClients { get; set; } public DbSet NotificationActions { get; set; } public DbSet AaPanels { get; set; } public DbSet Websites { get; set; } public DbSet DdosAttacks { get; set; } + public DbSet Subscriptions { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { diff --git a/Moonlight/App/Database/Entities/Domain.cs b/Moonlight/App/Database/Entities/Domain.cs index 3b65089..2f7645a 100644 --- a/Moonlight/App/Database/Entities/Domain.cs +++ b/Moonlight/App/Database/Entities/Domain.cs @@ -1,8 +1,12 @@ -namespace Moonlight.App.Database.Entities; +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Database.Entities; public class Domain { public int Id { get; set; } + + [Required] public string Name { get; set; } public SharedDomain SharedDomain { get; set; } public User Owner { get; set; } diff --git a/Moonlight/App/Database/Entities/Server.cs b/Moonlight/App/Database/Entities/Server.cs index 11388d9..cad9ced 100644 --- a/Moonlight/App/Database/Entities/Server.cs +++ b/Moonlight/App/Database/Entities/Server.cs @@ -20,4 +20,5 @@ public class Server public NodeAllocation MainAllocation { get; set; } = null!; public Node Node { get; set; } = null!; public User Owner { get; set; } = null!; + public bool IsCleanupException { get; set; } = false; } \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/Subscription.cs b/Moonlight/App/Database/Entities/Subscription.cs index 7f2fa6e..ab0b8c7 100644 --- a/Moonlight/App/Database/Entities/Subscription.cs +++ b/Moonlight/App/Database/Entities/Subscription.cs @@ -5,7 +5,5 @@ public class Subscription public int Id { get; set; } public string Name { get; set; } = ""; public string Description { get; set; } = ""; - public string SellPassId { get; set; } = ""; - public int Duration { get; set; } - public List Limits { get; set; } = new(); + public string LimitsJson { get; set; } = ""; } \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/SubscriptionLimit.cs b/Moonlight/App/Database/Entities/SubscriptionLimit.cs deleted file mode 100644 index 96c0691..0000000 --- a/Moonlight/App/Database/Entities/SubscriptionLimit.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Moonlight.App.Database.Entities; - -public class SubscriptionLimit -{ - public int Id { get; set; } - public Image Image { get; set; } = null!; - public int Amount { get; set; } - public int Cpu { get; set; } - public int Memory { get; set; } - public int Disk { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/User.cs b/Moonlight/App/Database/Entities/User.cs index 76d23e4..a0654a3 100644 --- a/Moonlight/App/Database/Entities/User.cs +++ b/Moonlight/App/Database/Entities/User.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Models.Misc; +using System.ComponentModel.DataAnnotations; +using Moonlight.App.Models.Misc; namespace Moonlight.App.Database.Entities; @@ -7,14 +8,21 @@ public class User public int Id { get; set; } // Personal data - + public string FirstName { get; set; } = ""; + public string LastName { get; set; } = ""; + public string Email { get; set; } = ""; + public string Password { get; set; } = ""; + public string Address { get; set; } = ""; + public string City { get; set; } = ""; + public string State { get; set; } = ""; + public string Country { get; set; } = ""; // States @@ -34,9 +42,10 @@ public class User // Date stuff public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; - + // Subscriptions - public Subscription? Subscription { get; set; } = null; - public DateTime? SubscriptionSince { get; set; } + + public Subscription? CurrentSubscription { get; set; } = null; + public DateTime SubscriptionSince { get; set; } = DateTime.Now; public int SubscriptionDuration { get; set; } } \ No newline at end of file diff --git a/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.Designer.cs b/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.Designer.cs new file mode 100644 index 0000000..7ae6105 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.Designer.cs @@ -0,0 +1,1082 @@ +// +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("20230402204329_AddCleanupExceptionsTable")] + partial class AddCleanupExceptionsTable + { + /// + 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.AaPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Url") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AaPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Databases"); + }); + + 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("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.ImageTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ImageTags"); + }); + + 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.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.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.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.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.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("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("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.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SellPassId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("Cpu") + .HasColumnType("int"); + + b.Property("Disk") + .HasColumnType("int"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Memory") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.HasIndex("SubscriptionId"); + + b.ToTable("SubscriptionLimits"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportMessages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Admin") + .HasColumnType("tinyint(1)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DiscordId") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("SubscriptionDuration") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + 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("SubscriptionId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("DomainName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("PhpVersion") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Websites"); + }); + + modelBuilder.Entity("Moonlight.App.Models.Misc.CleanupException", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ServerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CleanupExceptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + 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.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.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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("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.SubscriptionLimit", b => + { + b.HasOne("Moonlight.App.Database.Entities.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.Subscription", null) + .WithMany("Limits") + .HasForeignKey("SubscriptionId"); + + b.Navigation("Image"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId"); + + 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", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + 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.Subscription", b => + { + b.Navigation("Limits"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.cs b/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.cs new file mode 100644 index 0000000..3c0f8e1 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402204329_AddCleanupExceptionsTable.cs @@ -0,0 +1,170 @@ +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class AddCleanupExceptionsTable : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "State", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LastName", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "FirstName", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Country", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "City", + table: "Users", + type: "varchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Address", + table: "Users", + type: "varchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "CleanupExceptions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ServerId = table.Column(type: "int", nullable: false), + Note = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_CleanupExceptions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CleanupExceptions"); + + migrationBuilder.AlterColumn( + name: "State", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LastName", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "FirstName", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Country", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "City", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(128)", + oldMaxLength: 128) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Address", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(128)", + oldMaxLength: 128) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.Designer.cs b/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.Designer.cs new file mode 100644 index 0000000..6dd7b20 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.Designer.cs @@ -0,0 +1,1098 @@ +// +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("20230402215155_ChengedCleanupExceptionModel")] + partial class ChengedCleanupExceptionModel + { + /// + 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.AaPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Url") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AaPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Databases"); + }); + + 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("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.ImageTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ImageTags"); + }); + + 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.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.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.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.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.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("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("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.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SellPassId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("Cpu") + .HasColumnType("int"); + + b.Property("Disk") + .HasColumnType("int"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Memory") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.HasIndex("SubscriptionId"); + + b.ToTable("SubscriptionLimits"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportMessages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Admin") + .HasColumnType("tinyint(1)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DiscordId") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("SubscriptionDuration") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + 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("SubscriptionId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("DomainName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("PhpVersion") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Websites"); + }); + + modelBuilder.Entity("Moonlight.App.Models.Misc.CleanupException", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("Note") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ServerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ServerId"); + + b.ToTable("CleanupExceptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + 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.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.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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("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.SubscriptionLimit", b => + { + b.HasOne("Moonlight.App.Database.Entities.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.Subscription", null) + .WithMany("Limits") + .HasForeignKey("SubscriptionId"); + + b.Navigation("Image"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId"); + + 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", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("Moonlight.App.Models.Misc.CleanupException", b => + { + b.HasOne("Moonlight.App.Database.Entities.Server", "Server") + .WithMany() + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Server"); + }); + + 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.Subscription", b => + { + b.Navigation("Limits"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.cs b/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.cs new file mode 100644 index 0000000..15e5bcb --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402215155_ChengedCleanupExceptionModel.cs @@ -0,0 +1,51 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class ChengedCleanupExceptionModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CreatedAt", + table: "CleanupExceptions", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateIndex( + name: "IX_CleanupExceptions_ServerId", + table: "CleanupExceptions", + column: "ServerId"); + + migrationBuilder.AddForeignKey( + name: "FK_CleanupExceptions_Servers_ServerId", + table: "CleanupExceptions", + column: "ServerId", + principalTable: "Servers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_CleanupExceptions_Servers_ServerId", + table: "CleanupExceptions"); + + migrationBuilder.DropIndex( + name: "IX_CleanupExceptions_ServerId", + table: "CleanupExceptions"); + + migrationBuilder.DropColumn( + name: "CreatedAt", + table: "CleanupExceptions"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.Designer.cs b/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.Designer.cs new file mode 100644 index 0000000..59b5c12 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.Designer.cs @@ -0,0 +1,1067 @@ +// +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("20230402220651_RemovedCleanupExceptionChangedServerModel")] + partial class RemovedCleanupExceptionChangedServerModel + { + /// + 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.AaPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Url") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AaPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Databases"); + }); + + 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("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.ImageTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ImageTags"); + }); + + 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.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.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.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.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.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("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("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.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Duration") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("SellPassId") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Amount") + .HasColumnType("int"); + + b.Property("Cpu") + .HasColumnType("int"); + + b.Property("Disk") + .HasColumnType("int"); + + b.Property("ImageId") + .HasColumnType("int"); + + b.Property("Memory") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ImageId"); + + b.HasIndex("SubscriptionId"); + + b.ToTable("SubscriptionLimits"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportMessages"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Address") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Admin") + .HasColumnType("tinyint(1)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(128) + .HasColumnType("varchar(128)"); + + b.Property("Country") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("DiscordId") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("varchar(64)"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("SubscriptionDuration") + .HasColumnType("int"); + + b.Property("SubscriptionId") + .HasColumnType("int"); + + 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("SubscriptionId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("DomainName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("PhpVersion") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Websites"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + 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.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.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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("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.SubscriptionLimit", b => + { + b.HasOne("Moonlight.App.Database.Entities.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.Subscription", null) + .WithMany("Limits") + .HasForeignKey("SubscriptionId"); + + b.Navigation("Image"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId"); + + 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", "Subscription") + .WithMany() + .HasForeignKey("SubscriptionId"); + + b.Navigation("Subscription"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + 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.Subscription", b => + { + b.Navigation("Limits"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.cs b/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.cs new file mode 100644 index 0000000..4f1a3c1 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230402220651_RemovedCleanupExceptionChangedServerModel.cs @@ -0,0 +1,62 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class RemovedCleanupExceptionChangedServerModel : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CleanupExceptions"); + + migrationBuilder.AddColumn( + name: "IsCleanupException", + table: "Servers", + type: "tinyint(1)", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IsCleanupException", + table: "Servers"); + + migrationBuilder.CreateTable( + name: "CleanupExceptions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ServerId = table.Column(type: "int", nullable: false), + CreatedAt = table.Column(type: "datetime(6)", nullable: false), + Note = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_CleanupExceptions", x => x.Id); + table.ForeignKey( + name: "FK_CleanupExceptions_Servers_ServerId", + column: x => x.ServerId, + principalTable: "Servers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_CleanupExceptions_ServerId", + table: "CleanupExceptions", + column: "ServerId"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.Designer.cs b/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.Designer.cs new file mode 100644 index 0000000..d5429e9 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.Designer.cs @@ -0,0 +1,962 @@ +// +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("20230403130734_RemovedOldSubscriptionData")] + partial class RemovedOldSubscriptionData + { + /// + 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.AaPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Url") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AaPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Databases"); + }); + + 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("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.ImageTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ImageTags"); + }); + + 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.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.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.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.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.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("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("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.SupportMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportMessages"); + }); + + 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("DiscordId") + .HasColumnType("bigint"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .HasColumnType("int"); + + 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.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("DomainName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("PhpVersion") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Websites"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + 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.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.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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("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.SupportMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId"); + + b.HasOne("Moonlight.App.Database.Entities.User", "Sender") + .WithMany() + .HasForeignKey("SenderId"); + + b.Navigation("Recipient"); + + b.Navigation("Sender"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + 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"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.cs b/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.cs new file mode 100644 index 0000000..23c0f92 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.cs @@ -0,0 +1,269 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class RemovedOldSubscriptionData : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Subscriptions_SubscriptionId", + table: "Users"); + + migrationBuilder.DropTable( + name: "SubscriptionLimits"); + + migrationBuilder.DropTable( + name: "Subscriptions"); + + migrationBuilder.DropIndex( + name: "IX_Users_SubscriptionId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "SubscriptionDuration", + table: "Users"); + + migrationBuilder.DropColumn( + name: "SubscriptionId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "SubscriptionSince", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "State", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LastName", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "FirstName", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Country", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(64)", + oldMaxLength: 64) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "City", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(128)", + oldMaxLength: 128) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Address", + table: "Users", + type: "longtext", + nullable: false, + oldClrType: typeof(string), + oldType: "varchar(128)", + oldMaxLength: 128) + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.AlterColumn( + name: "State", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "LastName", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "FirstName", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Country", + table: "Users", + type: "varchar(64)", + maxLength: 64, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "City", + table: "Users", + type: "varchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AlterColumn( + name: "Address", + table: "Users", + type: "varchar(128)", + maxLength: 128, + nullable: false, + oldClrType: typeof(string), + oldType: "longtext") + .Annotation("MySql:CharSet", "utf8mb4") + .OldAnnotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.AddColumn( + name: "SubscriptionDuration", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "SubscriptionId", + table: "Users", + type: "int", + nullable: true); + + migrationBuilder.AddColumn( + name: "SubscriptionSince", + table: "Users", + type: "datetime(6)", + nullable: true); + + migrationBuilder.CreateTable( + name: "Subscriptions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Duration = table.Column(type: "int", nullable: false), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + SellPassId = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateTable( + name: "SubscriptionLimits", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + ImageId = table.Column(type: "int", nullable: false), + Amount = table.Column(type: "int", nullable: false), + Cpu = table.Column(type: "int", nullable: false), + Disk = table.Column(type: "int", nullable: false), + Memory = table.Column(type: "int", nullable: false), + SubscriptionId = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_SubscriptionLimits", x => x.Id); + table.ForeignKey( + name: "FK_SubscriptionLimits_Images_ImageId", + column: x => x.ImageId, + principalTable: "Images", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_SubscriptionLimits_Subscriptions_SubscriptionId", + column: x => x.SubscriptionId, + principalTable: "Subscriptions", + principalColumn: "Id"); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Users_SubscriptionId", + table: "Users", + column: "SubscriptionId"); + + migrationBuilder.CreateIndex( + name: "IX_SubscriptionLimits_ImageId", + table: "SubscriptionLimits", + column: "ImageId"); + + migrationBuilder.CreateIndex( + name: "IX_SubscriptionLimits_SubscriptionId", + table: "SubscriptionLimits", + column: "SubscriptionId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Subscriptions_SubscriptionId", + table: "Users", + column: "SubscriptionId", + principalTable: "Subscriptions", + principalColumn: "Id"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.Designer.cs b/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.Designer.cs new file mode 100644 index 0000000..e0d6429 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.Designer.cs @@ -0,0 +1,1005 @@ +// +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("20230403131343_AddedNewSubscriptionData")] + partial class AddedNewSubscriptionData + { + /// + 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.AaPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Key") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Url") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("AaPanels"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Databases"); + }); + + 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("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.ImageTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("ImageTags"); + }); + + 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.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.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.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.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.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .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("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("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.Subscription", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Description") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LimitsJson") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("Subscriptions"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("Answer") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("CreatedAt") + .HasColumnType("datetime(6)"); + + b.Property("IsQuestion") + .HasColumnType("tinyint(1)"); + + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); + + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") + .HasColumnType("int"); + + b.Property("SenderId") + .HasColumnType("int"); + + b.Property("Type") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("RecipientId"); + + b.HasIndex("SenderId"); + + b.ToTable("SupportMessages"); + }); + + 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"); + + b.Property("Email") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FirstName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("LastName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Password") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("State") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("SubscriptionDuration") + .HasColumnType("int"); + + 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.ToTable("Users"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("AaPanelId") + .HasColumnType("int"); + + b.Property("DomainName") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpUsername") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("InternalAaPanelId") + .HasColumnType("int"); + + b.Property("OwnerId") + .HasColumnType("int"); + + b.Property("PhpVersion") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.HasIndex("AaPanelId"); + + b.HasIndex("OwnerId"); + + b.ToTable("Websites"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Database", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + b.Navigation("Owner"); + }); + + 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.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.Image", "Image") + .WithMany() + .HasForeignKey("ImageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") + .WithMany() + .HasForeignKey("MainAllocationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + 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("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.SupportMessage", b => + { + b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") + .WithMany() + .HasForeignKey("RecipientId"); + + 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.Navigation("CurrentSubscription"); + }); + + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => + { + b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") + .WithMany() + .HasForeignKey("AaPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Moonlight.App.Database.Entities.User", "Owner") + .WithMany() + .HasForeignKey("OwnerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AaPanel"); + + 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"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.cs b/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.cs new file mode 100644 index 0000000..5299884 --- /dev/null +++ b/Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.cs @@ -0,0 +1,94 @@ +using System; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Moonlight.App.Database.Migrations +{ + /// + public partial class AddedNewSubscriptionData : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CurrentSubscriptionId", + table: "Users", + type: "int", + nullable: true); + + migrationBuilder.AddColumn( + name: "SubscriptionDuration", + table: "Users", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "SubscriptionSince", + table: "Users", + type: "datetime(6)", + nullable: false, + defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified)); + + migrationBuilder.CreateTable( + name: "Subscriptions", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), + Name = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + Description = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4"), + LimitsJson = table.Column(type: "longtext", nullable: false) + .Annotation("MySql:CharSet", "utf8mb4") + }, + constraints: table => + { + table.PrimaryKey("PK_Subscriptions", x => x.Id); + }) + .Annotation("MySql:CharSet", "utf8mb4"); + + migrationBuilder.CreateIndex( + name: "IX_Users_CurrentSubscriptionId", + table: "Users", + column: "CurrentSubscriptionId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Subscriptions_CurrentSubscriptionId", + table: "Users", + column: "CurrentSubscriptionId", + principalTable: "Subscriptions", + principalColumn: "Id"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Subscriptions_CurrentSubscriptionId", + table: "Users"); + + migrationBuilder.DropTable( + name: "Subscriptions"); + + migrationBuilder.DropIndex( + name: "IX_Users_CurrentSubscriptionId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "CurrentSubscriptionId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "SubscriptionDuration", + table: "Users"); + + migrationBuilder.DropColumn( + name: "SubscriptionSince", + table: "Users"); + } + } +} diff --git a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs index 566e4e6..d670d74 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -482,6 +482,9 @@ namespace Moonlight.App.Database.Migrations b.Property("Installing") .HasColumnType("tinyint(1)"); + b.Property("IsCleanupException") + .HasColumnType("tinyint(1)"); + b.Property("MainAllocationId") .HasColumnType("int"); @@ -606,14 +609,11 @@ namespace Moonlight.App.Database.Migrations .IsRequired() .HasColumnType("longtext"); - b.Property("Duration") - .HasColumnType("int"); - - b.Property("Name") + b.Property("LimitsJson") .IsRequired() .HasColumnType("longtext"); - b.Property("SellPassId") + b.Property("Name") .IsRequired() .HasColumnType("longtext"); @@ -622,39 +622,6 @@ namespace Moonlight.App.Database.Migrations b.ToTable("Subscriptions"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Amount") - .HasColumnType("int"); - - b.Property("Cpu") - .HasColumnType("int"); - - b.Property("Disk") - .HasColumnType("int"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Memory") - .HasColumnType("int"); - - b.Property("SubscriptionId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.HasIndex("SubscriptionId"); - - b.ToTable("SubscriptionLimits"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => { b.Property("Id") @@ -723,6 +690,9 @@ namespace Moonlight.App.Database.Migrations b.Property("CreatedAt") .HasColumnType("datetime(6)"); + b.Property("CurrentSubscriptionId") + .HasColumnType("int"); + b.Property("DiscordId") .HasColumnType("bigint"); @@ -752,10 +722,7 @@ namespace Moonlight.App.Database.Migrations b.Property("SubscriptionDuration") .HasColumnType("int"); - b.Property("SubscriptionId") - .HasColumnType("int"); - - b.Property("SubscriptionSince") + b.Property("SubscriptionSince") .HasColumnType("datetime(6)"); b.Property("SupportPending") @@ -776,7 +743,7 @@ namespace Moonlight.App.Database.Migrations b.HasKey("Id"); - b.HasIndex("SubscriptionId"); + b.HasIndex("CurrentSubscriptionId"); b.ToTable("Users"); }); @@ -966,21 +933,6 @@ namespace Moonlight.App.Database.Migrations .HasForeignKey("ServerId"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", "Image") - .WithMany() - .HasForeignKey("ImageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.Subscription", null) - .WithMany("Limits") - .HasForeignKey("SubscriptionId"); - - b.Navigation("Image"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => { b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") @@ -998,11 +950,11 @@ namespace Moonlight.App.Database.Migrations modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => { - b.HasOne("Moonlight.App.Database.Entities.Subscription", "Subscription") + b.HasOne("Moonlight.App.Database.Entities.Subscription", "CurrentSubscription") .WithMany() - .HasForeignKey("SubscriptionId"); + .HasForeignKey("CurrentSubscriptionId"); - b.Navigation("Subscription"); + b.Navigation("CurrentSubscription"); }); modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => @@ -1044,11 +996,6 @@ namespace Moonlight.App.Database.Migrations b.Navigation("Variables"); }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Navigation("Limits"); - }); #pragma warning restore 612, 618 } } diff --git a/Moonlight/App/Helpers/FieldCssHelper.cs b/Moonlight/App/Helpers/FieldCssHelper.cs new file mode 100644 index 0000000..557532a --- /dev/null +++ b/Moonlight/App/Helpers/FieldCssHelper.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Components.Forms; + +namespace Moonlight.App.Helpers; + +public class FieldCssHelper : FieldCssClassProvider +{ + public override string GetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier) + { + return editContext.GetValidationMessages(fieldIdentifier).Any() ? "is-invalid" : "is-valid"; + } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/ContextAction.cs b/Moonlight/App/Helpers/Files/ContextAction.cs new file mode 100644 index 0000000..704c425 --- /dev/null +++ b/Moonlight/App/Helpers/Files/ContextAction.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Helpers.Files; + +public class ContextAction +{ + public string Id { get; set; } = ""; + public string Name { get; set; } = ""; + public Action Action { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/FileAccess.cs b/Moonlight/App/Helpers/Files/FileAccess.cs new file mode 100644 index 0000000..a900c46 --- /dev/null +++ b/Moonlight/App/Helpers/Files/FileAccess.cs @@ -0,0 +1,24 @@ +namespace Moonlight.App.Helpers.Files; + +public abstract class FileAccess : ICloneable +{ + public string CurrentPath { get; set; } = "/"; + + public abstract Task Ls(); + public abstract Task Cd(string dir); + public abstract Task Up(); + public abstract Task SetDir(string dir); + public abstract Task Read(FileData fileData); + public abstract Task Write(FileData fileData, string content); + public abstract Task Upload(string name, Stream stream, Action? progressUpdated = null); + public abstract Task MkDir(string name); + public abstract Task Pwd(); + public abstract Task DownloadUrl(FileData fileData); + public abstract Task DownloadStream(FileData fileData); + public abstract Task Delete(FileData fileData); + public abstract Task Move(FileData fileData, string newPath); + public abstract Task Compress(params FileData[] files); + public abstract Task Decompress(FileData fileData); + public abstract Task GetLaunchUrl(); + public abstract object Clone(); +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/FileData.cs b/Moonlight/App/Helpers/Files/FileData.cs new file mode 100644 index 0000000..f0bb75f --- /dev/null +++ b/Moonlight/App/Helpers/Files/FileData.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Helpers.Files; + +public class FileData +{ + public string Name { get; set; } = ""; + public long Size { get; set; } + public bool IsFile { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/WingsFileAccess.cs b/Moonlight/App/Helpers/Files/WingsFileAccess.cs new file mode 100644 index 0000000..b1c2296 --- /dev/null +++ b/Moonlight/App/Helpers/Files/WingsFileAccess.cs @@ -0,0 +1,232 @@ +using System.Web; +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Wings.Requests; +using Moonlight.App.Models.Wings.Resources; +using Moonlight.App.Services; +using RestSharp; + +namespace Moonlight.App.Helpers.Files; + +public class WingsFileAccess : FileAccess +{ + private readonly WingsApiHelper WingsApiHelper; + private readonly WingsJwtHelper WingsJwtHelper; + private readonly ConfigService ConfigService; + private readonly Server Server; + private readonly User User; + + public WingsFileAccess( + WingsApiHelper wingsApiHelper, + WingsJwtHelper wingsJwtHelper, + Server server, + ConfigService configService, + User user) + { + WingsApiHelper = wingsApiHelper; + WingsJwtHelper = wingsJwtHelper; + Server = server; + ConfigService = configService; + User = user; + + if (server.Node == null) + { + throw new ArgumentException("The wings file access server model needs to include the node data"); + } + } + + public override async Task Ls() + { + var res = await WingsApiHelper.Get( + Server.Node, + $"api/servers/{Server.Uuid}/files/list-directory?directory={CurrentPath}" + ); + + var x = new List(); + + foreach (var response in res) + { + x.Add(new() + { + Name = response.Name, + Size = response.File ? response.Size : 0, + IsFile = response.File, + }); + } + + return x.ToArray(); + } + + public override Task Cd(string dir) + { + var x = Path.Combine(CurrentPath, dir).Replace("\\", "/") + "/"; + x = x.Replace("//", "/"); + CurrentPath = x; + + return Task.CompletedTask; + } + + public override Task Up() + { + CurrentPath = Path.GetFullPath(Path.Combine(CurrentPath, "..")).Replace("\\", "/").Replace("C:", ""); + return Task.CompletedTask; + } + + public override Task SetDir(string dir) + { + CurrentPath = dir; + return Task.CompletedTask; + } + + public override async Task Read(FileData fileData) + { + return await WingsApiHelper.GetRaw(Server.Node, + $"api/servers/{Server.Uuid}/files/contents?file={CurrentPath}{fileData.Name}"); + } + + public override async Task Write(FileData fileData, string content) + { + await WingsApiHelper.PostRaw(Server.Node, + $"api/servers/{Server.Uuid}/files/write?file={CurrentPath}{fileData.Name}", content); + } + + public override async Task Upload(string name, Stream dataStream, Action? progressUpdated = null) + { + var token = WingsJwtHelper.Generate( + Server.Node.Token, + claims => { claims.Add("server_uuid", Server.Uuid.ToString()); } + ); + + var client = new RestClient(); + var request = new RestRequest(); + + if (Server.Node.Ssl) + request.Resource = + $"https://{Server.Node.Fqdn}:{Server.Node.HttpPort}/upload/file?token={token}&directory={CurrentPath}"; + else + request.Resource = + $"http://{Server.Node.Fqdn}:{Server.Node.HttpPort}/upload/file?token={token}&directory={CurrentPath}"; + + request.AddParameter("name", "files"); + request.AddParameter("filename", name); + request.AddHeader("Content-Type", "multipart/form-data"); + request.AddHeader("Origin", ConfigService.GetSection("Moonlight").GetValue("AppUrl")); + request.AddFile("files", () => + { + return new StreamProgressHelper(dataStream) + { + Progress = i => { progressUpdated?.Invoke(i); } + }; + }, name); + + await client.ExecutePostAsync(request); + + client.Dispose(); + dataStream.Close(); + } + + public override async Task MkDir(string name) + { + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/create-directory", + new CreateDirectory() + { + Name = name, + Path = CurrentPath + } + ); + } + + public override Task Pwd() + { + return Task.FromResult(CurrentPath); + } + + public override Task DownloadUrl(FileData fileData) + { + var token = WingsJwtHelper.Generate(Server.Node.Token, claims => + { + claims.Add("server_uuid", Server.Uuid.ToString()); + claims.Add("file_path", CurrentPath + "/" + fileData.Name); + }); + + if (Server.Node.Ssl) + { + return Task.FromResult( + $"https://{Server.Node.Fqdn}:{Server.Node.HttpPort}/download/file?token={token}" + ); + } + else + { + return Task.FromResult( + $"http://{Server.Node.Fqdn}:{Server.Node.HttpPort}/download/file?token={token}" + ); + } + } + + public override Task DownloadStream(FileData fileData) + { + throw new NotImplementedException(); + } + + public override async Task Delete(FileData fileData) + { + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFiles() + { + Root = CurrentPath, + Files = new() + { + fileData.Name + } + }); + } + + public override async Task Move(FileData fileData, string newPath) + { + var req = new RenameFiles() + { + Root = "/", + Files = new[] + { + new RenameFilesData() + { + From = (CurrentPath + fileData.Name), + To = newPath + } + } + }; + + await WingsApiHelper.Put(Server.Node, $"api/servers/{Server.Uuid}/files/rename", req); + } + + public override async Task Compress(params FileData[] files) + { + var req = new CompressFiles() + { + Root = CurrentPath, + Files = files.Select(x => x.Name).ToArray() + }; + + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/compress", req); + } + + public override async Task Decompress(FileData fileData) + { + var req = new DecompressFile() + { + Root = CurrentPath, + File = fileData.Name + }; + + await WingsApiHelper.Post(Server.Node, $"api/servers/{Server.Uuid}/files/decompress", req); + } + + public override Task GetLaunchUrl() + { + return Task.FromResult( + $"sftp://{User.Id}.{StringHelper.IntToStringWithLeadingZeros(Server.Id, 8)}@{Server.Node.Fqdn}:{Server.Node.SftpPort}"); + } + + public override object Clone() + { + return new WingsFileAccess(WingsApiHelper, WingsJwtHelper, Server, ConfigService, User); + } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/PaperApiHelper.cs b/Moonlight/App/Helpers/PaperApiHelper.cs index 232b4a8..c8e1a3f 100644 --- a/Moonlight/App/Helpers/PaperApiHelper.cs +++ b/Moonlight/App/Helpers/PaperApiHelper.cs @@ -24,11 +24,11 @@ public class PaperApiHelper else requrl = ApiUrl + "/" + url; - RestRequest request = new(requrl); + RestRequest request = new(requrl, Method.Get); request.AddHeader("Content-Type", "application/json"); - var response = await client.GetAsync(request); + var response = await client.ExecuteAsync(request); if (!response.IsSuccessful) { diff --git a/Moonlight/App/Helpers/WingsApiHelper.cs b/Moonlight/App/Helpers/WingsApiHelper.cs index 23900b4..9611d64 100644 --- a/Moonlight/App/Helpers/WingsApiHelper.cs +++ b/Moonlight/App/Helpers/WingsApiHelper.cs @@ -14,24 +14,13 @@ public class WingsApiHelper Client = new(); } - private string GetApiUrl(Node node) - { - if(node.Ssl) - return $"https://{node.Fqdn}:{node.HttpPort}/"; - else - return $"http://{node.Fqdn}:{node.HttpPort}/"; - //return $"https://{node.Fqdn}:{node.HttpPort}/"; - } - public async Task Get(Node node, string resource) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Get; - var response = await Client.GetAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -53,13 +42,11 @@ public class WingsApiHelper public async Task GetRaw(Node node, string resource) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Get; - var response = await Client.GetAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -81,18 +68,16 @@ public class WingsApiHelper public async Task Post(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody ); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -114,16 +99,14 @@ public class WingsApiHelper public async Task Post(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; - if(body != null) + if(body != null) request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -143,15 +126,13 @@ public class WingsApiHelper public async Task PostRaw(Node node, string resource, object body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Post; request.AddParameter("text/plain", body, ParameterType.RequestBody); - var response = await Client.PostAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -171,16 +152,14 @@ public class WingsApiHelper public async Task Delete(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Delete; - if(body != null) + if(body != null) request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.DeleteAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -200,15 +179,13 @@ public class WingsApiHelper public async Task Put(Node node, string resource, object? body) { - RestRequest request = new(GetApiUrl(node) + resource); + var request = CreateRequest(node, resource); - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + node.Token); + request.Method = Method.Put; request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - var response = await Client.PutAsync(request); + var response = await Client.ExecuteAsync(request); if (!response.IsSuccessful) { @@ -225,4 +202,20 @@ public class WingsApiHelper } } } + + private RestRequest CreateRequest(Node node, string resource) + { + var url = (node.Ssl ? "https" : "http") + $"://{node.Fqdn}:{node.HttpPort}/" + resource; + + var request = new RestRequest(url) + { + Timeout = 60 * 15 + }; + + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("Accept", "application/json"); + request.AddHeader("Authorization", "Bearer " + node.Token); + + return request; + } } \ No newline at end of file diff --git a/Moonlight/App/Helpers/WingsServerConverter.cs b/Moonlight/App/Helpers/WingsServerConverter.cs index 2ef6ef6..acc7ed1 100644 --- a/Moonlight/App/Helpers/WingsServerConverter.cs +++ b/Moonlight/App/Helpers/WingsServerConverter.cs @@ -80,6 +80,13 @@ public class WingsServerConverter wingsServer.Settings.Environment.Add(v.Key, v.Value); } } + + int i = 0; + foreach (var allocation in server.Allocations) + { + wingsServer.Settings.Environment.Add("ML_PORT_" + i, allocation.Port.ToString()); + i++; + } // Stop if (image.StopCommand.StartsWith("!")) diff --git a/Moonlight/App/Http/Controllers/Api/Moonlight/PaymentsController.cs b/Moonlight/App/Http/Controllers/Api/Moonlight/PaymentsController.cs deleted file mode 100644 index 9298d46..0000000 --- a/Moonlight/App/Http/Controllers/Api/Moonlight/PaymentsController.cs +++ /dev/null @@ -1,50 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Moonlight.App.Services; - -namespace Moonlight.App.Http.Controllers.Api.Moonlight; - -[ApiController] -[Route("api/moonlight/payments")] -public class PaymentsController : Controller -{ - private readonly ConfigService ConfigService; - private readonly SubscriptionService SubscriptionService; - - public PaymentsController(ConfigService configService, SubscriptionService subscriptionService) - { - ConfigService = configService; - SubscriptionService = subscriptionService; - } - - [HttpGet("generate")] - public async Task GenerateGet([FromQuery] string key, [FromQuery] int subscriptionId) - { - var validKey = ConfigService - .GetSection("Moonlight") - .GetSection("Payments") - .GetValue("Key"); - - if (key != validKey) - return StatusCode(403); - - var token = await SubscriptionService.ProcessGenerate(subscriptionId); - - return Ok(token); - } - - [HttpPost("generate")] - public async Task GeneratePost([FromQuery] string key, [FromQuery] int subscriptionId) - { - var validKey = ConfigService - .GetSection("Moonlight") - .GetSection("Payments") - .GetValue("Key"); - - if (key != validKey) - return StatusCode(403); - - var token = await SubscriptionService.ProcessGenerate(subscriptionId); - - return Ok(token); - } -} \ No newline at end of file diff --git a/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs b/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs index a02762c..52750c4 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/Models/Files/Accesses/WingsFileAccess.cs b/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs index 6d181e2..1d64ab8 100644 --- a/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs +++ b/Moonlight/App/Models/Files/Accesses/WingsFileAccess.cs @@ -39,7 +39,7 @@ public class WingsFileAccess : IFileAccess public async Task GetDirectoryContent() { - var res = await WingsApiHelper.Get(Node, + var res = await WingsApiHelper.Get(Node, $"api/servers/{Server.Uuid}/files/list-directory?directory={Path}"); var x = new List(); @@ -130,7 +130,7 @@ public class WingsFileAccess : IFileAccess public async Task CreateDirectory(string name) { await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/create-directory", - new CreateDirectoryRequest() + new CreateDirectory() { Name = name, Path = Path @@ -171,7 +171,7 @@ public class WingsFileAccess : IFileAccess public async Task Delete(FileManagerObject managerObject) { - await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFilesRequest() + await WingsApiHelper.Post(Node, $"api/servers/{Server.Uuid}/files/delete", new DeleteFiles() { Root = Path, Files = new() @@ -183,7 +183,7 @@ public class WingsFileAccess : IFileAccess public async Task Move(FileManagerObject managerObject, string newPath) { - await WingsApiHelper.Put(Node, $"api/servers/{Server.Uuid}/files/rename", new RenameFilesRequest() + await WingsApiHelper.Put(Node, $"api/servers/{Server.Uuid}/files/rename", new RenameFiles() { Root = "/", Files = new[] diff --git a/Moonlight/App/Models/Files/FileContextAction.cs b/Moonlight/App/Models/Files/FileContextAction.cs new file mode 100644 index 0000000..7570013 --- /dev/null +++ b/Moonlight/App/Models/Files/FileContextAction.cs @@ -0,0 +1,8 @@ +namespace Moonlight.App.Models.Files; + +public class FileContextAction +{ + public string Id { get; set; } + public string Name { get; set; } + public Action Action { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/LoginDataModel.cs b/Moonlight/App/Models/Forms/LoginDataModel.cs new file mode 100644 index 0000000..63a5ac2 --- /dev/null +++ b/Moonlight/App/Models/Forms/LoginDataModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms; + +public class LoginDataModel +{ + [Required(ErrorMessage = "You need to enter an email address")] + [EmailAddress(ErrorMessage = "You need to enter a valid email address")] + public string Email { get; set; } + + [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/Forms/LoginTotpDataModel.cs b/Moonlight/App/Models/Forms/LoginTotpDataModel.cs new file mode 100644 index 0000000..b1dcca0 --- /dev/null +++ b/Moonlight/App/Models/Forms/LoginTotpDataModel.cs @@ -0,0 +1,9 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms; + +public class LoginTotpDataModel +{ + [Required(ErrorMessage = "You need to enter a 2fa code")] + public string Code { get; set; } = ""; +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/NameModel.cs b/Moonlight/App/Models/Forms/NameModel.cs new file mode 100644 index 0000000..17d832a --- /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/App/Models/Forms/PasswordModel.cs b/Moonlight/App/Models/Forms/PasswordModel.cs new file mode 100644 index 0000000..237f6a4 --- /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/Forms/SubscriptionDataModel.cs b/Moonlight/App/Models/Forms/SubscriptionDataModel.cs new file mode 100644 index 0000000..92bf8eb --- /dev/null +++ b/Moonlight/App/Models/Forms/SubscriptionDataModel.cs @@ -0,0 +1,13 @@ +using System.ComponentModel.DataAnnotations; + +namespace Moonlight.App.Models.Forms; + +public class SubscriptionDataModel +{ + [Required(ErrorMessage = "You need to enter a name")] + [MaxLength(32, ErrorMessage = "Max lenght for name is 32")] + public string Name { get; set; } = ""; + + [Required(ErrorMessage = "You need to enter a description")] + public string Description { get; set; } = ""; +} \ No newline at end of file diff --git a/Moonlight/App/Models/Log/LogData.cs b/Moonlight/App/Models/Log/LogData.cs new file mode 100644 index 0000000..645a666 --- /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/Models/Misc/AuditLogType.cs b/Moonlight/App/Models/Misc/AuditLogType.cs index d505deb..a2ccf6d 100644 --- a/Moonlight/App/Models/Misc/AuditLogType.cs +++ b/Moonlight/App/Models/Misc/AuditLogType.cs @@ -19,5 +19,9 @@ public enum AuditLogType AddDomainRecord, UpdateDomainRecord, DeleteDomainRecord, - PasswordReset + PasswordReset, + CleanupEnabled, + CleanupDisabled, + CleanupTriggered, + PasswordChange, } \ No newline at end of file diff --git a/Moonlight/App/Models/Misc/SubscriptionLimit.cs b/Moonlight/App/Models/Misc/SubscriptionLimit.cs new file mode 100644 index 0000000..6e77aba --- /dev/null +++ b/Moonlight/App/Models/Misc/SubscriptionLimit.cs @@ -0,0 +1,14 @@ +namespace Moonlight.App.Models.Misc; + +public class SubscriptionLimit +{ + public string Identifier { get; set; } = ""; + public int Amount { get; set; } + public List Options { get; set; } = new(); + + public class LimitOption + { + public string Key { get; set; } = ""; + public string Value { 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 22bf70c..a270ead 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/App/Models/Wings/Requests/CompressFiles.cs b/Moonlight/App/Models/Wings/Requests/CompressFiles.cs new file mode 100644 index 0000000..2c86667 --- /dev/null +++ b/Moonlight/App/Models/Wings/Requests/CompressFiles.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Moonlight.App.Models.Wings.Requests; + +public class CompressFiles +{ + [JsonProperty("root")] + public string Root { get; set; } + + [JsonProperty("files")] + public string[] Files { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateBackup.cs similarity index 89% rename from Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateBackup.cs index a0ce5b4..779abf1 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateBackupRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateBackup.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateBackupRequest +public class CreateBackup { [JsonProperty("adapter")] public string Adapter { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateDirectory.cs similarity index 85% rename from Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateDirectory.cs index 62c95e3..1dc6617 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateDirectoryRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateDirectory.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateDirectoryRequest +public class CreateDirectory { [JsonProperty("name")] public string Name { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs b/Moonlight/App/Models/Wings/Requests/CreateServer.cs similarity index 87% rename from Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs rename to Moonlight/App/Models/Wings/Requests/CreateServer.cs index 3288d88..7e939a4 100644 --- a/Moonlight/App/Models/Wings/Requests/CreateServerRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/CreateServer.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class CreateServerRequest +public class CreateServer { [JsonProperty("uuid")] public Guid Uuid { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/DecompressFile.cs b/Moonlight/App/Models/Wings/Requests/DecompressFile.cs new file mode 100644 index 0000000..5fb7073 --- /dev/null +++ b/Moonlight/App/Models/Wings/Requests/DecompressFile.cs @@ -0,0 +1,12 @@ +using Newtonsoft.Json; + +namespace Moonlight.App.Models.Wings.Requests; + +public class DecompressFile +{ + [JsonProperty("root")] + public string Root { get; set; } + + [JsonProperty("file")] + public string File { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs b/Moonlight/App/Models/Wings/Requests/DeleteFiles.cs similarity index 86% rename from Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs rename to Moonlight/App/Models/Wings/Requests/DeleteFiles.cs index c64487f..9988ff0 100644 --- a/Moonlight/App/Models/Wings/Requests/DeleteFilesRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/DeleteFiles.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class DeleteFilesRequest +public class DeleteFiles { [JsonProperty("root")] public string Root { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs b/Moonlight/App/Models/Wings/Requests/RenameFiles.cs similarity index 91% rename from Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs rename to Moonlight/App/Models/Wings/Requests/RenameFiles.cs index 8355cff..f565a32 100644 --- a/Moonlight/App/Models/Wings/Requests/RenameFilesRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/RenameFiles.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class RenameFilesRequest +public class RenameFiles { [JsonProperty("root")] public string Root { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs b/Moonlight/App/Models/Wings/Requests/RestoreBackup.cs similarity index 90% rename from Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs rename to Moonlight/App/Models/Wings/Requests/RestoreBackup.cs index 0dfa9cb..fcd7b8a 100644 --- a/Moonlight/App/Models/Wings/Requests/RestoreBackupRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/RestoreBackup.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class RestoreBackupRequest +public class RestoreBackup { [JsonProperty("adapter")] public string Adapter { get; set; } diff --git a/Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs b/Moonlight/App/Models/Wings/Requests/ServerPower.cs similarity index 81% rename from Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs rename to Moonlight/App/Models/Wings/Requests/ServerPower.cs index 597d9e5..e877fb7 100644 --- a/Moonlight/App/Models/Wings/Requests/ServerPowerRequest.cs +++ b/Moonlight/App/Models/Wings/Requests/ServerPower.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Requests; -public class ServerPowerRequest +public class ServerPower { [JsonProperty("action")] public string Action { get; set; } diff --git a/Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs b/Moonlight/App/Models/Wings/Resources/ListDirectory.cs similarity index 94% rename from Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs rename to Moonlight/App/Models/Wings/Resources/ListDirectory.cs index 0a67bfa..d99e15d 100644 --- a/Moonlight/App/Models/Wings/Resources/ListDirectoryRequest.cs +++ b/Moonlight/App/Models/Wings/Resources/ListDirectory.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Resources; -public class ListDirectoryRequest +public class ListDirectory { [JsonProperty("name")] public string Name { get; set; } diff --git a/Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs b/Moonlight/App/Models/Wings/Resources/ServerDetails.cs similarity index 78% rename from Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs rename to Moonlight/App/Models/Wings/Resources/ServerDetails.cs index bc89a29..b14ac56 100644 --- a/Moonlight/App/Models/Wings/Resources/ServerDetailsResponse.cs +++ b/Moonlight/App/Models/Wings/Resources/ServerDetails.cs @@ -2,7 +2,7 @@ namespace Moonlight.App.Models.Wings.Resources; -public class ServerDetailsResponse +public class ServerDetails { [JsonProperty("state")] public string State { get; set; } @@ -11,9 +11,9 @@ public class ServerDetailsResponse public bool IsSuspended { get; set; } [JsonProperty("utilization")] - public ServerDetailsResponseUtilization Utilization { get; set; } + public ServerDetailsUtilization Utilization { get; set; } - public class ServerDetailsResponseUtilization + public class ServerDetailsUtilization { [JsonProperty("memory_bytes")] public long MemoryBytes { get; set; } @@ -25,7 +25,7 @@ public class ServerDetailsResponse public double CpuAbsolute { get; set; } [JsonProperty("network")] - public ServerDetailsResponseNetwork Network { get; set; } + public ServerDetailsNetwork Network { get; set; } [JsonProperty("uptime")] public long Uptime { get; set; } @@ -37,7 +37,7 @@ public class ServerDetailsResponse public long DiskBytes { get; set; } } - public class ServerDetailsResponseNetwork + public class ServerDetailsNetwork { [JsonProperty("rx_bytes")] public long RxBytes { get; set; } diff --git a/Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.cs b/Moonlight/App/Repositories/SubscriptionRepository.cs similarity index 94% rename from Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.cs rename to Moonlight/App/Repositories/SubscriptionRepository.cs index d7f212b..3ffb678 100644 --- a/Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.cs +++ b/Moonlight/App/Repositories/SubscriptionRepository.cs @@ -2,7 +2,7 @@ using Moonlight.App.Database; using Moonlight.App.Database.Entities; -namespace Moonlight.App.Repositories.Subscriptions; +namespace Moonlight.App.Repositories; public class SubscriptionRepository : IDisposable { diff --git a/Moonlight/App/Repositories/Subscriptions/SubscriptionLimitRepository.cs b/Moonlight/App/Repositories/Subscriptions/SubscriptionLimitRepository.cs deleted file mode 100644 index f11daeb..0000000 --- a/Moonlight/App/Repositories/Subscriptions/SubscriptionLimitRepository.cs +++ /dev/null @@ -1,44 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities; - -namespace Moonlight.App.Repositories.Subscriptions; - -public class SubscriptionLimitRepository : IDisposable -{ - private readonly DataContext DataContext; - - public SubscriptionLimitRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public DbSet Get() - { - return DataContext.SubscriptionLimits; - } - - public SubscriptionLimit Add(SubscriptionLimit subscription) - { - var x = DataContext.SubscriptionLimits.Add(subscription); - DataContext.SaveChanges(); - return x.Entity; - } - - public void Update(SubscriptionLimit subscription) - { - DataContext.SubscriptionLimits.Update(subscription); - DataContext.SaveChanges(); - } - - public void Delete(SubscriptionLimit subscription) - { - DataContext.SubscriptionLimits.Remove(subscription); - DataContext.SaveChanges(); - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/CleanupService.cs b/Moonlight/App/Services/CleanupService.cs new file mode 100644 index 0000000..42e046c --- /dev/null +++ b/Moonlight/App/Services/CleanupService.cs @@ -0,0 +1,216 @@ +using System.Diagnostics; +using Microsoft.EntityFrameworkCore; +using MineStatLib; +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Daemon.Resources; +using Moonlight.App.Models.Wings; +using Moonlight.App.Repositories; +using Moonlight.App.Repositories.Servers; +using Logging.Net; +using Newtonsoft.Json; + +namespace Moonlight.App.Services; + +public class CleanupService +{ + #region Stats + public DateTime StartedAt { get; private set; } + public DateTime CompletedAt { get; private set; } + public int ServersCleaned { get; private set; } + public int CleanupsPerformed { get; private set; } + public int ServersRunning { get; private set; } + public bool IsRunning { get; private set; } + #endregion + + private readonly ConfigService ConfigService; + private readonly MessageService MessageService; + private readonly IServiceScopeFactory ServiceScopeFactory; + private readonly PeriodicTimer Timer; + + public CleanupService( + ConfigService configService, + IServiceScopeFactory serviceScopeFactory, + MessageService messageService) + { + ServiceScopeFactory = serviceScopeFactory; + MessageService = messageService; + ConfigService = configService; + + StartedAt = DateTime.Now; + CompletedAt = DateTime.Now; + IsRunning = false; + + var config = ConfigService.GetSection("Moonlight").GetSection("Cleanup"); + + if (!config.GetValue("Enable") || ConfigService.DebugMode) + { + Logger.Info("Disabling cleanup service"); + return; + } + + Timer = new(TimeSpan.FromMinutes(config.GetValue("Wait"))); + + Task.Run(Run); + } + + private async Task Run() + { + while (await Timer.WaitForNextTickAsync()) + { + IsRunning = true; + + using var scope = ServiceScopeFactory.CreateScope(); + var config = ConfigService.GetSection("Moonlight").GetSection("Cleanup"); + + var maxCpu = config.GetValue("Cpu"); + var minMemory = config.GetValue("Memory"); + var maxUptime = config.GetValue("Uptime"); + var minUptime = config.GetValue("MinUptime"); + + var nodeRepository = scope.ServiceProvider.GetRequiredService(); + var nodeService = scope.ServiceProvider.GetRequiredService(); + + var nodes = nodeRepository + .Get() + .ToArray(); + + foreach (var node in nodes) + { + try + { + var cpuStats = await nodeService.GetCpuStats(node); + var memoryStats = await nodeService.GetMemoryStats(node); + + if (cpuStats.Usage > maxCpu || memoryStats.Free < minMemory) + { + var containerStats = await nodeService.GetContainerStats(node); + + var serverRepository = scope.ServiceProvider.GetRequiredService(); + var imageRepository = scope.ServiceProvider.GetRequiredService(); + + var images = imageRepository + .Get() + .ToArray(); + + var imagesWithFlag = images + .Where(x => + (JsonConvert.DeserializeObject(x.TagsJson) ?? Array.Empty()).Contains("cleanup") + ) + .ToArray(); + + var containerMappedToServers = new Dictionary(); + + foreach (var container in containerStats.Containers) + { + if (Guid.TryParse(container.Name, out Guid uuid)) + { + var server = serverRepository + .Get() + .Include(x => x.Image) + .Include(x => x.MainAllocation) + .Include(x => x.Variables) + .FirstOrDefault(x => x.Uuid == uuid); + + if (server != null && imagesWithFlag.Any(y => y.Id == server.Image.Id)) + { + containerMappedToServers.Add(container, server); + } + } + } + + var serverService = scope.ServiceProvider.GetRequiredService(); + + foreach (var containerMapped in containerMappedToServers) + { + var server = containerMapped.Value; + + try + { + var stats = await serverService.GetDetails(server); + + if (server.IsCleanupException) + { + if (stats.Utilization.Uptime > TimeSpan.FromHours(maxUptime).TotalMilliseconds) + { + var players = GetPlayers(node, server.MainAllocation); + + if (players == 0) + { + await serverService.SetPowerState(server, PowerSignal.Restart); + + ServersCleaned++; + } + else + { + ServersRunning++; + } + + await MessageService.Emit("cleanup.updated", null); + } + } + else + { + if (stats.Utilization.Uptime > TimeSpan.FromMinutes(minUptime).TotalMilliseconds) + { + var players = GetPlayers(node, server.MainAllocation); + + if (players < 1) + { + var j2SVar = server.Variables.FirstOrDefault(x => x.Key == "J2S"); + var handleJ2S = j2SVar != null && j2SVar.Value == "1"; + + if (handleJ2S) + { + await serverService.SetPowerState(server, PowerSignal.Restart); + } + else + { + await serverService.SetPowerState(server, PowerSignal.Stop); + } + + ServersCleaned++; + } + else + { + ServersRunning++; + } + + await MessageService.Emit("cleanup.updated", null); + } + } + } + catch (Exception e) + { + Logger.Warn($"Error checking server {server.Name} ({server.Id})"); + Logger.Warn(e); + } + } + } + } + catch (Exception e) + { + Logger.Error($"Error performing cleanup on node {node.Name} ({node.Id})"); + Logger.Error(e); + } + } + + IsRunning = false; + CleanupsPerformed++; + await MessageService.Emit("cleanup.updated", null); + } + } + + private int GetPlayers(Node node, NodeAllocation allocation) + { + var ms = new MineStat(node.Fqdn, (ushort)allocation.Port); + + //TODO: Add fake player check + + if (ms.ServerUp) + { + return ms.CurrentPlayersInt; + } + + return -1; + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/ConfigService.cs b/Moonlight/App/Services/ConfigService.cs index 7a315cb..ed124f6 100644 --- a/Moonlight/App/Services/ConfigService.cs +++ b/Moonlight/App/Services/ConfigService.cs @@ -1,4 +1,5 @@ using System.Text; +using Logging.Net; using Microsoft.Extensions.Primitives; using Moonlight.App.Helpers; @@ -21,6 +22,9 @@ public class ConfigService : IConfiguration if (debugVar != null) DebugMode = bool.Parse(debugVar); + + if(DebugMode) + Logger.Debug("Debug mode enabled"); } public IEnumerable GetChildren() diff --git a/Moonlight/App/Services/DomainService.cs b/Moonlight/App/Services/DomainService.cs index b2b2b1f..4bdbf9b 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/Interop/ModalService.cs b/Moonlight/App/Services/Interop/ModalService.cs new file mode 100644 index 0000000..881fb2e --- /dev/null +++ b/Moonlight/App/Services/Interop/ModalService.cs @@ -0,0 +1,23 @@ +using Microsoft.JSInterop; + +namespace Moonlight.App.Services.Interop; + +public class ModalService +{ + private readonly IJSRuntime JsRuntime; + + public ModalService(IJSRuntime jsRuntime) + { + JsRuntime = jsRuntime; + } + + public async Task Show(string name) + { + await JsRuntime.InvokeVoidAsync("moonlight.modals.show", name); + } + + public async Task Hide(string name) + { + await JsRuntime.InvokeVoidAsync("moonlight.modals.hide", name); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/Interop/ToastService.cs b/Moonlight/App/Services/Interop/ToastService.cs index 3eff8a1..5e1839d 100644 --- a/Moonlight/App/Services/Interop/ToastService.cs +++ b/Moonlight/App/Services/Interop/ToastService.cs @@ -30,4 +30,19 @@ public class ToastService { await JsRuntime.InvokeVoidAsync("showSuccessToast", message); } + + public async Task CreateProcessToast(string id, string text) + { + await JsRuntime.InvokeVoidAsync("createToast", id, text); + } + + public async Task UpdateProcessToast(string id, string text) + { + await JsRuntime.InvokeVoidAsync("modifyToast", id, text); + } + + public async Task RemoveProcessToast(string id) + { + await JsRuntime.InvokeVoidAsync("removeToast", id); + } } \ No newline at end of file diff --git a/Moonlight/App/Services/LogServices/AuditLogService.cs b/Moonlight/App/Services/LogServices/AuditLogService.cs index 7e32f58..4b0fdf8 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); @@ -36,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); @@ -62,4 +68,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/LogServices/ErrorLogService.cs b/Moonlight/App/Services/LogServices/ErrorLogService.cs index 6c41945..4328c95 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/LogServices/SecurityLogService.cs b/Moonlight/App/Services/LogServices/SecurityLogService.cs index d276a2b..f58fa19 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 871a1b0..0f70d59 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 0542a09..7969bd7 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -75,11 +75,11 @@ public class ServerService return s; } - public async Task GetDetails(Server s) + public async Task GetDetails(Server s) { Server server = EnsureNodeData(s); - return await WingsApiHelper.Get( + return await WingsApiHelper.Get( server.Node, $"api/servers/{server.Uuid}" ); @@ -91,12 +91,16 @@ public class ServerService var rawSignal = signal.ToString().ToLower(); - await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/power", new ServerPowerRequest() + await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/power", new ServerPower() { 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) @@ -118,7 +122,7 @@ public class ServerService serverData.Backups.Add(backup); ServerRepository.Update(serverData); - await WingsApiHelper.Post(serverData.Node, $"api/servers/{serverData.Uuid}/backup", new CreateBackupRequest() + await WingsApiHelper.Post(serverData.Node, $"api/servers/{serverData.Uuid}/backup", new CreateBackup() { Adapter = "wings", Uuid = backup.Uuid, @@ -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; } @@ -158,13 +166,17 @@ public class ServerService Server server = EnsureNodeData(s); await WingsApiHelper.Post(server.Node, $"api/servers/{server.Uuid}/backup/{serverBackup.Uuid}/restore", - new RestoreBackupRequest() + new RestoreBackup() { Adapter = "wings" }); 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}"; } @@ -299,19 +319,26 @@ public class ServerService try { - await WingsApiHelper.Post(node, $"api/servers", new CreateServerRequest() + await WingsApiHelper.Post(node, $"api/servers", new CreateServer() { Uuid = newServerData.Uuid, StartOnCompletion = false }); - await AuditLogService.Log(AuditLogType.CreateServer, newServerData.Uuid.ToString()); + await AuditLogService.Log(AuditLogType.CreateServer, x => + { + x.Add(newServerData.Uuid); + }); return newServerData; } 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); @@ -325,7 +352,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) @@ -334,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 bce9382..f35519e 100644 --- a/Moonlight/App/Services/Sessions/IdentityService.cs +++ b/Moonlight/App/Services/Sessions/IdentityService.cs @@ -89,12 +89,15 @@ 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) { - await ErrorLogService.Log(e); + await ErrorLogService.Log(e, x => {}); return null; } @@ -130,7 +133,7 @@ public class IdentityService } catch (Exception e) { - await ErrorLogService.Log(e); + await ErrorLogService.Log(e, x => {}); return null; } } diff --git a/Moonlight/App/Services/SubscriptionAdminService.cs b/Moonlight/App/Services/SubscriptionAdminService.cs new file mode 100644 index 0000000..fbbe84b --- /dev/null +++ b/Moonlight/App/Services/SubscriptionAdminService.cs @@ -0,0 +1,45 @@ +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Misc; +using Moonlight.App.Repositories; +using Newtonsoft.Json; + +namespace Moonlight.App.Services; + +public class SubscriptionAdminService +{ + private readonly SubscriptionRepository SubscriptionRepository; + private readonly OneTimeJwtService OneTimeJwtService; + + public SubscriptionAdminService(OneTimeJwtService oneTimeJwtService, SubscriptionRepository subscriptionRepository) + { + OneTimeJwtService = oneTimeJwtService; + SubscriptionRepository = subscriptionRepository; + } + + public Task GetLimits(Subscription subscription) + { + return Task.FromResult( + JsonConvert.DeserializeObject(subscription.LimitsJson) + ?? Array.Empty() + ); + } + + public Task SaveLimits(Subscription subscription, SubscriptionLimit[] limits) + { + subscription.LimitsJson = JsonConvert.SerializeObject(limits); + SubscriptionRepository.Update(subscription); + + return Task.CompletedTask; + } + + public Task GenerateCode(Subscription subscription, int duration) + { + return Task.FromResult( + OneTimeJwtService.Generate(data => + { + data.Add("subscription", subscription.Id.ToString()); + data.Add("duration", duration.ToString()); + }, TimeSpan.FromDays(10324)) + ); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/SubscriptionService.cs b/Moonlight/App/Services/SubscriptionService.cs index 1627eca..f5e77c9 100644 --- a/Moonlight/App/Services/SubscriptionService.cs +++ b/Moonlight/App/Services/SubscriptionService.cs @@ -3,126 +3,138 @@ using Moonlight.App.Database.Entities; using Moonlight.App.Exceptions; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories; -using Moonlight.App.Repositories.Subscriptions; -using Moonlight.App.Services.LogServices; using Moonlight.App.Services.Sessions; +using Newtonsoft.Json; namespace Moonlight.App.Services; public class SubscriptionService { private readonly SubscriptionRepository SubscriptionRepository; - private readonly UserRepository UserRepository; - private readonly IdentityService IdentityService; - private readonly ConfigService ConfigService; private readonly OneTimeJwtService OneTimeJwtService; - private readonly AuditLogService AuditLogService; + private readonly IdentityService IdentityService; + private readonly UserRepository UserRepository; + private readonly ConfigService ConfigService; - public SubscriptionService(SubscriptionRepository subscriptionRepository, - UserRepository userRepository, - IdentityService identityService, - ConfigService configService, + public SubscriptionService( + SubscriptionRepository subscriptionRepository, OneTimeJwtService oneTimeJwtService, - AuditLogService auditLogService) + IdentityService identityService, + UserRepository userRepository, + ConfigService configService) { SubscriptionRepository = subscriptionRepository; - UserRepository = userRepository; - IdentityService = identityService; - ConfigService = configService; OneTimeJwtService = oneTimeJwtService; - AuditLogService = auditLogService; + IdentityService = identityService; + UserRepository = userRepository; + ConfigService = configService; } - public async Task Get() + public async Task GetCurrent() { - var user = await IdentityService.Get(); - var advancedUser = UserRepository - .Get() - .Include(x => x.Subscription) - .First(x => x.Id == user!.Id); + var user = await GetCurrentUser(); - if (advancedUser.Subscription == null) + if (user == null || user.CurrentSubscription == null) return null; - return SubscriptionRepository - .Get() - .Include(x => x.Limits) - .Include("Limits.Image") - .First(x => x.Id == advancedUser.Subscription.Id); - } - public async Task Cancel() - { - var user = await IdentityService.Get(); - user!.Subscription = null; - UserRepository.Update(user!); + var subscriptionEnd = user.SubscriptionSince.ToUniversalTime().AddDays(user.SubscriptionDuration); - await AuditLogService.Log(AuditLogType.CancelSubscription, new[] { user.Email }); - } - public Task GetAvailable() - { - return Task.FromResult( - SubscriptionRepository - .Get() - .Include(x => x.Limits) - .ToArray() - ); - } - public Task GenerateBuyUrl(Subscription subscription) - { - var url = ConfigService - .GetSection("Moonlight") - .GetSection("Payments") - .GetValue("BaseUrl"); + if (subscriptionEnd > DateTime.UtcNow) + { + return user.CurrentSubscription; + } - return Task.FromResult($"{url}/products/{subscription.SellPassId}"); - } - public Task ProcessGenerate(int subscriptionId) - { - var subscription = SubscriptionRepository - .Get() - .FirstOrDefault(x => x.Id == subscriptionId); - - if (subscription == null) - throw new DisplayException("Unknown subscription id"); - - var token = OneTimeJwtService.Generate( - options => - { - options.Add("id", subscription.Id.ToString()); - } - ); - - return Task.FromResult(token); + return null; } public async Task ApplyCode(string code) { - var user = (await IdentityService.Get())!; - var values = await OneTimeJwtService.Validate(code); + var data = await OneTimeJwtService.Validate(code); - if (values == null) - throw new DisplayException("Invalid subscription code"); + if (data == null) + throw new DisplayException("Invalid or expired subscription code"); - if (!values.ContainsKey("id")) - throw new DisplayException("Subscription code is missing the id"); - - var id = int.Parse(values["id"]); + var id = int.Parse(data["subscription"]); + var duration = int.Parse(data["duration"]); var subscription = SubscriptionRepository .Get() .FirstOrDefault(x => x.Id == id); if (subscription == null) - throw new DisplayException("The subscription the code is referring does not exist"); + throw new DisplayException("The subscription the code is associated with does not exist"); - user.Subscription = subscription; - user.SubscriptionDuration = subscription.Duration; - user.SubscriptionSince = DateTime.Now; + var user = await GetCurrentUser(); + + if (user == null) + throw new DisplayException("Unable to determine current user"); + + user.CurrentSubscription = subscription; + user.SubscriptionDuration = duration; + user.SubscriptionSince = DateTime.UtcNow; UserRepository.Update(user); - - await OneTimeJwtService.Revoke(code); - await AuditLogService.Log(AuditLogType.ApplySubscriptionCode, new[] { user.Email, subscription.Id.ToString() }); + await OneTimeJwtService.Revoke(code); + } + + public async Task GetLimit(string identifier) + { + var configSection = ConfigService.GetSection("Moonlight").GetSection("Subscriptions"); + + var defaultLimits = configSection.GetValue("defaultLimits"); + + var subscription = await GetCurrent(); + + if (subscription == null) + { + var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier); + + if (foundDefault != null) + return foundDefault; + + return new() + { + Identifier = identifier, + Amount = 0 + }; + } + else + { + var subscriptionLimits = + JsonConvert.DeserializeObject(subscription.LimitsJson) + ?? Array.Empty(); + + var foundLimit = subscriptionLimits.FirstOrDefault(x => x.Identifier == identifier); + + if (foundLimit != null) + return foundLimit; + + var foundDefault = defaultLimits.FirstOrDefault(x => x.Identifier == identifier); + + if (foundDefault != null) + return foundDefault; + + return new() + { + Identifier = identifier, + Amount = 0 + }; + } + } + + private async Task GetCurrentUser() + { + var user = await IdentityService.Get(); + + if (user == null) + return null; + + var userWithData = UserRepository + .Get() + .Include(x => x.CurrentSubscription) + .First(x => x.Id == user.Id); + + return userWithData; } } \ No newline at end of file diff --git a/Moonlight/App/Services/TotpService.cs b/Moonlight/App/Services/TotpService.cs index be76546..caffc7a 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; @@ -46,13 +47,23 @@ public class TotpService public async Task Enable() { var user = (await IdentityService.Get())!; - - user.TotpEnabled = true; + user.TotpSecret = GenerateSecret(); UserRepository.Update(user); - await AuditLogService.Log(AuditLogType.EnableTotp, user.Email); + await AuditLogService.Log(AuditLogType.EnableTotp, x => + { + x.Add(user.Email); + }); + } + + public async Task EnforceTotpLogin() + { + var user = (await IdentityService.Get())!; + + user.TotpEnabled = true; + UserRepository.Update(user); } public async Task Disable() @@ -63,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 2cf233e..60ec0a9 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); } @@ -91,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"); } @@ -100,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");; } @@ -125,18 +136,28 @@ 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 { - 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"); } } else { - await AuditLogService.Log(AuditLogType.Login, email); + await AuditLogService.Log(AuditLogType.Login, x => + { + x.Add(email); + }); return await GenerateToken(user!, true); } } @@ -149,7 +170,10 @@ public class UserService if (isSystemAction) { - await AuditLogService.LogSystem(AuditLogType.ChangePassword, user.Email); + await AuditLogService.LogSystem(AuditLogType.ChangePassword, x=> + { + x.Add(user.Email); + }); } else { @@ -160,7 +184,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); + }); } } @@ -170,17 +197,27 @@ 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"); } 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; } - 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"); } @@ -218,7 +255,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/Moonlight.csproj b/Moonlight/Moonlight.csproj index 6580ff2..27c1bed 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -58,6 +58,8 @@ <_ContentIncludedByDefault Remove="wwwroot\css\site.css" /> <_ContentIncludedByDefault Remove="Shared\Components\Tables\Column.razor" /> <_ContentIncludedByDefault Remove="Shared\Components\Tables\Table.razor" /> + <_ContentIncludedByDefault Remove="Shared\Views\Admin\Servers\Cleanup\Exceptions\Add.razor" /> + <_ContentIncludedByDefault Remove="Shared\Views\Admin\Servers\Cleanup\Exceptions\Edit.razor" /> @@ -66,7 +68,6 @@ - diff --git a/Moonlight/Pages/_Layout.cshtml b/Moonlight/Pages/_Layout.cshtml index cbfcf6e..b82364f 100644 --- a/Moonlight/Pages/_Layout.cshtml +++ b/Moonlight/Pages/_Layout.cshtml @@ -101,6 +101,7 @@ + @@ -112,5 +113,6 @@ + \ No newline at end of file diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 4543609..d762971 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -9,7 +9,6 @@ using Moonlight.App.Repositories; using Moonlight.App.Repositories.Domains; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Repositories.Servers; -using Moonlight.App.Repositories.Subscriptions; using Moonlight.App.Services; using Moonlight.App.Services.DiscordBot; using Moonlight.App.Services.Interop; @@ -58,13 +57,12 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -89,14 +87,19 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + + builder.Services.AddSingleton(); + // Loggers builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -153,6 +156,9 @@ namespace Moonlight // Support service var supportServerService = app.Services.GetRequiredService(); + // cleanup service + _ = app.Services.GetRequiredService(); + // Discord bot service //var discordBotService = app.Services.GetRequiredService(); diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor index b3ffcd8..f9ee3ac 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 9540015..9dcafe0 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 c215f4d..810a356 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 43cc89a..846f0d8 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/Components/Auth/Login.razor b/Moonlight/Shared/Components/Auth/Login.razor index ccf9177..dd642e3 100644 --- a/Moonlight/Shared/Components/Auth/Login.razor +++ b/Moonlight/Shared/Components/Auth/Login.razor @@ -9,8 +9,12 @@ @using Moonlight.App.Services @using Moonlight.App.Exceptions @using Logging.Net +@using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Misc @using Moonlight.App.Services.OAuth2 @using Moonlight.App.Services.Sessions +@using System.ComponentModel.DataAnnotations +@using Moonlight.App.Models.Forms @inject AlertService AlertService @inject UserService UserService @@ -24,10 +28,10 @@
-
- @if (!TotpRequired) - { -
+ @if (!TotpRequired) + { + +

Sign In

@@ -61,12 +65,12 @@
-
- +
+
-
- +
+
@@ -78,35 +82,33 @@
- - +
- } - else - { + +
+ Not registered yet? + + + Sign up + +
+ + } + else + { +
- +
- - +
- } - -
- Not registered yet? - - - Sign up - -
-
+ + }
@@ -114,37 +116,54 @@ @code { - private string Email = ""; - private string Password = ""; + private LoginDataModel LoginData = new(); + private LoginTotpDataModel TotpData = new(); private bool TotpRequired = false; - private string TotpCode = ""; private async Task DoLogin() { try { - Email = Email.ToLower().Trim(); - - TotpRequired = await UserService.CheckTotp(Email, Password); + LoginData.Email = LoginData.Email.ToLower().Trim(); - if (!TotpRequired) + if (string.IsNullOrEmpty(TotpData.Code)) { - var token = await UserService.Login(Email, Password); + TotpRequired = await UserService.CheckTotp(LoginData.Email, LoginData.Password); + + if (!TotpRequired) + { + var token = await UserService.Login(LoginData.Email, LoginData.Password); + await CookieService.SetValue("token", token, 10); + + if (NavigationManager.Uri.EndsWith("login")) + NavigationManager.NavigateTo("/", true); + else + NavigationManager.NavigateTo(NavigationManager.Uri, true); + } + else + { + await InvokeAsync(StateHasChanged); + } + } + else + { + var token = await UserService.Login(LoginData.Email, LoginData.Password, TotpData.Code); await CookieService.SetValue("token", token, 10); - - if(NavigationManager.Uri.EndsWith("login")) + + if (NavigationManager.Uri.EndsWith("login")) NavigationManager.NavigateTo("/", true); else NavigationManager.NavigateTo(NavigationManager.Uri, true); } - else - { - await InvokeAsync(StateHasChanged); - } } catch (DisplayException e) { + // Reset state + LoginData = new(); + TotpData = new(); + TotpRequired = false; + await AlertService.Error( SmartTranslateService.Translate("Error"), SmartTranslateService.Translate(e.Message) @@ -152,6 +171,11 @@ } catch (Exception e) { + // Reset state + LoginData = new(); + TotpData = new(); + TotpRequired = false; + await AlertService.Error( SmartTranslateService.Translate("Error"), SmartTranslateService.Translate("An error occured while logging you in") @@ -167,7 +191,7 @@ var url = await GoogleOAuth2Service.GetUrl(); NavigationManager.NavigateTo(url, true); } - + private async Task DoDiscord() { var url = await DiscordOAuth2Service.GetUrl(); diff --git a/Moonlight/Shared/Components/Auth/PasswordChangeView.razor b/Moonlight/Shared/Components/Auth/PasswordChangeView.razor new file mode 100644 index 0000000..f57d1aa --- /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/Components/Auth/UserDataSetView.razor b/Moonlight/Shared/Components/Auth/UserDataSetView.razor new file mode 100644 index 0000000..d1191ec --- /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/Components/ErrorBoundaries/ComponentErrorBoundary.razor b/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor index d8f29c9..c540c4c 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); } diff --git a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor index 0a2888c..9af01b0 100644 --- a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor +++ b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor @@ -3,27 +3,30 @@ @using Moonlight.Shared.Components.Partials @inject SmartTranslateService TranslationService +@inject IJSRuntime JsRuntime -
- -
- -@if (!HideControls) -{ -