From 6db877d8fcad9840a763bbe173ad3430d52a94aa Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Mon, 3 Apr 2023 15:09:22 +0200 Subject: [PATCH 1/2] Removed old subscription data --- Moonlight/App/Database/DataContext.cs | 2 - .../App/Database/Entities/Subscription.cs | 1 - .../Database/Entities/SubscriptionLimit.cs | 11 - Moonlight/App/Database/Entities/User.cs | 30 +- ...734_RemovedOldSubscriptionData.Designer.cs | 962 ++++++++++++++++++ ...230403130734_RemovedOldSubscriptionData.cs | 269 +++++ .../Migrations/DataContextModelSnapshot.cs | 117 +-- .../Api/Moonlight/PaymentsController.cs | 50 - .../SubscriptionLimitRepository.cs | 44 - .../Subscriptions/SubscriptionRepository.cs | 44 - Moonlight/App/Services/SubscriptionService.cs | 128 --- Moonlight/Program.cs | 4 - Moonlight/Shared/Views/Admin/Users/View.razor | 11 +- .../Shared/Views/Profile/Subscriptions.razor | 126 --- 14 files changed, 1239 insertions(+), 560 deletions(-) delete mode 100644 Moonlight/App/Database/Entities/SubscriptionLimit.cs create mode 100644 Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.Designer.cs create mode 100644 Moonlight/App/Database/Migrations/20230403130734_RemovedOldSubscriptionData.cs delete mode 100644 Moonlight/App/Http/Controllers/Api/Moonlight/PaymentsController.cs delete mode 100644 Moonlight/App/Repositories/Subscriptions/SubscriptionLimitRepository.cs delete mode 100644 Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.cs delete mode 100644 Moonlight/App/Services/SubscriptionService.cs delete mode 100644 Moonlight/Shared/Views/Profile/Subscriptions.razor diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index 23b93734..0f970404 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -35,8 +35,6 @@ 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; } diff --git a/Moonlight/App/Database/Entities/Subscription.cs b/Moonlight/App/Database/Entities/Subscription.cs index 7f2fa6ef..bd893d73 100644 --- a/Moonlight/App/Database/Entities/Subscription.cs +++ b/Moonlight/App/Database/Entities/Subscription.cs @@ -7,5 +7,4 @@ public class Subscription public string Description { get; set; } = ""; public string SellPassId { get; set; } = ""; public int Duration { get; set; } - public List Limits { get; set; } = new(); } \ 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..397e3790 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,4 @@ 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 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/DataContextModelSnapshot.cs b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs index dba0d962..6aa632ad 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -599,65 +599,6 @@ namespace Moonlight.App.Database.Migrations b.ToTable("SharedDomains"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Duration") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("SellPassId") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Subscriptions"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.SubscriptionLimit", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Amount") - .HasColumnType("int"); - - b.Property("Cpu") - .HasColumnType("int"); - - b.Property("Disk") - .HasColumnType("int"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Memory") - .HasColumnType("int"); - - b.Property("SubscriptionId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.HasIndex("SubscriptionId"); - - b.ToTable("SubscriptionLimits"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => { b.Property("Id") @@ -710,21 +651,18 @@ 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)"); @@ -738,13 +676,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,21 +688,11 @@ namespace Moonlight.App.Database.Migrations b.Property("State") .IsRequired() - .HasMaxLength(64) - .HasColumnType("varchar(64)"); + .HasColumnType("longtext"); b.Property("Status") .HasColumnType("int"); - b.Property("SubscriptionDuration") - .HasColumnType("int"); - - b.Property("SubscriptionId") - .HasColumnType("int"); - - b.Property("SubscriptionSince") - .HasColumnType("datetime(6)"); - b.Property("SupportPending") .HasColumnType("tinyint(1)"); @@ -785,8 +711,6 @@ namespace Moonlight.App.Database.Migrations b.HasKey("Id"); - b.HasIndex("SubscriptionId"); - b.ToTable("Users"); }); @@ -975,21 +899,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") @@ -1005,15 +914,6 @@ namespace Moonlight.App.Database.Migrations b.Navigation("Sender"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => - { - b.HasOne("Moonlight.App.Database.Entities.Subscription", "Subscription") - .WithMany() - .HasForeignKey("SubscriptionId"); - - b.Navigation("Subscription"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => { b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel") @@ -1053,11 +953,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/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/Repositories/Subscriptions/SubscriptionRepository.cs b/Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.cs deleted file mode 100644 index d7f212bc..00000000 --- a/Moonlight/App/Repositories/Subscriptions/SubscriptionRepository.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 SubscriptionRepository : IDisposable -{ - private readonly DataContext DataContext; - - public SubscriptionRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public DbSet Get() - { - return DataContext.Subscriptions; - } - - public Subscription Add(Subscription subscription) - { - var x = DataContext.Subscriptions.Add(subscription); - DataContext.SaveChanges(); - return x.Entity; - } - - public void Update(Subscription subscription) - { - DataContext.Subscriptions.Update(subscription); - DataContext.SaveChanges(); - } - - public void Delete(Subscription subscription) - { - DataContext.Subscriptions.Remove(subscription); - DataContext.SaveChanges(); - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/SubscriptionService.cs b/Moonlight/App/Services/SubscriptionService.cs deleted file mode 100644 index 1627eca4..00000000 --- a/Moonlight/App/Services/SubscriptionService.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Microsoft.EntityFrameworkCore; -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; - -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; - - public SubscriptionService(SubscriptionRepository subscriptionRepository, - UserRepository userRepository, - IdentityService identityService, - ConfigService configService, - OneTimeJwtService oneTimeJwtService, - AuditLogService auditLogService) - { - SubscriptionRepository = subscriptionRepository; - UserRepository = userRepository; - IdentityService = identityService; - ConfigService = configService; - OneTimeJwtService = oneTimeJwtService; - AuditLogService = auditLogService; - } - - public async Task Get() - { - var user = await IdentityService.Get(); - var advancedUser = UserRepository - .Get() - .Include(x => x.Subscription) - .First(x => x.Id == user!.Id); - - if (advancedUser.Subscription == 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!); - - 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"); - - 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); - } - - public async Task ApplyCode(string code) - { - var user = (await IdentityService.Get())!; - var values = await OneTimeJwtService.Validate(code); - - if (values == null) - throw new DisplayException("Invalid subscription code"); - - if (!values.ContainsKey("id")) - throw new DisplayException("Subscription code is missing the id"); - - var id = int.Parse(values["id"]); - - var subscription = SubscriptionRepository - .Get() - .FirstOrDefault(x => x.Id == id); - - if (subscription == null) - throw new DisplayException("The subscription the code is referring does not exist"); - - user.Subscription = subscription; - user.SubscriptionDuration = subscription.Duration; - user.SubscriptionSince = DateTime.Now; - - UserRepository.Update(user); - - await OneTimeJwtService.Revoke(code); - - await AuditLogService.Log(AuditLogType.ApplySubscriptionCode, new[] { user.Email, subscription.Id.ToString() }); - } -} \ No newline at end of file diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index c1519c11..e0584a8e 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,8 +57,6 @@ 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(); @@ -89,7 +86,6 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Moonlight/Shared/Views/Admin/Users/View.razor b/Moonlight/Shared/Views/Admin/Users/View.razor index dc3d1604..b4851f22 100644 --- a/Moonlight/Shared/Views/Admin/Users/View.razor +++ b/Moonlight/Shared/Views/Admin/Users/View.razor @@ -196,16 +196,7 @@ else
- @if (User.Subscription == null) - { - - None - - } - else - { - @(User.Subscription.Name) - } +
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 From 010436cdb6e01c6e4fa99a8117ad00a2e49bf8db Mon Sep 17 00:00:00 2001 From: Marcel Baumgartner Date: Mon, 3 Apr 2023 19:29:07 +0200 Subject: [PATCH 2/2] Added services. Added admin ui. Added delete button --- Moonlight/App/Database/DataContext.cs | 1 + .../App/Database/Entities/Subscription.cs | 3 +- Moonlight/App/Database/Entities/User.cs | 6 + ...31343_AddedNewSubscriptionData.Designer.cs | 1005 +++++++++++++++++ ...20230403131343_AddedNewSubscriptionData.cs | 94 ++ .../Migrations/DataContextModelSnapshot.cs | 43 + .../App/Models/Forms/SubscriptionDataModel.cs | 13 + .../App/Models/Misc/SubscriptionLimit.cs | 14 + .../Repositories/SubscriptionRepository.cs | 44 + .../App/Services/SubscriptionAdminService.cs | 45 + Moonlight/App/Services/SubscriptionService.cs | 140 +++ Moonlight/Program.cs | 4 + .../Components/Forms/DeleteButton.razor | 57 + .../Shared/Components/Forms/SmartForm.razor | 23 +- .../Components/Partials/SidebarMenu.razor | 8 + .../Views/Admin/Subscriptions/Index.razor | 72 ++ .../Views/Admin/Subscriptions/New.razor | 137 +++ Moonlight/Shared/Views/Profile/Index.razor | 4 +- Moonlight/resources/lang/de_de.lang | 8 + 19 files changed, 1711 insertions(+), 10 deletions(-) create mode 100644 Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.Designer.cs create mode 100644 Moonlight/App/Database/Migrations/20230403131343_AddedNewSubscriptionData.cs create mode 100644 Moonlight/App/Models/Forms/SubscriptionDataModel.cs create mode 100644 Moonlight/App/Models/Misc/SubscriptionLimit.cs create mode 100644 Moonlight/App/Repositories/SubscriptionRepository.cs create mode 100644 Moonlight/App/Services/SubscriptionAdminService.cs create mode 100644 Moonlight/App/Services/SubscriptionService.cs create mode 100644 Moonlight/Shared/Components/Forms/DeleteButton.razor create mode 100644 Moonlight/Shared/Views/Admin/Subscriptions/Index.razor create mode 100644 Moonlight/Shared/Views/Admin/Subscriptions/New.razor diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index 0f970404..3e2875f4 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -41,6 +41,7 @@ public class DataContext : DbContext 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 bd893d73..ab0b8c77 100644 --- a/Moonlight/App/Database/Entities/Subscription.cs +++ b/Moonlight/App/Database/Entities/Subscription.cs @@ -5,6 +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 string LimitsJson { 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 397e3790..a0654a33 100644 --- a/Moonlight/App/Database/Entities/User.cs +++ b/Moonlight/App/Database/Entities/User.cs @@ -42,4 +42,10 @@ public class User // Date stuff public DateTime CreatedAt { get; set; } = DateTime.UtcNow; public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + + // Subscriptions + + 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/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 6aa632ad..d670d747 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -599,6 +599,29 @@ namespace Moonlight.App.Database.Migrations 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") @@ -667,6 +690,9 @@ namespace Moonlight.App.Database.Migrations b.Property("CreatedAt") .HasColumnType("datetime(6)"); + b.Property("CurrentSubscriptionId") + .HasColumnType("int"); + b.Property("DiscordId") .HasColumnType("bigint"); @@ -693,6 +719,12 @@ namespace Moonlight.App.Database.Migrations b.Property("Status") .HasColumnType("int"); + b.Property("SubscriptionDuration") + .HasColumnType("int"); + + b.Property("SubscriptionSince") + .HasColumnType("datetime(6)"); + b.Property("SupportPending") .HasColumnType("tinyint(1)"); @@ -711,6 +743,8 @@ namespace Moonlight.App.Database.Migrations b.HasKey("Id"); + b.HasIndex("CurrentSubscriptionId"); + b.ToTable("Users"); }); @@ -914,6 +948,15 @@ namespace Moonlight.App.Database.Migrations 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") 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/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/SubscriptionRepository.cs b/Moonlight/App/Repositories/SubscriptionRepository.cs new file mode 100644 index 00000000..3ffb678f --- /dev/null +++ b/Moonlight/App/Repositories/SubscriptionRepository.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Repositories; + +public class SubscriptionRepository : IDisposable +{ + private readonly DataContext DataContext; + + public SubscriptionRepository(DataContext dataContext) + { + DataContext = dataContext; + } + + public DbSet Get() + { + return DataContext.Subscriptions; + } + + public Subscription Add(Subscription subscription) + { + var x = DataContext.Subscriptions.Add(subscription); + DataContext.SaveChanges(); + return x.Entity; + } + + public void Update(Subscription subscription) + { + DataContext.Subscriptions.Update(subscription); + DataContext.SaveChanges(); + } + + public void Delete(Subscription subscription) + { + DataContext.Subscriptions.Remove(subscription); + DataContext.SaveChanges(); + } + + public void Dispose() + { + DataContext.Dispose(); + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..f5e77c95 --- /dev/null +++ b/Moonlight/App/Services/SubscriptionService.cs @@ -0,0 +1,140 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database.Entities; +using Moonlight.App.Exceptions; +using Moonlight.App.Models.Misc; +using Moonlight.App.Repositories; +using Moonlight.App.Services.Sessions; +using Newtonsoft.Json; + +namespace Moonlight.App.Services; + +public class SubscriptionService +{ + private readonly SubscriptionRepository SubscriptionRepository; + private readonly OneTimeJwtService OneTimeJwtService; + private readonly IdentityService IdentityService; + private readonly UserRepository UserRepository; + private readonly ConfigService ConfigService; + + public SubscriptionService( + SubscriptionRepository subscriptionRepository, + OneTimeJwtService oneTimeJwtService, + IdentityService identityService, + UserRepository userRepository, + ConfigService configService) + { + SubscriptionRepository = subscriptionRepository; + OneTimeJwtService = oneTimeJwtService; + IdentityService = identityService; + UserRepository = userRepository; + ConfigService = configService; + } + + public async Task GetCurrent() + { + var user = await GetCurrentUser(); + + if (user == null || user.CurrentSubscription == null) + return null; + + var subscriptionEnd = user.SubscriptionSince.ToUniversalTime().AddDays(user.SubscriptionDuration); + + if (subscriptionEnd > DateTime.UtcNow) + { + return user.CurrentSubscription; + } + + return null; + } + + public async Task ApplyCode(string code) + { + var data = await OneTimeJwtService.Validate(code); + + if (data == null) + throw new DisplayException("Invalid or expired subscription code"); + + 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 associated with does not exist"); + + 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); + } + + 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/Program.cs b/Moonlight/Program.cs index e0584a8e..d7629715 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -62,6 +62,7 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -94,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/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 +