diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index 23b93734..3e2875f4 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -35,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/Subscription.cs b/Moonlight/App/Database/Entities/Subscription.cs index 7f2fa6ef..ab0b8c77 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 96c06911..00000000 --- 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 f99b8c60..a0654a33 100644 --- a/Moonlight/App/Database/Entities/User.cs +++ b/Moonlight/App/Database/Entities/User.cs @@ -8,44 +8,21 @@ public class User public int Id { get; set; } // Personal data - - [Required] - [MinLength(3, ErrorMessage = "Invalid first name")] - [MaxLength(64, ErrorMessage = "Max lenght reached")] + public string FirstName { get; set; } = ""; - [Required] - [MinLength(3, ErrorMessage = "Invalid last name")] - [MaxLength(64, ErrorMessage = "Max lenght reached")] public string LastName { get; set; } = ""; - [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; } = ""; - [Required] - [RegularExpression(@"^(?:[A-Z] \d|[^\W\d_]{2,}\.?)(?:[- '’][^\W\d_]+\.?)*\s+[1-9]\d{0,3} ?[a-zA-Z]?(?: ?[/-] ?[1-9]\d{0,3} ?[a-zA-Z]?)?$", - ErrorMessage = "Street and house number required")] - [MaxLength(128, ErrorMessage = "Max lenght reached")] public string Address { get; set; } = ""; - [Required] - [MinLength(3, ErrorMessage = "Invalid city")] - [MaxLength(128, ErrorMessage = "Max lenght reached")] public string City { get; set; } = ""; - [Required] - [MinLength(3, ErrorMessage = "Invalid state")] - [MaxLength(64, ErrorMessage = "Max lenght reached")] public string State { get; set; } = ""; - [Required] - [MinLength(3, ErrorMessage = "Invalid country")] - [MaxLength(64, ErrorMessage = "Max lenght reached")] public string Country { get; set; } = ""; // States @@ -65,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/20230403130734_RemovedOldSubscriptionData.Designer.cs b/Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.Designer.cs new file mode 100644 index 00000000..d5429e9a --- /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 00000000..23c0f92b --- /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 00000000..e0d6429f --- /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 00000000..5299884f --- /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 dba0d962..d670d747 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -609,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"); @@ -625,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") @@ -710,25 +674,25 @@ namespace Moonlight.App.Database.Migrations b.Property("Address") .IsRequired() - .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("longtext"); b.Property("Admin") .HasColumnType("tinyint(1)"); b.Property("City") .IsRequired() - .HasMaxLength(128) - .HasColumnType("varchar(128)"); + .HasColumnType("longtext"); b.Property("Country") .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("longtext"); b.Property("CreatedAt") .HasColumnType("datetime(6)"); + b.Property("CurrentSubscriptionId") + .HasColumnType("int"); + b.Property("DiscordId") .HasColumnType("bigint"); @@ -738,13 +702,11 @@ namespace Moonlight.App.Database.Migrations b.Property("FirstName") .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("longtext"); b.Property("LastName") .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("longtext"); b.Property("Password") .IsRequired() @@ -752,8 +714,7 @@ namespace Moonlight.App.Database.Migrations b.Property("State") .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("longtext"); b.Property("Status") .HasColumnType("int"); @@ -761,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") @@ -785,7 +743,7 @@ namespace Moonlight.App.Database.Migrations b.HasKey("Id"); - b.HasIndex("SubscriptionId"); + b.HasIndex("CurrentSubscriptionId"); b.ToTable("Users"); }); @@ -975,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") @@ -1007,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 => @@ -1053,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/Http/Controllers/Api/Moonlight/PaymentsController.cs b/Moonlight/App/Http/Controllers/Api/Moonlight/PaymentsController.cs deleted file mode 100644 index 9298d46d..00000000 --- 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 a02762c5..52750c40 100644 --- a/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs +++ b/Moonlight/App/Http/Controllers/Api/Moonlight/ResourcesController.cs @@ -21,7 +21,10 @@ public class ResourcesController : Controller { if (name.Contains("..")) { - await SecurityLogService.Log(SecurityLogType.PathTransversal, name); + await SecurityLogService.Log(SecurityLogType.PathTransversal, x => + { + x.Add(name); + }); return NotFound(); } diff --git a/Moonlight/App/Models/Forms/SubscriptionDataModel.cs b/Moonlight/App/Models/Forms/SubscriptionDataModel.cs new file mode 100644 index 00000000..92bf8ebc --- /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 00000000..645a666f --- /dev/null +++ b/Moonlight/App/Models/Log/LogData.cs @@ -0,0 +1,7 @@ +namespace Moonlight.App.Models.Log; + +public class LogData +{ + public Type Type { get; set; } + public string Value { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Misc/SubscriptionLimit.cs b/Moonlight/App/Models/Misc/SubscriptionLimit.cs new file mode 100644 index 00000000..6e77abaf --- /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/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 d7f212bc..3ffb678f 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 f11daeb8..00000000 --- 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/DomainService.cs b/Moonlight/App/Services/DomainService.cs index b2b2b1fb..4bdbf9b3 100644 --- a/Moonlight/App/Services/DomainService.cs +++ b/Moonlight/App/Services/DomainService.cs @@ -169,7 +169,11 @@ public class DomainService })); } - await AuditLogService.Log(AuditLogType.AddDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.AddDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } public async Task UpdateDnsRecord(Domain d, DnsRecord dnsRecord) @@ -199,7 +203,11 @@ public class DomainService })); } - await AuditLogService.Log(AuditLogType.UpdateDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.UpdateDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } public async Task DeleteDnsRecord(Domain d, DnsRecord dnsRecord) @@ -210,7 +218,11 @@ public class DomainService await Client.Zones.DnsRecords.DeleteAsync(domain.SharedDomain.CloudflareId, dnsRecord.Id) ); - await AuditLogService.Log(AuditLogType.DeleteDomainRecord, new[] { d.Id.ToString(), dnsRecord.Name }); + await AuditLogService.Log(AuditLogType.DeleteDomainRecord, x => + { + x.Add(d.Id); + x.Add(dnsRecord.Name); + }); } private Domain EnsureData(Domain domain) diff --git a/Moonlight/App/Services/LogServices/AuditLogService.cs b/Moonlight/App/Services/LogServices/AuditLogService.cs index 7e32f588..4b0fdf87 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 6c419450..4328c95a 100644 --- a/Moonlight/App/Services/LogServices/ErrorLogService.cs +++ b/Moonlight/App/Services/LogServices/ErrorLogService.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using System.Reflection; using Moonlight.App.Database.Entities.LogsEntries; +using Moonlight.App.Models.Log; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Services.Sessions; using Newtonsoft.Json; @@ -18,15 +19,17 @@ public class ErrorLogService HttpContextAccessor = httpContextAccessor; } - public Task Log(Exception exception, params object[] objects) + public Task Log(Exception exception, Action data) { var ip = GetIp(); + var al = new ErrorLogParameters(); + data(al); var entry = new ErrorLogEntry() { Ip = ip, System = false, - JsonData = !objects.Any() ? "" : JsonConvert.SerializeObject(objects), + JsonData = al.Build(), Class = NameOfCallingClass(), Stacktrace = exception.ToStringDemystified() }; @@ -36,12 +39,15 @@ public class ErrorLogService return Task.CompletedTask; } - public Task LogSystem(Exception exception, params object[] objects) + public Task LogSystem(Exception exception, Action data) { + var al = new ErrorLogParameters(); + data(al); + var entry = new ErrorLogEntry() { System = true, - JsonData = !objects.Any() ? "" : JsonConvert.SerializeObject(objects), + JsonData = al.Build(), Class = NameOfCallingClass(), Stacktrace = exception.ToStringDemystified() }; @@ -87,4 +93,23 @@ public class ErrorLogService return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString(); } + + public class ErrorLogParameters + { + private List Data = new List(); + + public void Add(object data) + { + Data.Add(new LogData() + { + Type = typeof(T), + Value = data.ToString() + }); + } + + internal string Build() + { + return JsonConvert.SerializeObject(Data); + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/LogServices/SecurityLogService.cs b/Moonlight/App/Services/LogServices/SecurityLogService.cs index d276a2b9..f58fa198 100644 --- a/Moonlight/App/Services/LogServices/SecurityLogService.cs +++ b/Moonlight/App/Services/LogServices/SecurityLogService.cs @@ -1,4 +1,5 @@ using Moonlight.App.Database.Entities.LogsEntries; +using Moonlight.App.Models.Log; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories.LogEntries; using Moonlight.App.Services.Sessions; @@ -17,16 +18,18 @@ public class SecurityLogService HttpContextAccessor = httpContextAccessor; } - public Task Log(SecurityLogType type, params object[] data) + public Task Log(SecurityLogType type, Action data) { var ip = GetIp(); + var al = new SecurityLogParameters(); + data(al); var entry = new SecurityLogEntry() { Ip = ip, Type = type, System = false, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); @@ -34,13 +37,16 @@ public class SecurityLogService return Task.CompletedTask; } - public Task LogSystem(SecurityLogType type, params object[] data) + public Task LogSystem(SecurityLogType type, Action data) { + var al = new SecurityLogParameters(); + data(al); + var entry = new SecurityLogEntry() { Type = type, System = true, - JsonData = data.Length == 0 ? "" : JsonConvert.SerializeObject(data) + JsonData = al.Build() }; Repository.Add(entry); @@ -60,4 +66,24 @@ public class SecurityLogService return HttpContextAccessor.HttpContext.Connection.RemoteIpAddress!.ToString(); } + + + public class SecurityLogParameters + { + private List Data = new List(); + + public void Add(object data) + { + Data.Add(new LogData() + { + Type = typeof(T), + Value = data.ToString() + }); + } + + internal string Build() + { + return JsonConvert.SerializeObject(Data); + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/OneTimeJwtService.cs b/Moonlight/App/Services/OneTimeJwtService.cs index 871a1b02..0f70d597 100644 --- a/Moonlight/App/Services/OneTimeJwtService.cs +++ b/Moonlight/App/Services/OneTimeJwtService.cs @@ -76,7 +76,10 @@ public class OneTimeJwtService } catch (SignatureVerificationException) { - await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, token); + await SecurityLogService.LogSystem(SecurityLogType.ManipulatedJwt, x => + { + x.Add(token); + }); return null; } catch (Exception e) diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index 2f69fd7b..7969bd78 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -96,7 +96,11 @@ public class ServerService Action = rawSignal }); - await AuditLogService.Log(AuditLogType.ChangePowerState, new[] { server.Uuid.ToString(), rawSignal }); + await AuditLogService.Log(AuditLogType.ChangePowerState, x => + { + x.Add(server.Uuid); + x.Add(rawSignal); + }); } public async Task CreateBackup(Server server) @@ -126,7 +130,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.CreateBackup, - new[] { serverData.Uuid.ToString(), backup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(backup.Uuid); + }); return backup; } @@ -164,7 +172,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.RestoreBackup, - new[] { s.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(serverBackup.Uuid); + }); } public async Task DeleteBackup(Server server, ServerBackup serverBackup) @@ -186,7 +198,11 @@ public class ServerService await MessageService.Emit("wings.backups.delete", backup); await AuditLogService.Log(AuditLogType.DeleteBackup, - new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(backup.Uuid); + }); } public async Task DownloadBackup(Server s, ServerBackup serverBackup) @@ -200,7 +216,11 @@ public class ServerService }); await AuditLogService.Log(AuditLogType.DownloadBackup, - new[] { serverBackup.Uuid.ToString(), serverBackup.Uuid.ToString() }); + x => + { + x.Add(server.Uuid); + x.Add(serverBackup.Uuid); + }); return $"https://{server.Node.Fqdn}:{server.Node.HttpPort}/download/backup?token={token}"; } @@ -305,13 +325,20 @@ public class ServerService StartOnCompletion = false }); - await AuditLogService.Log(AuditLogType.CreateServer, newServerData.Uuid.ToString()); + await AuditLogService.Log(AuditLogType.CreateServer, x => + { + x.Add(newServerData.Uuid); + }); return newServerData; } 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 bce93828..f35519e1 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 00000000..fbbe84bd --- /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 1627eca4..f5e77c95 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 0e359fec..caffc7a7 100644 --- a/Moonlight/App/Services/TotpService.cs +++ b/Moonlight/App/Services/TotpService.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Models.Misc; +using Moonlight.App.Database.Entities; +using Moonlight.App.Models.Misc; using Moonlight.App.Repositories; using Moonlight.App.Services.LogServices; using Moonlight.App.Services.Sessions; @@ -51,7 +52,10 @@ public class TotpService UserRepository.Update(user); - await AuditLogService.Log(AuditLogType.EnableTotp, user.Email); + await AuditLogService.Log(AuditLogType.EnableTotp, x => + { + x.Add(user.Email); + }); } public async Task EnforceTotpLogin() @@ -70,7 +74,10 @@ public class TotpService UserRepository.Update(user); - await AuditLogService.Log(AuditLogType.DisableTotp, user.Email); + await AuditLogService.Log(AuditLogType.DisableTotp,x => + { + x.Add(user.Email); + }); } private string GenerateSecret() diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index 2cf233ea..60ec0a9d 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/Program.cs b/Moonlight/Program.cs index c1519c11..d7629715 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,7 +87,6 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -98,6 +95,9 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddSingleton(); // Loggers diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor index b3ffcd8f..f9ee3ac8 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePassword.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - Password change for @(Data[0]) + Password change for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor index 95400158..9dcafe02 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryChangePowerState.razor @@ -2,6 +2,7 @@ @using Moonlight.App.Helpers @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @using Moonlight.App.Repositories.Servers @inject ServerRepository ServerRepository @@ -18,11 +19,11 @@
@if (Server == null) { - Change power state for @(Data[0]) to @(Data[1]) + Change power state for @(Data[0].Value) to @(Data[1].Value) } else { - Change power state for @(Server.Name) to @(Data[1]) + Change power state for @(Server.Name) to @(Data[1].Value) }
@@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private Server? Server; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - Server = ServerRepository.Get().FirstOrDefault(x => x.Uuid == Guid.Parse(Data[0])); + Server = ServerRepository.Get().FirstOrDefault(x => x.Uuid == Guid.Parse(Data[0].Value)); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor index c215f4df..810a3568 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryLogin.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - New login for @(Data[0]) + New login for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor index 43cc89a3..846f0d86 100644 --- a/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor +++ b/Moonlight/Shared/Components/AuditLogEntrys/AuditLogEntryRegister.razor @@ -3,6 +3,7 @@ @using Moonlight.App.Repositories @using Newtonsoft.Json @using Moonlight.App.Database.Entities +@using Moonlight.App.Models.Log @inject UserRepository UserRepository @@ -18,7 +19,7 @@
@if (User == null) { - Register for @(Data[0]) + Register for @(Data[0].Value) } else { @@ -38,18 +39,18 @@ public AuditLogEntry Entry { get; set; } private User? User; - private string[] Data; + private LogData[] Data; protected override void OnInitialized() { - Data = JsonConvert.DeserializeObject(Entry.JsonData)!; + Data = JsonConvert.DeserializeObject(Entry.JsonData)!; } protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { - User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0]); + User = UserRepository.Get().FirstOrDefault(x => x.Email == Data[0].Value); await InvokeAsync(StateHasChanged); } diff --git a/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor b/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor index d8f29c90..c540c4c5 100644 --- a/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor +++ b/Moonlight/Shared/Components/ErrorBoundaries/ComponentErrorBoundary.razor @@ -53,7 +53,7 @@ else { receivedExceptions.Add(exception); - await ErrorLogService.Log(exception); + await ErrorLogService.Log(exception, x => {}); await base.OnErrorAsync(exception); } diff --git a/Moonlight/Shared/Components/Forms/DeleteButton.razor b/Moonlight/Shared/Components/Forms/DeleteButton.razor new file mode 100644 index 00000000..4c37ec9f --- /dev/null +++ b/Moonlight/Shared/Components/Forms/DeleteButton.razor @@ -0,0 +1,57 @@ +@using Moonlight.App.Services +@using Moonlight.App.Services.Interop + +@inject SmartTranslateService SmartTranslateService +@inject AlertService AlertService + +@if (!Working) +{ + +} +else +{ + +} + +@code +{ + private bool Working { get; set; } = false; + + [Parameter] + public Func? OnClick { get; set; } + + [Parameter] + public bool Confirm { get; set; } = false; + + private async Task Do() + { + Working = true; + StateHasChanged(); + await Task.Run(async () => + { + if (Confirm) + { + var b = await AlertService.YesNo( + SmartTranslateService.Translate("Are you sure?"), + SmartTranslateService.Translate("Do you really want to delete it?"), + SmartTranslateService.Translate("Yes"), + SmartTranslateService.Translate("No") + ); + + if (b) + { + if(OnClick != null) + await OnClick.Invoke(); + } + + } + + Working = false; + await InvokeAsync(StateHasChanged); + }); + } +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Forms/SmartForm.razor b/Moonlight/Shared/Components/Forms/SmartForm.razor index 0eb23002..9b3acd60 100644 --- a/Moonlight/Shared/Components/Forms/SmartForm.razor +++ b/Moonlight/Shared/Components/Forms/SmartForm.razor @@ -33,13 +33,13 @@ public object Model { get; set; } [Parameter] - public EventCallback OnValidSubmit { get; set; } + public Func? OnValidSubmit { get; set; } [Parameter] - public EventCallback OnInvalidSubmit { get; set; } + public Func? OnInvalidSubmit { get; set; } [Parameter] - public EventCallback OnSubmit { get; set; } + public Func? OnSubmit { get; set; } [Parameter] public RenderFragment ChildContent { get; set; } @@ -67,8 +67,14 @@ await Task.Run(async () => { - await InvokeAsync(() => OnValidSubmit.InvokeAsync(context)); - await InvokeAsync(() => OnSubmit.InvokeAsync(context)); + await InvokeAsync(async () => + { + if (OnValidSubmit != null) + await OnValidSubmit.Invoke(); + + if (OnSubmit != null) + await OnSubmit.Invoke(); + }); Working = false; await InvokeAsync(StateHasChanged); @@ -87,7 +93,10 @@ await InvokeAsync(StateHasChanged); - await OnInvalidSubmit.InvokeAsync(context); - await OnSubmit.InvokeAsync(context); + if (OnInvalidSubmit != null) + await OnInvalidSubmit.Invoke(); + + if (OnSubmit != null) + await OnSubmit.Invoke(); } } \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/SidebarMenu.razor b/Moonlight/Shared/Components/Partials/SidebarMenu.razor index 5ce76e18..37dd7d6d 100644 --- a/Moonlight/Shared/Components/Partials/SidebarMenu.razor +++ b/Moonlight/Shared/Components/Partials/SidebarMenu.razor @@ -225,6 +225,14 @@ else Support
+ diff --git a/Moonlight/Shared/Views/Profile/Index.razor b/Moonlight/Shared/Views/Profile/Index.razor index 81fd74df..030e4a3e 100644 --- a/Moonlight/Shared/Views/Profile/Index.razor +++ b/Moonlight/Shared/Views/Profile/Index.razor @@ -87,8 +87,10 @@ User = await IdentityService.Get(); } - private void Save() + private Task Save() { UserRepository.Update(User); + + return Task.CompletedTask; } } diff --git a/Moonlight/Shared/Views/Profile/Security.razor b/Moonlight/Shared/Views/Profile/Security.razor index e648de9d..db0bf9f8 100644 --- a/Moonlight/Shared/Views/Profile/Security.razor +++ b/Moonlight/Shared/Views/Profile/Security.razor @@ -236,7 +236,7 @@ private async void Enable() { - await AuditLogService.Log(AuditLogType.EnableTotp, "Totp enabled"); + await AuditLogService.Log(AuditLogType.EnableTotp, x => x.Add("Totp enabled")); await TotpService.Enable(); TotpEnabled = await TotpService.GetEnabled(); TotpSecret = await TotpService.GetSecret(); @@ -262,7 +262,7 @@ private async void Disable() { - await AuditLogService.Log(AuditLogType.DisableTotp, "Totp disabled"); + await AuditLogService.Log(AuditLogType.DisableTotp, x => x.Add("Totp disabled")); await TotpService.Disable(); NavigationManager.NavigateTo(NavigationManager.Uri, true); } @@ -286,7 +286,7 @@ { await UserService.ChangePassword(User, Password); - await AuditLogService.Log(AuditLogType.PasswordChange, "The password has been set to a new one"); + await AuditLogService.Log(AuditLogType.PasswordChange, x => x.Add("The password has been set to a new one")); // Reload to make the user login again NavigationManager.NavigateTo(NavigationManager.Uri, true); diff --git a/Moonlight/Shared/Views/Profile/Subscriptions.razor b/Moonlight/Shared/Views/Profile/Subscriptions.razor deleted file mode 100644 index 30b8d196..00000000 --- a/Moonlight/Shared/Views/Profile/Subscriptions.razor +++ /dev/null @@ -1,126 +0,0 @@ -@page "/profile/subscriptions" -@using Moonlight.App.Services -@using Moonlight.Shared.Components.Navigations -@using Moonlight.App.Database.Entities -@using Moonlight.App.Helpers - -@inject SubscriptionService SubscriptionService -@inject SmartTranslateService SmartTranslateService -@inject NavigationManager NavigationManager - - - - -
-
- @if (User.Subscription != null) - { -
-
-

- Active until @(Formatter.FormatDate(User.SubscriptionSince!.Value.AddDays(User.SubscriptionDuration))) -

-

- We will send you a notification upon subscription expiration -

-
-
-
- - -
-
-
- } - else - { -
-
- -
-
- - -
-
- -
- @if (Available.Any()) - { - @foreach (var sub in Available) - { -
-
-
-
- @(sub.Name) -
-
-
@(sub.Description)
-
-
-
- - -
-
-
- } - } - else - { -
- No subscription available -
- } -
- } -
-
-
- -@code -{ - [CascadingParameter] - public User User { get; set; } - - private Subscription? Subscription; - private Subscription[] Available; - - private string Code = ""; - - private LazyLoader LazyLoader; - - private async Task Load(LazyLoader lazyLoader) - { - Subscription = await SubscriptionService.Get(); - Available = await SubscriptionService.GetAvailable(); - } - - private async Task Cancel() - { - await SubscriptionService.Cancel(); - } - - private async Task Buy(Subscription subscription) - { - var url = await SubscriptionService.GenerateBuyUrl(subscription); - - NavigationManager.NavigateTo(url); - } - - private async Task ApplyCode() - { - await SubscriptionService.ApplyCode(Code); - await LazyLoader.Reload(); - } -} \ No newline at end of file diff --git a/Moonlight/resources/lang/de_de.lang b/Moonlight/resources/lang/de_de.lang index 41f79bca..0cfc0d21 100644 --- a/Moonlight/resources/lang/de_de.lang +++ b/Moonlight/resources/lang/de_de.lang @@ -454,3 +454,11 @@ Finish activation;Finish activation New password;New password Secure your account;Secure your account 2fa adds another layer of security to your account. You have to enter a 6 digit code in order to login.;2fa adds another layer of security to your account. You have to enter a 6 digit code in order to login. +New subscription;New subscription +You need to enter a name;You need to enter a name +You need to enter a description;You need to enter a description +Add new limit;Add new limit +Create subscription;Create subscription +Options;Options +Amount;Amount +Do you really want to delete it?;Do you really want to delete it?