diff --git a/Moonlight/App/ApiClients/CloudPanel/CloudPanelApiHelper.cs b/Moonlight/App/ApiClients/CloudPanel/CloudPanelApiHelper.cs deleted file mode 100644 index fd6e99fb..00000000 --- a/Moonlight/App/ApiClients/CloudPanel/CloudPanelApiHelper.cs +++ /dev/null @@ -1,83 +0,0 @@ -using Moonlight.App.Database.Entities; -using Moonlight.App.Models.Plesk.Resources; -using Newtonsoft.Json; -using RestSharp; - -namespace Moonlight.App.ApiClients.CloudPanel; - -public class CloudPanelApiHelper -{ - private readonly RestClient Client; - - public CloudPanelApiHelper() - { - Client = new(); - } - - public async Task Post(Database.Entities.CloudPanel cloudPanel, string resource, object? body) - { - var request = CreateRequest(cloudPanel, resource); - - request.Method = Method.Post; - - if(body != null) - request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - - var response = await Client.ExecuteAsync(request); - - if (!response.IsSuccessful) - { - if (response.StatusCode != 0) - { - throw new CloudPanelException( - $"An error occured: ({response.StatusCode}) {response.Content}", - (int)response.StatusCode - ); - } - else - { - throw new Exception($"An internal error occured: {response.ErrorMessage}"); - } - } - } - - public async Task Delete(Database.Entities.CloudPanel cloudPanel, string resource, object? body) - { - var request = CreateRequest(cloudPanel, resource); - - request.Method = Method.Delete; - - if(body != null) - request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); - - var response = await Client.ExecuteAsync(request); - - if (!response.IsSuccessful) - { - if (response.StatusCode != 0) - { - throw new CloudPanelException( - $"An error occured: ({response.StatusCode}) {response.Content}", - (int)response.StatusCode - ); - } - else - { - throw new Exception($"An internal error occured: {response.ErrorMessage}"); - } - } - } - - private RestRequest CreateRequest(Database.Entities.CloudPanel cloudPanel, string resource) - { - var url = $"{cloudPanel.ApiUrl}/" + resource; - - var request = new RestRequest(url); - - request.AddHeader("Content-Type", "application/json"); - request.AddHeader("Accept", "application/json"); - request.AddHeader("Authorization", "Bearer " + cloudPanel.ApiKey); - - return request; - } -} \ No newline at end of file diff --git a/Moonlight/App/ApiClients/CloudPanel/CloudPanelException.cs b/Moonlight/App/ApiClients/CloudPanel/CloudPanelException.cs deleted file mode 100644 index a7610348..00000000 --- a/Moonlight/App/ApiClients/CloudPanel/CloudPanelException.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Runtime.Serialization; - -namespace Moonlight.App.ApiClients.CloudPanel; - -[Serializable] -public class CloudPanelException : Exception -{ - public int StatusCode { get; set; } - - public CloudPanelException() - { - } - - public CloudPanelException(string message, int statusCode) : base(message) - { - StatusCode = statusCode; - } - - public CloudPanelException(string message) : base(message) - { - } - - public CloudPanelException(string message, Exception inner) : base(message, inner) - { - } - - protected CloudPanelException( - SerializationInfo info, - StreamingContext context) : base(info, context) - { - } -} \ No newline at end of file diff --git a/Moonlight/App/ApiClients/CloudPanel/Requests/AddDatabase.cs b/Moonlight/App/ApiClients/CloudPanel/Requests/AddDatabase.cs deleted file mode 100644 index 26d8d4bb..00000000 --- a/Moonlight/App/ApiClients/CloudPanel/Requests/AddDatabase.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.ApiClients.CloudPanel.Requests; - -public class AddDatabase -{ - [JsonProperty("domainName")] - public string DomainName { get; set; } - - [JsonProperty("databaseName")] - public string DatabaseName { get; set; } - - [JsonProperty("databaseUserName")] - public string DatabaseUserName { get; set; } - - [JsonProperty("databaseUserPassword")] - public string DatabaseUserPassword { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/ApiClients/CloudPanel/Requests/AddPhpSite.cs b/Moonlight/App/ApiClients/CloudPanel/Requests/AddPhpSite.cs deleted file mode 100644 index 9e04eeff..00000000 --- a/Moonlight/App/ApiClients/CloudPanel/Requests/AddPhpSite.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.ApiClients.CloudPanel.Requests; - -public class AddPhpSite -{ - [JsonProperty("domainName")] public string DomainName { get; set; } = ""; - - [JsonProperty("siteUser")] public string SiteUser { get; set; } = ""; - - [JsonProperty("siteUserPassword")] public string SiteUserPassword { get; set; } = ""; - - [JsonProperty("vHostTemplate")] public string VHostTemplate { get; set; } = ""; - - [JsonProperty("phpVersion")] public string PhpVersion { get; set; } = ""; -} \ No newline at end of file diff --git a/Moonlight/App/ApiClients/CloudPanel/Requests/InstallLetsEncrypt.cs b/Moonlight/App/ApiClients/CloudPanel/Requests/InstallLetsEncrypt.cs deleted file mode 100644 index e10068fd..00000000 --- a/Moonlight/App/ApiClients/CloudPanel/Requests/InstallLetsEncrypt.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.ApiClients.CloudPanel.Requests; - -public class InstallLetsEncrypt -{ - [JsonProperty("domainName")] - public string DomainName { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Database/DataContext.cs b/Moonlight/App/Database/DataContext.cs index 9c92b5b8..dc3e77de 100644 --- a/Moonlight/App/Database/DataContext.cs +++ b/Moonlight/App/Database/DataContext.cs @@ -2,7 +2,6 @@ using Moonlight.App.Database.Entities; using Moonlight.App.Database.Entities.LogsEntries; using Moonlight.App.Database.Entities.Notification; -using Moonlight.App.Database.Interceptors; using Moonlight.App.Models.Misc; using Moonlight.App.Services; @@ -30,7 +29,8 @@ public class DataContext : DbContext public DbSet AuditLog { get; set; } public DbSet ErrorLog { get; set; } public DbSet SecurityLog { get; set; } - + public DbSet SupportMessages { get; set; } + public DbSet SharedDomains { get; set; } public DbSet Domains { get; set; } public DbSet Revokes { get; set; } @@ -38,13 +38,10 @@ public class DataContext : DbContext public DbSet NotificationActions { get; set; } public DbSet DdosAttacks { get; set; } public DbSet Subscriptions { get; set; } + public DbSet PleskServers { get; set; } + public DbSet Websites { get; set; } public DbSet Statistics { get; set; } public DbSet NewsEntries { get; set; } - - public DbSet CloudPanels { get; set; } - public DbSet Databases { get; set; } - public DbSet WebSpaces { get; set; } - public DbSet SupportChatMessages { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { @@ -68,9 +65,6 @@ public class DataContext : DbContext builder.EnableRetryOnFailure(5); } ); - - if(ConfigService.SqlDebugMode) - optionsBuilder.AddInterceptors(new SqlLoggingInterceptor()); } } } \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/DockerImage.cs b/Moonlight/App/Database/Entities/DockerImage.cs index 047d1faa..4ad61376 100644 --- a/Moonlight/App/Database/Entities/DockerImage.cs +++ b/Moonlight/App/Database/Entities/DockerImage.cs @@ -1,10 +1,7 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.Database.Entities; +namespace Moonlight.App.Database.Entities; public class DockerImage { - [JsonIgnore] public int Id { get; set; } public bool Default { get; set; } = false; public string Name { get; set; } = ""; diff --git a/Moonlight/App/Database/Entities/Image.cs b/Moonlight/App/Database/Entities/Image.cs index 1711940d..6e2b6041 100644 --- a/Moonlight/App/Database/Entities/Image.cs +++ b/Moonlight/App/Database/Entities/Image.cs @@ -1,10 +1,7 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.Database.Entities; +namespace Moonlight.App.Database.Entities; public class Image { - [JsonIgnore] public int Id { get; set; } public Guid Uuid { get; set; } public string Name { get; set; } = ""; diff --git a/Moonlight/App/Database/Entities/ImageVariable.cs b/Moonlight/App/Database/Entities/ImageVariable.cs index 8a394a70..dd14b223 100644 --- a/Moonlight/App/Database/Entities/ImageVariable.cs +++ b/Moonlight/App/Database/Entities/ImageVariable.cs @@ -1,10 +1,7 @@ -using Newtonsoft.Json; - -namespace Moonlight.App.Database.Entities; +namespace Moonlight.App.Database.Entities; public class ImageVariable { - [JsonIgnore] public int Id { get; set; } public string Key { get; set; } = ""; public string DefaultValue { get; set; } = ""; diff --git a/Moonlight/App/Database/Entities/MySqlDatabase.cs b/Moonlight/App/Database/Entities/MySqlDatabase.cs deleted file mode 100644 index c9cdc6ef..00000000 --- a/Moonlight/App/Database/Entities/MySqlDatabase.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Moonlight.App.Database.Entities; - -public class MySqlDatabase -{ - public int Id { get; set; } - public WebSpace WebSpace { get; set; } - public string UserName { get; set; } = ""; - public string Password { get; set; } = ""; -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/CloudPanel.cs b/Moonlight/App/Database/Entities/PleskServer.cs similarity index 76% rename from Moonlight/App/Database/Entities/CloudPanel.cs rename to Moonlight/App/Database/Entities/PleskServer.cs index de872b0f..a4cd6307 100644 --- a/Moonlight/App/Database/Entities/CloudPanel.cs +++ b/Moonlight/App/Database/Entities/PleskServer.cs @@ -1,10 +1,9 @@ namespace Moonlight.App.Database.Entities; -public class CloudPanel +public class PleskServer { public int Id { get; set; } public string Name { get; set; } = ""; public string ApiUrl { get; set; } = ""; public string ApiKey { get; set; } = ""; - public string Host { get; set; } = ""; } \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/SupportChatMessage.cs b/Moonlight/App/Database/Entities/SupportChatMessage.cs deleted file mode 100644 index 47ad3e6b..00000000 --- a/Moonlight/App/Database/Entities/SupportChatMessage.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Moonlight.App.Models.Misc; - -namespace Moonlight.App.Database.Entities; - -public class SupportChatMessage -{ - public int Id { get; set; } - - public string Content { get; set; } = ""; - public string Attachment { get; set; } = ""; - - public User? Sender { get; set; } - public User Recipient { get; set; } - - public bool IsQuestion { get; set; } = false; - public QuestionType QuestionType { get; set; } - public string Answer { get; set; } = ""; - - public DateTime CreatedAt { get; set; } - public DateTime UpdatedAt { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/SupportMessage.cs b/Moonlight/App/Database/Entities/SupportMessage.cs new file mode 100644 index 00000000..df1019d4 --- /dev/null +++ b/Moonlight/App/Database/Entities/SupportMessage.cs @@ -0,0 +1,17 @@ +using Moonlight.App.Models.Misc; + +namespace Moonlight.App.Database.Entities; + +public class SupportMessage +{ + public int Id { get; set; } + public string Message { get; set; } = ""; + public User? Sender { get; set; } = null; + public User? Recipient { get; set; } = null; + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public bool IsQuestion { get; set; } = false; + public QuestionType Type { get; set; } + public string Answer { get; set; } = ""; + public bool IsSystem { get; set; } = false; + public bool IsSupport { get; set; } = false; +} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/User.cs b/Moonlight/App/Database/Entities/User.cs index 254ca5d6..790d4e20 100644 --- a/Moonlight/App/Database/Entities/User.cs +++ b/Moonlight/App/Database/Entities/User.cs @@ -1,4 +1,5 @@ -using Moonlight.App.Models.Misc; +using System.ComponentModel.DataAnnotations; +using Moonlight.App.Models.Misc; namespace Moonlight.App.Database.Entities; @@ -33,7 +34,7 @@ public class User // Security public bool TotpEnabled { get; set; } = false; public string TotpSecret { get; set; } = ""; - public DateTime TokenValidTime { get; set; } = DateTime.UtcNow; + public DateTime TokenValidTime { get; set; } = DateTime.Now; // Discord public ulong DiscordId { get; set; } diff --git a/Moonlight/App/Database/Entities/WebSpace.cs b/Moonlight/App/Database/Entities/WebSpace.cs deleted file mode 100644 index 1112fdf6..00000000 --- a/Moonlight/App/Database/Entities/WebSpace.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Moonlight.App.Database.Entities; - -public class WebSpace -{ - public int Id { get; set; } - public string Domain { get; set; } = ""; - public string UserName { get; set; } = ""; - public string Password { get; set; } = ""; - public string VHostTemplate { get; set; } = ""; - public User Owner { get; set; } - public List Databases { get; set; } = new(); - public CloudPanel CloudPanel { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Database/Entities/Website.cs b/Moonlight/App/Database/Entities/Website.cs new file mode 100644 index 00000000..56e9fd12 --- /dev/null +++ b/Moonlight/App/Database/Entities/Website.cs @@ -0,0 +1,12 @@ +namespace Moonlight.App.Database.Entities; + +public class Website +{ + public int Id { get; set; } + public string BaseDomain { get; set; } = ""; + public int PleskId { get; set; } + public PleskServer PleskServer { get; set; } + public User Owner { get; set; } + public string FtpLogin { get; set; } = ""; + public string FtpPassword { get; set; } = ""; +} \ No newline at end of file diff --git a/Moonlight/App/Database/Interceptors/SqlLoggingInterceptor.cs b/Moonlight/App/Database/Interceptors/SqlLoggingInterceptor.cs deleted file mode 100644 index 06e51413..00000000 --- a/Moonlight/App/Database/Interceptors/SqlLoggingInterceptor.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Data.Common; -using Logging.Net; -using Microsoft.EntityFrameworkCore.Diagnostics; - -namespace Moonlight.App.Database.Interceptors; - -public class SqlLoggingInterceptor : DbCommandInterceptor -{ - public override InterceptionResult ReaderExecuting( - DbCommand command, - CommandEventData eventData, - InterceptionResult result) - { - LogSql(command.CommandText); - return base.ReaderExecuting(command, eventData, result); - } - - public override InterceptionResult ScalarExecuting( - DbCommand command, - CommandEventData eventData, - InterceptionResult result) - { - LogSql(command.CommandText); - return base.ScalarExecuting(command, eventData, result); - } - - public override InterceptionResult NonQueryExecuting( - DbCommand command, - CommandEventData eventData, - InterceptionResult result) - { - LogSql(command.CommandText); - return base.NonQueryExecuting(command, eventData, result); - } - - private void LogSql(string sql) - { - Logger.Info($"[SQL DEBUG] {sql.Replace("\n", "")}"); - } -} \ No newline at end of file diff --git a/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.Designer.cs b/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.Designer.cs deleted file mode 100644 index 26edf52f..00000000 --- a/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.Designer.cs +++ /dev/null @@ -1,1099 +0,0 @@ -// -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("20230419120719_AddedCloudPanelModels")] - partial class AddedCloudPanelModels - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("CloudPanels"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .HasColumnType("bigint"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Ongoing") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.ToTable("DdosAttacks"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Default") - .HasColumnType("tinyint(1)"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("DockerImages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("SharedDomainId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("SharedDomainId"); - - b.ToTable("Domains"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Allocations") - .HasColumnType("int"); - - b.Property("ConfigFiles") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallDockerImage") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallEntrypoint") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallScript") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Startup") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StartupDetection") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StopCommand") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TagsJson") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Uuid") - .HasColumnType("char(36)"); - - b.HasKey("Id"); - - b.ToTable("Images"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DefaultValue") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("ImageVariables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.MySqlDatabase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("WebSpaceId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WebSpaceId"); - - b.ToTable("Databases"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Markdown") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Title") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("NewsEntries"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Fqdn") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("HttpPort") - .HasColumnType("int"); - - b.Property("MoonlightDaemonPort") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("SftpPort") - .HasColumnType("int"); - - b.Property("Ssl") - .HasColumnType("tinyint(1)"); - - b.Property("Token") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TokenId") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Nodes"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Port") - .HasColumnType("int"); - - b.Property("ServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.HasIndex("ServerId"); - - b.ToTable("NodeAllocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Action") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NotificationClientId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NotificationClientId"); - - b.ToTable("NotificationActions"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("NotificationClients"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("PleskServers"); - }); - - 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.StatisticsData", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Chart") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Value") - .HasColumnType("double"); - - b.HasKey("Id"); - - b.ToTable("Statistics"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("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 unsigned"); - - 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.WebSpace", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CloudPanelId") - .HasColumnType("int"); - - b.Property("Domain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("VHostTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("CloudPanelId"); - - b.HasIndex("OwnerId"); - - b.ToTable("WebSpaces"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("BaseDomain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("FtpLogin") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("FtpPassword") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("PleskId") - .HasColumnType("int"); - - b.Property("PleskServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("PleskServerId"); - - b.ToTable("Websites"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Node"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("DockerImages") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain") - .WithMany() - .HasForeignKey("SharedDomainId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("SharedDomain"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("Variables") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") - .WithMany("Databases") - .HasForeignKey("WebSpaceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WebSpace"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", null) - .WithMany("Allocations") - .HasForeignKey("NodeId"); - - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Allocations") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient") - .WithMany() - .HasForeignKey("NotificationClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("NotificationClient"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", "Image") - .WithMany() - .HasForeignKey("ImageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") - .WithMany() - .HasForeignKey("MainAllocationId"); - - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("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.WebSpace", b => - { - b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") - .WithMany() - .HasForeignKey("CloudPanelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("CloudPanel"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.PleskServer", "PleskServer") - .WithMany() - .HasForeignKey("PleskServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("PleskServer"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Navigation("DockerImages"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Navigation("Allocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.Navigation("Allocations"); - - b.Navigation("Backups"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.Navigation("Databases"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.cs b/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.cs deleted file mode 100644 index 845437af..00000000 --- a/Moonlight/App/Database/Migrations/20230419120719_AddedCloudPanelModels.cs +++ /dev/null @@ -1,121 +0,0 @@ -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Moonlight.App.Database.Migrations -{ - /// - public partial class AddedCloudPanelModels : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "CloudPanels", - 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"), - ApiUrl = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ApiKey = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_CloudPanels", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "WebSpaces", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Domain = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - UserName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Password = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - VHostTemplate = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - OwnerId = table.Column(type: "int", nullable: false), - CloudPanelId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_WebSpaces", x => x.Id); - table.ForeignKey( - name: "FK_WebSpaces_CloudPanels_CloudPanelId", - column: x => x.CloudPanelId, - principalTable: "CloudPanels", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_WebSpaces_Users_OwnerId", - column: x => x.OwnerId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Databases", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - WebSpaceId = table.Column(type: "int", nullable: false), - UserName = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Password = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_Databases", x => x.Id); - table.ForeignKey( - name: "FK_Databases_WebSpaces_WebSpaceId", - column: x => x.WebSpaceId, - principalTable: "WebSpaces", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_Databases_WebSpaceId", - table: "Databases", - column: "WebSpaceId"); - - migrationBuilder.CreateIndex( - name: "IX_WebSpaces_CloudPanelId", - table: "WebSpaces", - column: "CloudPanelId"); - - migrationBuilder.CreateIndex( - name: "IX_WebSpaces_OwnerId", - table: "WebSpaces", - column: "OwnerId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Databases"); - - migrationBuilder.DropTable( - name: "WebSpaces"); - - migrationBuilder.DropTable( - name: "CloudPanels"); - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.Designer.cs b/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.Designer.cs deleted file mode 100644 index dda0a9f9..00000000 --- a/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.Designer.cs +++ /dev/null @@ -1,1103 +0,0 @@ -// -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("20230419125155_AddedHostFieldToCloudPanelModel")] - partial class AddedHostFieldToCloudPanelModel - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Host") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("CloudPanels"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .HasColumnType("bigint"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Ongoing") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.ToTable("DdosAttacks"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Default") - .HasColumnType("tinyint(1)"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("DockerImages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("SharedDomainId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("SharedDomainId"); - - b.ToTable("Domains"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Allocations") - .HasColumnType("int"); - - b.Property("ConfigFiles") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallDockerImage") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallEntrypoint") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallScript") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Startup") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StartupDetection") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StopCommand") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TagsJson") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Uuid") - .HasColumnType("char(36)"); - - b.HasKey("Id"); - - b.ToTable("Images"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DefaultValue") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("ImageVariables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.MySqlDatabase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("WebSpaceId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WebSpaceId"); - - b.ToTable("Databases"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Markdown") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Title") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("NewsEntries"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Fqdn") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("HttpPort") - .HasColumnType("int"); - - b.Property("MoonlightDaemonPort") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("SftpPort") - .HasColumnType("int"); - - b.Property("Ssl") - .HasColumnType("tinyint(1)"); - - b.Property("Token") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TokenId") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Nodes"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Port") - .HasColumnType("int"); - - b.Property("ServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.HasIndex("ServerId"); - - b.ToTable("NodeAllocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Action") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NotificationClientId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NotificationClientId"); - - b.ToTable("NotificationActions"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("NotificationClients"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("PleskServers"); - }); - - 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.StatisticsData", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Chart") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Value") - .HasColumnType("double"); - - b.HasKey("Id"); - - b.ToTable("Statistics"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("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 unsigned"); - - 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.WebSpace", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CloudPanelId") - .HasColumnType("int"); - - b.Property("Domain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("VHostTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("CloudPanelId"); - - b.HasIndex("OwnerId"); - - b.ToTable("WebSpaces"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("BaseDomain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("FtpLogin") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("FtpPassword") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("PleskId") - .HasColumnType("int"); - - b.Property("PleskServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("PleskServerId"); - - b.ToTable("Websites"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Node"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("DockerImages") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain") - .WithMany() - .HasForeignKey("SharedDomainId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("SharedDomain"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("Variables") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") - .WithMany("Databases") - .HasForeignKey("WebSpaceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WebSpace"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", null) - .WithMany("Allocations") - .HasForeignKey("NodeId"); - - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Allocations") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient") - .WithMany() - .HasForeignKey("NotificationClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("NotificationClient"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", "Image") - .WithMany() - .HasForeignKey("ImageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") - .WithMany() - .HasForeignKey("MainAllocationId"); - - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("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.WebSpace", b => - { - b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") - .WithMany() - .HasForeignKey("CloudPanelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("CloudPanel"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.PleskServer", "PleskServer") - .WithMany() - .HasForeignKey("PleskServerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("PleskServer"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Navigation("DockerImages"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Navigation("Allocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.Navigation("Allocations"); - - b.Navigation("Backups"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.Navigation("Databases"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.cs b/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.cs deleted file mode 100644 index a0273c4d..00000000 --- a/Moonlight/App/Database/Migrations/20230419125155_AddedHostFieldToCloudPanelModel.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Moonlight.App.Database.Migrations -{ - /// - public partial class AddedHostFieldToCloudPanelModel : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Host", - table: "CloudPanels", - type: "longtext", - nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Host", - table: "CloudPanels"); - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.Designer.cs b/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.Designer.cs deleted file mode 100644 index 7cea0436..00000000 --- a/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.Designer.cs +++ /dev/null @@ -1,1087 +0,0 @@ -// -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("20230420213846_AddedNewSupportChatModels")] - partial class AddedNewSupportChatModels - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Host") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("CloudPanels"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .HasColumnType("bigint"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Ongoing") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.ToTable("DdosAttacks"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Default") - .HasColumnType("tinyint(1)"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("DockerImages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("SharedDomainId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("SharedDomainId"); - - b.ToTable("Domains"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Allocations") - .HasColumnType("int"); - - b.Property("ConfigFiles") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallDockerImage") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallEntrypoint") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallScript") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Startup") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StartupDetection") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StopCommand") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TagsJson") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Uuid") - .HasColumnType("char(36)"); - - b.HasKey("Id"); - - b.ToTable("Images"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DefaultValue") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("ImageVariables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.MySqlDatabase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("WebSpaceId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WebSpaceId"); - - b.ToTable("Databases"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Markdown") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Title") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("NewsEntries"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Fqdn") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("HttpPort") - .HasColumnType("int"); - - b.Property("MoonlightDaemonPort") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("SftpPort") - .HasColumnType("int"); - - b.Property("Ssl") - .HasColumnType("tinyint(1)"); - - b.Property("Token") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TokenId") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Nodes"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Port") - .HasColumnType("int"); - - b.Property("ServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.HasIndex("ServerId"); - - b.ToTable("NodeAllocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Action") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NotificationClientId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NotificationClientId"); - - b.ToTable("NotificationActions"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("NotificationClients"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.StatisticsData", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Chart") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Value") - .HasColumnType("double"); - - b.HasKey("Id"); - - b.ToTable("Statistics"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("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.SupportChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Answer") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Attachment") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Content") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("IsQuestion") - .HasColumnType("tinyint(1)"); - - b.Property("QuestionType") - .HasColumnType("int"); - - b.Property("RecipientId") - .HasColumnType("int"); - - b.Property("SenderId") - .HasColumnType("int"); - - b.Property("UpdatedAt") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("RecipientId"); - - b.HasIndex("SenderId"); - - b.ToTable("SupportChatMessages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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 unsigned"); - - 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.WebSpace", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CloudPanelId") - .HasColumnType("int"); - - b.Property("Domain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("VHostTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("CloudPanelId"); - - b.HasIndex("OwnerId"); - - b.ToTable("WebSpaces"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Node"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("DockerImages") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain") - .WithMany() - .HasForeignKey("SharedDomainId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("SharedDomain"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("Variables") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") - .WithMany("Databases") - .HasForeignKey("WebSpaceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WebSpace"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", null) - .WithMany("Allocations") - .HasForeignKey("NodeId"); - - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Allocations") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient") - .WithMany() - .HasForeignKey("NotificationClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("NotificationClient"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", "Image") - .WithMany() - .HasForeignKey("ImageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") - .WithMany() - .HasForeignKey("MainAllocationId"); - - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Image"); - - b.Navigation("MainAllocation"); - - b.Navigation("Node"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b => - { - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Backups") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Variables") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") - .WithMany() - .HasForeignKey("RecipientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Sender") - .WithMany() - .HasForeignKey("SenderId"); - - b.Navigation("Recipient"); - - b.Navigation("Sender"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.WebSpace", b => - { - b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") - .WithMany() - .HasForeignKey("CloudPanelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("CloudPanel"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Navigation("DockerImages"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Navigation("Allocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.Navigation("Allocations"); - - b.Navigation("Backups"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.Navigation("Databases"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.cs b/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.cs deleted file mode 100644 index e8160af4..00000000 --- a/Moonlight/App/Database/Migrations/20230420213846_AddedNewSupportChatModels.cs +++ /dev/null @@ -1,138 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Moonlight.App.Database.Migrations -{ - /// - public partial class AddedNewSupportChatModels : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "Websites"); - - migrationBuilder.DropTable( - name: "PleskServers"); - - migrationBuilder.CreateTable( - name: "SupportChatMessages", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - Content = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Attachment = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - SenderId = table.Column(type: "int", nullable: true), - RecipientId = table.Column(type: "int", nullable: false), - IsQuestion = table.Column(type: "tinyint(1)", nullable: false), - QuestionType = table.Column(type: "int", nullable: false), - Answer = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - CreatedAt = table.Column(type: "datetime(6)", nullable: false), - UpdatedAt = table.Column(type: "datetime(6)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SupportChatMessages", x => x.Id); - table.ForeignKey( - name: "FK_SupportChatMessages_Users_RecipientId", - column: x => x.RecipientId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_SupportChatMessages_Users_SenderId", - column: x => x.SenderId, - principalTable: "Users", - principalColumn: "Id"); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_SupportChatMessages_RecipientId", - table: "SupportChatMessages", - column: "RecipientId"); - - migrationBuilder.CreateIndex( - name: "IX_SupportChatMessages_SenderId", - table: "SupportChatMessages", - column: "SenderId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "SupportChatMessages"); - - migrationBuilder.CreateTable( - name: "PleskServers", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - ApiKey = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - ApiUrl = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Name = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4") - }, - constraints: table => - { - table.PrimaryKey("PK_PleskServers", x => x.Id); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateTable( - name: "Websites", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - OwnerId = table.Column(type: "int", nullable: false), - PleskServerId = table.Column(type: "int", nullable: false), - BaseDomain = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - FtpLogin = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - FtpPassword = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - PleskId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Websites", x => x.Id); - table.ForeignKey( - name: "FK_Websites_PleskServers_PleskServerId", - column: x => x.PleskServerId, - principalTable: "PleskServers", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_Websites_Users_OwnerId", - column: x => x.OwnerId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_Websites_OwnerId", - table: "Websites", - column: "OwnerId"); - - migrationBuilder.CreateIndex( - name: "IX_Websites_PleskServerId", - table: "Websites", - column: "PleskServerId"); - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.Designer.cs b/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.Designer.cs deleted file mode 100644 index d34006e9..00000000 --- a/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.Designer.cs +++ /dev/null @@ -1,1028 +0,0 @@ -// -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("20230421143556_RemovedOldSupportChatModel")] - partial class RemovedOldSupportChatModel - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.3") - .HasAnnotation("Relational:MaxIdentifierLength", 64); - - modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Host") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("CloudPanels"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("Data") - .HasColumnType("bigint"); - - b.Property("Ip") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Ongoing") - .HasColumnType("tinyint(1)"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.ToTable("DdosAttacks"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Default") - .HasColumnType("tinyint(1)"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("DockerImages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("SharedDomainId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("OwnerId"); - - b.HasIndex("SharedDomainId"); - - b.ToTable("Domains"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Allocations") - .HasColumnType("int"); - - b.Property("ConfigFiles") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Description") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallDockerImage") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallEntrypoint") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("InstallScript") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Startup") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StartupDetection") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("StopCommand") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TagsJson") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Uuid") - .HasColumnType("char(36)"); - - b.HasKey("Id"); - - b.ToTable("Images"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("DefaultValue") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ImageId") - .HasColumnType("int"); - - b.Property("Key") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("ImageId"); - - b.ToTable("ImageVariables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.MySqlDatabase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("WebSpaceId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WebSpaceId"); - - b.ToTable("Databases"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Markdown") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Title") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("NewsEntries"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Fqdn") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("HttpPort") - .HasColumnType("int"); - - b.Property("MoonlightDaemonPort") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("SftpPort") - .HasColumnType("int"); - - b.Property("Ssl") - .HasColumnType("tinyint(1)"); - - b.Property("Token") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("TokenId") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("Nodes"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("NodeId") - .HasColumnType("int"); - - b.Property("Port") - .HasColumnType("int"); - - b.Property("ServerId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NodeId"); - - b.HasIndex("ServerId"); - - b.ToTable("NodeAllocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Action") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("NotificationClientId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("NotificationClientId"); - - b.ToTable("NotificationActions"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("UserId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("NotificationClients"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.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.StatisticsData", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Chart") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Date") - .HasColumnType("datetime(6)"); - - b.Property("Value") - .HasColumnType("double"); - - b.HasKey("Id"); - - b.ToTable("Statistics"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("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.SupportChatMessage", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Answer") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Attachment") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Content") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("IsQuestion") - .HasColumnType("tinyint(1)"); - - b.Property("QuestionType") - .HasColumnType("int"); - - b.Property("RecipientId") - .HasColumnType("int"); - - b.Property("SenderId") - .HasColumnType("int"); - - b.Property("UpdatedAt") - .HasColumnType("datetime(6)"); - - b.HasKey("Id"); - - b.HasIndex("RecipientId"); - - b.HasIndex("SenderId"); - - b.ToTable("SupportChatMessages"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Address") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Admin") - .HasColumnType("tinyint(1)"); - - b.Property("City") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Country") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("CreatedAt") - .HasColumnType("datetime(6)"); - - b.Property("CurrentSubscriptionId") - .HasColumnType("int"); - - b.Property("DiscordId") - .HasColumnType("bigint unsigned"); - - b.Property("Email") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("FirstName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("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.WebSpace", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("CloudPanelId") - .HasColumnType("int"); - - b.Property("Domain") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("OwnerId") - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("VHostTemplate") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.HasIndex("CloudPanelId"); - - b.HasIndex("OwnerId"); - - b.ToTable("WebSpaces"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Node"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("DockerImages") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.SharedDomain", "SharedDomain") - .WithMany() - .HasForeignKey("SharedDomainId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Owner"); - - b.Navigation("SharedDomain"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", null) - .WithMany("Variables") - .HasForeignKey("ImageId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") - .WithMany("Databases") - .HasForeignKey("WebSpaceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WebSpace"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => - { - b.HasOne("Moonlight.App.Database.Entities.Node", null) - .WithMany("Allocations") - .HasForeignKey("NodeId"); - - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Allocations") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b => - { - b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient") - .WithMany() - .HasForeignKey("NotificationClientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("NotificationClient"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.HasOne("Moonlight.App.Database.Entities.Image", "Image") - .WithMany() - .HasForeignKey("ImageId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation") - .WithMany() - .HasForeignKey("MainAllocationId"); - - b.HasOne("Moonlight.App.Database.Entities.Node", "Node") - .WithMany() - .HasForeignKey("NodeId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Image"); - - b.Navigation("MainAllocation"); - - b.Navigation("Node"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b => - { - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Backups") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b => - { - b.HasOne("Moonlight.App.Database.Entities.Server", null) - .WithMany("Variables") - .HasForeignKey("ServerId"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => - { - b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") - .WithMany() - .HasForeignKey("RecipientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Sender") - .WithMany() - .HasForeignKey("SenderId"); - - b.Navigation("Recipient"); - - b.Navigation("Sender"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => - { - b.HasOne("Moonlight.App.Database.Entities.Subscription", "CurrentSubscription") - .WithMany() - .HasForeignKey("CurrentSubscriptionId"); - - b.Navigation("CurrentSubscription"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") - .WithMany() - .HasForeignKey("CloudPanelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") - .WithMany() - .HasForeignKey("OwnerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("CloudPanel"); - - b.Navigation("Owner"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => - { - b.Navigation("DockerImages"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b => - { - b.Navigation("Allocations"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b => - { - b.Navigation("Allocations"); - - b.Navigation("Backups"); - - b.Navigation("Variables"); - }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.Navigation("Databases"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.cs b/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.cs deleted file mode 100644 index c89742ee..00000000 --- a/Moonlight/App/Database/Migrations/20230421143556_RemovedOldSupportChatModel.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Moonlight.App.Database.Migrations -{ - /// - public partial class RemovedOldSupportChatModel : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "SupportMessages"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "SupportMessages", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn), - RecipientId = table.Column(type: "int", nullable: true), - SenderId = table.Column(type: "int", nullable: true), - Answer = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - CreatedAt = table.Column(type: "datetime(6)", nullable: false), - IsQuestion = table.Column(type: "tinyint(1)", nullable: false), - IsSupport = table.Column(type: "tinyint(1)", nullable: false), - IsSystem = table.Column(type: "tinyint(1)", nullable: false), - Message = table.Column(type: "longtext", nullable: false) - .Annotation("MySql:CharSet", "utf8mb4"), - Type = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_SupportMessages", x => x.Id); - table.ForeignKey( - name: "FK_SupportMessages_Users_RecipientId", - column: x => x.RecipientId, - principalTable: "Users", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_SupportMessages_Users_SenderId", - column: x => x.SenderId, - principalTable: "Users", - principalColumn: "Id"); - }) - .Annotation("MySql:CharSet", "utf8mb4"); - - migrationBuilder.CreateIndex( - name: "IX_SupportMessages_RecipientId", - table: "SupportMessages", - column: "RecipientId"); - - migrationBuilder.CreateIndex( - name: "IX_SupportMessages_SenderId", - table: "SupportMessages", - column: "SenderId"); - } - } -} diff --git a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs index f6f8d75a..7a0da1a7 100644 --- a/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs +++ b/Moonlight/App/Database/Migrations/DataContextModelSnapshot.cs @@ -19,33 +19,6 @@ namespace Moonlight.App.Database.Migrations .HasAnnotation("ProductVersion", "7.0.3") .HasAnnotation("Relational:MaxIdentifierLength", 64); - modelBuilder.Entity("Moonlight.App.Database.Entities.CloudPanel", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("ApiKey") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("ApiUrl") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Host") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Name") - .IsRequired() - .HasColumnType("longtext"); - - b.HasKey("Id"); - - b.ToTable("CloudPanels"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => { b.Property("Id") @@ -308,30 +281,6 @@ namespace Moonlight.App.Database.Migrations b.ToTable("SecurityLog"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("WebSpaceId") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("WebSpaceId"); - - b.ToTable("Databases"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.NewsEntry", b => { b.Property("Id") @@ -453,6 +402,29 @@ namespace Moonlight.App.Database.Migrations b.ToTable("NotificationClients"); }); + modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + b.Property("ApiKey") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("ApiUrl") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("Name") + .IsRequired() + .HasColumnType("longtext"); + + b.HasKey("Id"); + + b.ToTable("PleskServers"); + }); + modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b => { b.Property("Id") @@ -650,7 +622,7 @@ namespace Moonlight.App.Database.Migrations b.ToTable("Subscriptions"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -660,31 +632,30 @@ namespace Moonlight.App.Database.Migrations .IsRequired() .HasColumnType("longtext"); - b.Property("Attachment") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("Content") - .IsRequired() - .HasColumnType("longtext"); - b.Property("CreatedAt") .HasColumnType("datetime(6)"); b.Property("IsQuestion") .HasColumnType("tinyint(1)"); - b.Property("QuestionType") - .HasColumnType("int"); + b.Property("IsSupport") + .HasColumnType("tinyint(1)"); - b.Property("RecipientId") + b.Property("IsSystem") + .HasColumnType("tinyint(1)"); + + b.Property("Message") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("RecipientId") .HasColumnType("int"); b.Property("SenderId") .HasColumnType("int"); - b.Property("UpdatedAt") - .HasColumnType("datetime(6)"); + b.Property("Type") + .HasColumnType("int"); b.HasKey("Id"); @@ -692,7 +663,7 @@ namespace Moonlight.App.Database.Migrations b.HasIndex("SenderId"); - b.ToTable("SupportChatMessages"); + b.ToTable("SupportMessages"); }); modelBuilder.Entity("Moonlight.App.Database.Entities.User", b => @@ -777,41 +748,40 @@ namespace Moonlight.App.Database.Migrations b.ToTable("Users"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => { b.Property("Id") .ValueGeneratedOnAdd() .HasColumnType("int"); - b.Property("CloudPanelId") - .HasColumnType("int"); + b.Property("BaseDomain") + .IsRequired() + .HasColumnType("longtext"); - b.Property("Domain") + b.Property("FtpLogin") + .IsRequired() + .HasColumnType("longtext"); + + b.Property("FtpPassword") .IsRequired() .HasColumnType("longtext"); b.Property("OwnerId") .HasColumnType("int"); - b.Property("Password") - .IsRequired() - .HasColumnType("longtext"); + b.Property("PleskId") + .HasColumnType("int"); - b.Property("UserName") - .IsRequired() - .HasColumnType("longtext"); - - b.Property("VHostTemplate") - .IsRequired() - .HasColumnType("longtext"); + b.Property("PleskServerId") + .HasColumnType("int"); b.HasKey("Id"); - b.HasIndex("CloudPanelId"); - b.HasIndex("OwnerId"); - b.ToTable("WebSpaces"); + b.HasIndex("PleskServerId"); + + b.ToTable("Websites"); }); modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b => @@ -858,17 +828,6 @@ namespace Moonlight.App.Database.Migrations .HasForeignKey("ImageId"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.MySqlDatabase", b => - { - b.HasOne("Moonlight.App.Database.Entities.WebSpace", "WebSpace") - .WithMany("Databases") - .HasForeignKey("WebSpaceId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("WebSpace"); - }); - modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b => { b.HasOne("Moonlight.App.Database.Entities.Node", null) @@ -949,13 +908,11 @@ namespace Moonlight.App.Database.Migrations .HasForeignKey("ServerId"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.SupportChatMessage", b => + modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b => { b.HasOne("Moonlight.App.Database.Entities.User", "Recipient") .WithMany() - .HasForeignKey("RecipientId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + .HasForeignKey("RecipientId"); b.HasOne("Moonlight.App.Database.Entities.User", "Sender") .WithMany() @@ -975,23 +932,23 @@ namespace Moonlight.App.Database.Migrations b.Navigation("CurrentSubscription"); }); - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => + modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b => { - b.HasOne("Moonlight.App.Database.Entities.CloudPanel", "CloudPanel") - .WithMany() - .HasForeignKey("CloudPanelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - b.HasOne("Moonlight.App.Database.Entities.User", "Owner") .WithMany() .HasForeignKey("OwnerId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.Navigation("CloudPanel"); + b.HasOne("Moonlight.App.Database.Entities.PleskServer", "PleskServer") + .WithMany() + .HasForeignKey("PleskServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); b.Navigation("Owner"); + + b.Navigation("PleskServer"); }); modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b => @@ -1014,11 +971,6 @@ namespace Moonlight.App.Database.Migrations b.Navigation("Variables"); }); - - modelBuilder.Entity("Moonlight.App.Database.Entities.WebSpace", b => - { - b.Navigation("Databases"); - }); #pragma warning restore 612, 618 } } diff --git a/Moonlight/App/Events/EventSystem.cs b/Moonlight/App/Events/EventSystem.cs deleted file mode 100644 index 1d0f1d40..00000000 --- a/Moonlight/App/Events/EventSystem.cs +++ /dev/null @@ -1,142 +0,0 @@ -using System.Diagnostics; -using Logging.Net; - -namespace Moonlight.App.Events; - -public class EventSystem -{ - private Dictionary Storage = new(); - private List Subscribers = new(); - - private readonly bool Debug = false; - private readonly bool DisableWarning = false; - private readonly TimeSpan TookToLongTime = TimeSpan.FromSeconds(1); - - public Task On(string id, object handle, Func action) - { - if(Debug) - Logger.Debug($"{handle} subscribed to '{id}'"); - - lock (Subscribers) - { - if (!Subscribers.Any(x => x.Id == id && x.Handle == handle)) - { - Subscribers.Add(new () - { - Action = action, - Handle = handle, - Id = id - }); - } - } - - return Task.CompletedTask; - } - - public Task Emit(string id, object? d = null) - { - int hashCode = -1; - - if (d != null) - { - hashCode = d.GetHashCode(); - Storage.TryAdd(hashCode, d); - } - - Subscriber[] subscribers; - - lock (Subscribers) - { - subscribers = Subscribers - .Where(x => x.Id == id) - .ToArray(); - } - - var tasks = new List(); - - foreach (var subscriber in subscribers) - { - tasks.Add(new Task(() => - { - int storageId = hashCode + 0; // To create a copy of the hash code - - object? data = null; - - if (storageId != -1) - { - if (Storage.TryGetValue(storageId, out var value)) - { - data = value; - } - else - { - Logger.Warn($"Object with the hash '{storageId}' was not present in the storage"); - return; - } - } - - var stopWatch = new Stopwatch(); - stopWatch.Start(); - - var del = (Delegate)subscriber.Action; - - try - { - ((Task)del.DynamicInvoke(data)!).Wait(); - } - catch (Exception e) - { - Logger.Warn($"Error emitting '{subscriber.Id} on {subscriber.Handle}'"); - Logger.Warn(e); - } - - stopWatch.Stop(); - - if (!DisableWarning) - { - if (stopWatch.Elapsed.TotalMilliseconds > TookToLongTime.TotalMilliseconds) - { - Logger.Warn($"Subscriber {subscriber.Handle} for event '{subscriber.Id}' took long to process. {stopWatch.Elapsed.TotalMilliseconds}ms"); - } - } - - if (Debug) - { - Logger.Debug($"Subscriber {subscriber.Handle} for event '{subscriber.Id}' took {stopWatch.Elapsed.TotalMilliseconds}ms"); - } - })); - } - - foreach (var task in tasks) - { - task.Start(); - } - - Task.Run(() => - { - Task.WaitAll(tasks.ToArray()); - Storage.Remove(hashCode); - - if(Debug) - Logger.Debug($"Completed all event tasks for '{id}' and removed object from storage"); - }); - - if(Debug) - Logger.Debug($"Completed event emit '{id}'"); - - return Task.CompletedTask; - } - - public Task Off(string id, object handle) - { - if(Debug) - Logger.Debug($"{handle} unsubscribed to '{id}'"); - - lock (Subscribers) - { - Subscribers.RemoveAll(x => x.Id == id && x.Handle == handle); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/Moonlight/App/Events/Subscriber.cs b/Moonlight/App/Events/Subscriber.cs deleted file mode 100644 index 0d64012c..00000000 --- a/Moonlight/App/Events/Subscriber.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Moonlight.App.Events; - -public class Subscriber -{ - public string Id { get; set; } - public object Action { get; set; } - public object Handle { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Exceptions/DaemonException.cs b/Moonlight/App/Exceptions/DaemonException.cs index 845c908f..05070d4a 100644 --- a/Moonlight/App/Exceptions/DaemonException.cs +++ b/Moonlight/App/Exceptions/DaemonException.cs @@ -5,7 +5,7 @@ namespace Moonlight.App.Exceptions; [Serializable] public class DaemonException : Exception { - public int StatusCode { get; set; } + public int StatusCode { private get; set; } public DaemonException() { diff --git a/Moonlight/App/Exceptions/PleskException.cs b/Moonlight/App/Exceptions/PleskException.cs index 5ad8aa82..e29676f0 100644 --- a/Moonlight/App/Exceptions/PleskException.cs +++ b/Moonlight/App/Exceptions/PleskException.cs @@ -5,7 +5,7 @@ namespace Moonlight.App.Exceptions; [Serializable] public class PleskException : Exception { - public int StatusCode { get; set; } + public int StatusCode { private get; set; } public PleskException() { diff --git a/Moonlight/App/Exceptions/WingsException.cs b/Moonlight/App/Exceptions/WingsException.cs index 92b83b3f..a5dc9310 100644 --- a/Moonlight/App/Exceptions/WingsException.cs +++ b/Moonlight/App/Exceptions/WingsException.cs @@ -5,7 +5,7 @@ namespace Moonlight.App.Exceptions; [Serializable] public class WingsException : Exception { - public int StatusCode { get; set; } + public int StatusCode { private get; set; } public WingsException() { diff --git a/Moonlight/App/Extensions/DbSetExtensions.cs b/Moonlight/App/Extensions/DbSetExtensions.cs deleted file mode 100644 index 7f06c81c..00000000 --- a/Moonlight/App/Extensions/DbSetExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.EntityFrameworkCore; - -namespace Moonlight.App.Extensions; - -public static class DbSetExtensions -{ - public static T Random(this DbSet repo) where T : class - { - Random rand = new Random(); - int toSkip = rand.Next(0, repo.Count()); - - return repo.Skip(toSkip).Take(1).First(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Helpers/Files/SftpFileAccess.cs b/Moonlight/App/Helpers/Files/SftpFileAccess.cs deleted file mode 100644 index f79b4388..00000000 --- a/Moonlight/App/Helpers/Files/SftpFileAccess.cs +++ /dev/null @@ -1,206 +0,0 @@ -using Logging.Net; -using Renci.SshNet; -using ConnectionInfo = Renci.SshNet.ConnectionInfo; - -namespace Moonlight.App.Helpers.Files; - -public class SftpFileAccess : FileAccess -{ - private readonly string SftpHost; - private readonly string SftpUser; - private readonly string SftpPassword; - private readonly int SftpPort; - private readonly bool ForceUserDir; - - private readonly SftpClient Client; - - private string InternalPath - { - get - { - if (ForceUserDir) - return $"/home/{SftpUser}{CurrentPath}"; - - return InternalPath; - } - } - - public SftpFileAccess(string sftpHost, string sftpUser, string sftpPassword, int sftpPort, - bool forceUserDir = false) - { - SftpHost = sftpHost; - SftpUser = sftpUser; - SftpPassword = sftpPassword; - SftpPort = sftpPort; - ForceUserDir = forceUserDir; - - Client = new( - new ConnectionInfo( - SftpHost, - SftpPort, - SftpUser, - new PasswordAuthenticationMethod( - SftpUser, - SftpPassword - ) - ) - ); - } - - private void EnsureConnect() - { - if (!Client.IsConnected) - Client.Connect(); - } - - - public override Task Ls() - { - EnsureConnect(); - - var x = new List(); - - foreach (var file in Client.ListDirectory(InternalPath)) - { - if (file.Name != "." && file.Name != "..") - { - x.Add(new() - { - Name = file.Name, - Size = file.Attributes.Size, - IsFile = !file.IsDirectory - }); - } - } - - return Task.FromResult(x.ToArray()); - } - - public override Task Cd(string dir) - { - var x = Path.Combine(CurrentPath, dir).Replace("\\", "/") + "/"; - x = x.Replace("//", "/"); - CurrentPath = x; - - return Task.CompletedTask; - } - - public override Task Up() - { - CurrentPath = Path.GetFullPath(Path.Combine(CurrentPath, "..")).Replace("\\", "/").Replace("C:", ""); - return Task.CompletedTask; - } - - public override Task SetDir(string dir) - { - CurrentPath = dir; - return Task.CompletedTask; - } - - public override Task Read(FileData fileData) - { - EnsureConnect(); - - var textStream = Client.Open(InternalPath.TrimEnd('/') + "/" + fileData.Name, FileMode.Open); - - if (textStream == null) - return Task.FromResult(""); - - var streamReader = new StreamReader(textStream); - - var text = streamReader.ReadToEnd(); - - streamReader.Close(); - textStream.Close(); - - return Task.FromResult(text); - } - - public override Task Write(FileData fileData, string content) - { - EnsureConnect(); - - var textStream = Client.Open(InternalPath.TrimEnd('/') + "/" + fileData.Name, FileMode.Create); - - var streamWriter = new StreamWriter(textStream); - streamWriter.Write(content); - - streamWriter.Flush(); - textStream.Flush(); - - streamWriter.Close(); - textStream.Close(); - - return Task.CompletedTask; - } - - public override async Task Upload(string name, Stream stream, Action? progressUpdated = null) - { - var dataStream = new SyncStreamAdapter(stream); - - await Task.Factory.FromAsync((x, _) => Client.BeginUploadFile(dataStream, InternalPath + name, x, null, u => - { - progressUpdated?.Invoke((int)((long)u / stream.Length)); - }), - Client.EndUploadFile, null); - } - - public override Task MkDir(string name) - { - Client.CreateDirectory(InternalPath + name); - - return Task.CompletedTask; - } - - public override Task Pwd() - { - return Task.FromResult(CurrentPath); - } - - public override Task DownloadUrl(FileData fileData) - { - throw new NotImplementedException(); - } - - public override Task DownloadStream(FileData fileData) - { - var stream = new MemoryStream(100 * 1024 * 1024); - Client.DownloadFile(InternalPath + fileData.Name, stream); - - return Task.FromResult(stream); - } - - public override Task Delete(FileData fileData) - { - Client.Delete(InternalPath + fileData.Name); - - return Task.CompletedTask; - } - - public override Task Move(FileData fileData, string newPath) - { - Client.RenameFile(InternalPath + fileData.Name, InternalPath + newPath); - - return Task.CompletedTask; - } - - public override Task Compress(params FileData[] files) - { - throw new NotImplementedException(); - } - - public override Task Decompress(FileData fileData) - { - throw new NotImplementedException(); - } - - public override Task GetLaunchUrl() - { - return Task.FromResult($"sftp://{SftpUser}@{SftpHost}:{SftpPort}"); - } - - public override object Clone() - { - return new SftpFileAccess(SftpHost, SftpUser, SftpPassword, SftpPort, ForceUserDir); - } -} \ No newline at end of file diff --git a/Moonlight/App/Helpers/ParseHelper.cs b/Moonlight/App/Helpers/ParseHelper.cs index b3074c1c..ecc983dd 100644 --- a/Moonlight/App/Helpers/ParseHelper.cs +++ b/Moonlight/App/Helpers/ParseHelper.cs @@ -1,23 +1,15 @@ -using Logging.Net; - -namespace Moonlight.App.Helpers; +namespace Moonlight.App.Helpers; public static class ParseHelper { public static int MinecraftToInt(string raw) { - var versionWithoutPre = raw.Split("_")[0]; - versionWithoutPre = versionWithoutPre.Split("-")[0]; - - // Fuck you 1.7.10 ;) - versionWithoutPre = versionWithoutPre.Replace("1.7.10", "1.7"); + var versionWithoutPre = raw.Split("-")[0]; if (versionWithoutPre.Count(x => x == "."[0]) == 1) versionWithoutPre += ".0"; - var x = versionWithoutPre.Replace(".", ""); - - return int.Parse(x); + return int.Parse(versionWithoutPre.Replace(".", "")); } public static string FirstPartStartingWithNumber(string raw) @@ -37,61 +29,4 @@ public static class ParseHelper return res; } - - public static string GetHighestVersion(string[] versions) - { - // Initialize the highest version to the first version in the array - string highestVersion = versions[0]; - - // Loop through the remaining versions in the array - for (int i = 1; i < versions.Length; i++) - { - // Compare the current version to the highest version - if (CompareVersions(versions[i], highestVersion) > 0) - { - // If the current version is higher, update the highest version - highestVersion = versions[i]; - } - } - - return highestVersion; - } - - public static int CompareVersions(string version1, string version2) - { - // Split the versions into their component parts - string[] version1Parts = version1.Split('.'); - string[] version2Parts = version2.Split('.'); - - // Compare each component part in turn - for (int i = 0; i < version1Parts.Length && i < version2Parts.Length; i++) - { - int part1 = int.Parse(version1Parts[i]); - int part2 = int.Parse(version2Parts[i]); - - if (part1 < part2) - { - return -1; - } - else if (part1 > part2) - { - return 1; - } - } - - // If we get here, the versions are equal up to the length of the shorter one. - // If one version has more parts than the other, the longer one is considered higher. - if (version1Parts.Length < version2Parts.Length) - { - return -1; - } - else if (version1Parts.Length > version2Parts.Length) - { - return 1; - } - else - { - return 0; - } - } } \ No newline at end of file diff --git a/Moonlight/App/Helpers/PleskApiHelper.cs b/Moonlight/App/Helpers/PleskApiHelper.cs new file mode 100644 index 00000000..87ea9878 --- /dev/null +++ b/Moonlight/App/Helpers/PleskApiHelper.cs @@ -0,0 +1,220 @@ +using System.Text; +using Moonlight.App.Database.Entities; +using Moonlight.App.Exceptions; +using Newtonsoft.Json; +using RestSharp; + +namespace Moonlight.App.Helpers; + +public class PleskApiHelper +{ + private readonly RestClient Client; + + public PleskApiHelper() + { + Client = new(); + } + + public async Task Get(PleskServer server, string resource) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Get; + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + + return JsonConvert.DeserializeObject(response.Content!)!; + } + + public async Task GetRaw(PleskServer server, string resource) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Get; + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + + return response.Content!; + } + + public async Task Post(PleskServer server, string resource, object? body) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Post; + + request.AddParameter("text/plain", + JsonConvert.SerializeObject(body), + ParameterType.RequestBody + ); + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + + return JsonConvert.DeserializeObject(response.Content!)!; + } + + public async Task Post(PleskServer server, string resource, object? body) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Post; + + if(body != null) + request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + } + + public async Task PostRaw(PleskServer server, string resource, object body) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Post; + + request.AddParameter("text/plain", body, ParameterType.RequestBody); + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + } + + public async Task Delete(PleskServer server, string resource, object? body) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Delete; + + if(body != null) + request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + } + + public async Task Put(PleskServer server, string resource, object? body) + { + var request = CreateRequest(server, resource); + + request.Method = Method.Put; + + request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody); + + var response = await Client.ExecuteAsync(request); + + if (!response.IsSuccessful) + { + if (response.StatusCode != 0) + { + throw new PleskException( + $"An error occured: ({response.StatusCode}) {response.Content}", + (int)response.StatusCode + ); + } + else + { + throw new Exception($"An internal error occured: {response.ErrorMessage}"); + } + } + } + + private RestRequest CreateRequest(PleskServer pleskServer, string resource) + { + var url = $"{pleskServer.ApiUrl}/" + resource; + + var request = new RestRequest(url); + var ba = Convert.ToBase64String(Encoding.UTF8.GetBytes(pleskServer.ApiKey)); + + request.AddHeader("Content-Type", "application/json"); + request.AddHeader("Accept", "application/json"); + request.AddHeader("Authorization", "Basic " + ba); + + return request; + } +} \ No newline at end of file diff --git a/Moonlight/App/Helpers/SyncStreamAdapter.cs b/Moonlight/App/Helpers/SyncStreamAdapter.cs deleted file mode 100644 index 304b3f12..00000000 --- a/Moonlight/App/Helpers/SyncStreamAdapter.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace Moonlight.App.Helpers; - -public class SyncStreamAdapter : Stream -{ - private readonly Stream _stream; - - public SyncStreamAdapter(Stream stream) - { - _stream = stream ?? throw new ArgumentNullException(nameof(stream)); - } - - public override bool CanRead => _stream.CanRead; - public override bool CanSeek => _stream.CanSeek; - public override bool CanWrite => _stream.CanWrite; - public override long Length => _stream.Length; - - public override long Position - { - get => _stream.Position; - set => _stream.Position = value; - } - - public override void Flush() - { - _stream.Flush(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - var task = Task.Run(() => _stream.ReadAsync(buffer, offset, count)); - return task.GetAwaiter().GetResult(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - return _stream.Seek(offset, origin); - } - - public override void SetLength(long value) - { - _stream.SetLength(value); - } - - public override void Write(byte[] buffer, int offset, int count) - { - var task = Task.Run(() => _stream.WriteAsync(buffer, offset, count)); - task.GetAwaiter().GetResult(); - } - - protected override void Dispose(bool disposing) - { - if (disposing) - { - _stream?.Dispose(); - } - base.Dispose(disposing); - } -} \ No newline at end of file diff --git a/Moonlight/App/Http/Controllers/Api/Moonlight/OAuth2Controller.cs b/Moonlight/App/Http/Controllers/Api/Moonlight/OAuth2Controller.cs index aa6c9fe5..3d1abb4c 100644 --- a/Moonlight/App/Http/Controllers/Api/Moonlight/OAuth2Controller.cs +++ b/Moonlight/App/Http/Controllers/Api/Moonlight/OAuth2Controller.cs @@ -18,19 +18,17 @@ public class OAuth2Controller : Controller private readonly DiscordOAuth2Service DiscordOAuth2Service; private readonly UserRepository UserRepository; private readonly UserService UserService; - private readonly DateTimeService DateTimeService; public OAuth2Controller( GoogleOAuth2Service googleOAuth2Service, UserRepository userRepository, UserService userService, - DiscordOAuth2Service discordOAuth2Service, DateTimeService dateTimeService) + DiscordOAuth2Service discordOAuth2Service) { GoogleOAuth2Service = googleOAuth2Service; UserRepository = userRepository; UserService = userService; DiscordOAuth2Service = discordOAuth2Service; - DateTimeService = dateTimeService; } [HttpGet("google")] @@ -65,7 +63,7 @@ public class OAuth2Controller : Controller Response.Cookies.Append("token", token, new () { - Expires = new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10)) + Expires = new DateTimeOffset(DateTime.UtcNow.AddDays(10)) }); return Redirect("/"); @@ -123,7 +121,7 @@ public class OAuth2Controller : Controller Response.Cookies.Append("token", token, new () { - Expires = new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10)) + Expires = new DateTimeOffset(DateTime.UtcNow.AddDays(10)) }); return Redirect("/"); diff --git a/Moonlight/App/Http/Controllers/Api/Remote/BackupController.cs b/Moonlight/App/Http/Controllers/Api/Remote/BackupController.cs index 63bbe28b..46978228 100644 --- a/Moonlight/App/Http/Controllers/Api/Remote/BackupController.cs +++ b/Moonlight/App/Http/Controllers/Api/Remote/BackupController.cs @@ -1,5 +1,4 @@ using Microsoft.AspNetCore.Mvc; -using Moonlight.App.Events; using Moonlight.App.Http.Requests.Wings; using Moonlight.App.Repositories; using Moonlight.App.Repositories.Servers; @@ -12,17 +11,17 @@ namespace Moonlight.App.Http.Controllers.Api.Remote; public class BackupController : Controller { private readonly ServerBackupRepository ServerBackupRepository; - private readonly EventSystem Event; + private readonly MessageService MessageService; private readonly NodeRepository NodeRepository; public BackupController( ServerBackupRepository serverBackupRepository, NodeRepository nodeRepository, - EventSystem eventSystem) + MessageService messageService) { ServerBackupRepository = serverBackupRepository; NodeRepository = nodeRepository; - Event = eventSystem; + MessageService = messageService; } [HttpGet("{uuid}")] @@ -58,11 +57,11 @@ public class BackupController : Controller ServerBackupRepository.Update(backup); - await Event.Emit($"wings.backups.create", backup); + await MessageService.Emit($"wings.backups.create", backup); } else { - await Event.Emit($"wings.backups.createFailed", backup); + await MessageService.Emit($"wings.backups.createfailed", backup); ServerBackupRepository.Delete(backup); } @@ -89,7 +88,7 @@ public class BackupController : Controller if (backup == null) return NotFound(); - await Event.Emit($"wings.backups.restore", backup); + await MessageService.Emit($"wings.backups.restore", backup); return NoContent(); } diff --git a/Moonlight/App/Http/Controllers/Api/Remote/DdosController.cs b/Moonlight/App/Http/Controllers/Api/Remote/DdosController.cs index e6a0dbc9..b1cf361c 100644 --- a/Moonlight/App/Http/Controllers/Api/Remote/DdosController.cs +++ b/Moonlight/App/Http/Controllers/Api/Remote/DdosController.cs @@ -1,7 +1,6 @@ using Logging.Net; using Microsoft.AspNetCore.Mvc; using Moonlight.App.Database.Entities; -using Moonlight.App.Events; using Moonlight.App.Http.Requests.Daemon; using Moonlight.App.Repositories; using Moonlight.App.Services; @@ -13,13 +12,13 @@ namespace Moonlight.App.Http.Controllers.Api.Remote; public class DdosController : Controller { private readonly NodeRepository NodeRepository; - private readonly EventSystem Event; + private readonly MessageService MessageService; private readonly DdosAttackRepository DdosAttackRepository; - public DdosController(NodeRepository nodeRepository, EventSystem eventSystem, DdosAttackRepository ddosAttackRepository) + public DdosController(NodeRepository nodeRepository, MessageService messageService, DdosAttackRepository ddosAttackRepository) { NodeRepository = nodeRepository; - Event = eventSystem; + MessageService = messageService; DdosAttackRepository = ddosAttackRepository; } @@ -48,7 +47,7 @@ public class DdosController : Controller ddosAttack = DdosAttackRepository.Add(ddosAttack); - await Event.Emit("node.ddos", ddosAttack); + await MessageService.Emit("node.ddos", ddosAttack); return Ok(); } diff --git a/Moonlight/App/Http/Controllers/Api/Remote/ServersController.cs b/Moonlight/App/Http/Controllers/Api/Remote/ServersController.cs index 08f4ddc0..1136bcae 100644 --- a/Moonlight/App/Http/Controllers/Api/Remote/ServersController.cs +++ b/Moonlight/App/Http/Controllers/Api/Remote/ServersController.cs @@ -1,6 +1,5 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Moonlight.App.Events; using Moonlight.App.Helpers; using Moonlight.App.Http.Resources.Wings; using Moonlight.App.Repositories; @@ -16,18 +15,18 @@ public class ServersController : Controller private readonly WingsServerConverter Converter; private readonly ServerRepository ServerRepository; private readonly NodeRepository NodeRepository; - private readonly EventSystem Event; + private readonly MessageService MessageService; public ServersController( WingsServerConverter converter, ServerRepository serverRepository, NodeRepository nodeRepository, - EventSystem eventSystem) + MessageService messageService) { Converter = converter; ServerRepository = serverRepository; NodeRepository = nodeRepository; - Event = eventSystem; + MessageService = messageService; } [HttpGet] @@ -69,7 +68,7 @@ public class ServersController : Controller totalPages = slice.Length - 1; } - await Event.Emit($"wings.{node.Id}.serverList", node); + await MessageService.Emit($"wings.{node.Id}.serverlist", node); //Logger.Debug($"[BRIDGE] Node '{node.Name}' is requesting server list page {page} with {perPage} items per page"); @@ -98,7 +97,7 @@ public class ServersController : Controller if (token != node.Token) return Unauthorized(); - await Event.Emit($"wings.{node.Id}.stateReset", node); + await MessageService.Emit($"wings.{node.Id}.statereset", node); foreach (var server in ServerRepository .Get() @@ -137,7 +136,7 @@ public class ServersController : Controller if (server == null) return NotFound(); - await Event.Emit($"wings.{node.Id}.serverFetch", server); + await MessageService.Emit($"wings.{node.Id}.serverfetch", server); try //TODO: Remove { @@ -170,7 +169,7 @@ public class ServersController : Controller if (server == null) return NotFound(); - await Event.Emit($"wings.{node.Id}.serverInstallFetch", server); + await MessageService.Emit($"wings.{node.Id}.serverinstallfetch", server); return new WingsServerInstall() { @@ -203,8 +202,8 @@ public class ServersController : Controller server.Installing = false; ServerRepository.Update(server); - await Event.Emit($"wings.{node.Id}.serverInstallComplete", server); - await Event.Emit($"server.{server.Uuid}.installComplete", server); + await MessageService.Emit($"wings.{node.Id}.serverinstallcomplete", server); + await MessageService.Emit($"server.{server.Uuid}.installcomplete", server); return Ok(); } diff --git a/Moonlight/App/MessageSystem/MessageSender.cs b/Moonlight/App/MessageSystem/MessageSender.cs new file mode 100644 index 00000000..a564eb58 --- /dev/null +++ b/Moonlight/App/MessageSystem/MessageSender.cs @@ -0,0 +1,83 @@ +using System.Diagnostics; +using Logging.Net; + +namespace Moonlight.App.MessageSystem; + +public class MessageSender +{ + private readonly List Subscribers; + + public bool Debug { get; set; } + public TimeSpan TookToLongTime { get; set; } = TimeSpan.FromSeconds(1); + + public MessageSender() + { + Subscribers = new(); + } + + public void Subscribe(string name, object bind, Func method) + { + lock (Subscribers) + { + Subscribers.Add(new () + { + Name = name, + Action = method, + Type = typeof(T), + Bind = bind + }); + } + + if(Debug) + Logger.Debug($"{bind} subscribed to '{name}'"); + } + + public void Unsubscribe(string name, object bind) + { + lock (Subscribers) + { + Subscribers.RemoveAll(x => x.Bind == bind); + } + + if(Debug) + Logger.Debug($"{bind} unsubscribed from '{name}'"); + } + + public Task Emit(string name, object? value, bool disableWarning = false) + { + lock (Subscribers) + { + foreach (var subscriber in Subscribers) + { + if (subscriber.Name == name) + { + var stopWatch = new Stopwatch(); + stopWatch.Start(); + + var del = (Delegate)subscriber.Action; + + ((Task)del.DynamicInvoke(value)!).Wait(); + + stopWatch.Stop(); + + if (!disableWarning) + { + if (stopWatch.Elapsed.TotalMilliseconds > TookToLongTime.TotalMilliseconds) + { + Logger.Warn( + $"Subscriber {subscriber.Type.Name} for event '{name}' took long to process. {stopWatch.Elapsed.TotalMilliseconds}ms"); + } + } + + if (Debug) + { + Logger.Debug( + $"Subscriber {subscriber.Type.Name} for event '{name}' took {stopWatch.Elapsed.TotalMilliseconds}ms"); + } + } + } + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/Moonlight/App/MessageSystem/MessageSubscriber.cs b/Moonlight/App/MessageSystem/MessageSubscriber.cs new file mode 100644 index 00000000..b435d81f --- /dev/null +++ b/Moonlight/App/MessageSystem/MessageSubscriber.cs @@ -0,0 +1,9 @@ +namespace Moonlight.App.MessageSystem; + +public class MessageSubscriber +{ + public string Name { get; set; } + public object Action { get; set; } + public Type Type { get; set; } + public object Bind { get; set; } +} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/CloudPanelDataModel.cs b/Moonlight/App/Models/Forms/CloudPanelDataModel.cs deleted file mode 100644 index d08e9461..00000000 --- a/Moonlight/App/Models/Forms/CloudPanelDataModel.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.ComponentModel.DataAnnotations; - -namespace Moonlight.App.Models.Forms; - -public class CloudPanelDataModel -{ - [Required(ErrorMessage = "You have to enter a name")] - [MaxLength(32, ErrorMessage = "The name should not be longer than 32 characters")] - public string Name { get; set; } - - [Required(ErrorMessage = "You need to specify the host")] - public string Host { get; set; } - - [Required(ErrorMessage = "You need to enter an api url")] - public string ApiUrl { get; set; } - - [Required(ErrorMessage = "You need to enter an api key")] - public string ApiKey { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Models/Forms/DomainOrderDataModel.cs b/Moonlight/App/Models/Forms/DomainOrderDataModel.cs index b3b8a93f..c49dd8e3 100644 --- a/Moonlight/App/Models/Forms/DomainOrderDataModel.cs +++ b/Moonlight/App/Models/Forms/DomainOrderDataModel.cs @@ -7,7 +7,7 @@ public class DomainOrderDataModel { [Required(ErrorMessage = "You need to specify a name")] [MaxLength(32, ErrorMessage = "The max lenght for the name is 32 characters")] - [RegularExpression(@"^[a-z0-9]+$", ErrorMessage = "The name should only consist of lower case characters or numbers")] + [RegularExpression(@"^[a-z]+$", ErrorMessage = "The name should only consist of lower case characters")] public string Name { get; set; } = ""; [Required(ErrorMessage = "You need to specify a shared domain")] diff --git a/Moonlight/App/Models/Forms/ServerEditDataModel.cs b/Moonlight/App/Models/Forms/ServerEditDataModel.cs deleted file mode 100644 index 22adcbaf..00000000 --- a/Moonlight/App/Models/Forms/ServerEditDataModel.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.ComponentModel.DataAnnotations; -using Moonlight.App.Database.Entities; - -namespace Moonlight.App.Models.Forms; - -public class ServerEditDataModel -{ - [Required(ErrorMessage = "You need to enter a name")] - [MaxLength(32, ErrorMessage = "The name cannot be longer that 32 characters")] - public string Name { get; set; } - - [Required(ErrorMessage = "You need to specify a user")] - public User Owner { get; set; } - - [Required(ErrorMessage = "You need to specify the cpu cores")] - public int Cpu { get; set; } - - [Required(ErrorMessage = "You need to specify the memory")] - public long Memory { get; set; } - - [Required(ErrorMessage = "You need to specify the disk")] - public long Disk { get; set; } - - public string OverrideStartup { get; set; } - - public int DockerImageIndex { get; set; } - - public bool IsCleanupException { get; set; } -} \ No newline at end of file diff --git a/Moonlight/App/Repositories/NodeAllocationRepository.cs b/Moonlight/App/Repositories/NodeAllocationRepository.cs deleted file mode 100644 index 529c9fbc..00000000 --- a/Moonlight/App/Repositories/NodeAllocationRepository.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities; - -namespace Moonlight.App.Repositories; - -public class NodeAllocationRepository : IDisposable -{ - // This repository is ONLY for the server creation service, so allocations can be found - // using raw sql. DO NOT use this in any other component - - private readonly DataContext DataContext; - - public NodeAllocationRepository(DataContext dataContext) - { - DataContext = dataContext; - } - - public DbSet Get() - { - return DataContext.NodeAllocations; - } - - public void Dispose() - { - DataContext.Dispose(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Repositories/PleskServerRepository.cs b/Moonlight/App/Repositories/PleskServerRepository.cs new file mode 100644 index 00000000..53742635 --- /dev/null +++ b/Moonlight/App/Repositories/PleskServerRepository.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Repositories; + +public class PleskServerRepository : IDisposable +{ + private readonly DataContext DataContext; + + public PleskServerRepository(DataContext dataContext) + { + DataContext = dataContext; + } + + public DbSet Get() + { + return DataContext.PleskServers; + } + + public PleskServer Add(PleskServer pleskServer) + { + var x = DataContext.PleskServers.Add(pleskServer); + DataContext.SaveChanges(); + return x.Entity; + } + + public void Update(PleskServer pleskServer) + { + DataContext.PleskServers.Update(pleskServer); + DataContext.SaveChanges(); + } + + public void Delete(PleskServer pleskServer) + { + DataContext.PleskServers.Remove(pleskServer); + DataContext.SaveChanges(); + } + + public void Dispose() + { + DataContext.Dispose(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Repositories/Repository.cs b/Moonlight/App/Repositories/Repository.cs deleted file mode 100644 index 1c46f6ab..00000000 --- a/Moonlight/App/Repositories/Repository.cs +++ /dev/null @@ -1,40 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database; - -namespace Moonlight.App.Repositories; - -public class Repository where TEntity : class -{ - private readonly DataContext DataContext; - private readonly DbSet DbSet; - - public Repository(DataContext dbContext) - { - DataContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); - DbSet = DataContext.Set(); - } - - public DbSet Get() - { - return DbSet; - } - - public TEntity Add(TEntity entity) - { - var x = DbSet.Add(entity); - DataContext.SaveChanges(); - return x.Entity; - } - - public void Update(TEntity entity) - { - DbSet.Update(entity); - DataContext.SaveChanges(); - } - - public void Delete(TEntity entity) - { - DbSet.Remove(entity); - DataContext.SaveChanges(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Repositories/StatisticsRepository.cs b/Moonlight/App/Repositories/StatisticsRepository.cs index 69630abe..f33751b7 100644 --- a/Moonlight/App/Repositories/StatisticsRepository.cs +++ b/Moonlight/App/Repositories/StatisticsRepository.cs @@ -1,19 +1,16 @@ using Microsoft.EntityFrameworkCore; using Moonlight.App.Database; using Moonlight.App.Database.Entities; -using Moonlight.App.Services; namespace Moonlight.App.Repositories; public class StatisticsRepository : IDisposable { private readonly DataContext DataContext; - private readonly DateTimeService DateTimeService; - public StatisticsRepository(DataContext dataContext, DateTimeService dateTimeService) + public StatisticsRepository(DataContext dataContext) { DataContext = dataContext; - DateTimeService = dateTimeService; } public DbSet Get() @@ -30,7 +27,7 @@ public class StatisticsRepository : IDisposable public StatisticsData Add(string chart, double value) { - return Add(new StatisticsData() {Chart = chart, Value = value, Date = DateTimeService.GetCurrent()}); + return Add(new StatisticsData() {Chart = chart, Value = value, Date = DateTime.Now}); } public void Dispose() diff --git a/Moonlight/App/Repositories/SupportMessageRepository.cs b/Moonlight/App/Repositories/SupportMessageRepository.cs new file mode 100644 index 00000000..1f6ec2e7 --- /dev/null +++ b/Moonlight/App/Repositories/SupportMessageRepository.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Repositories; + +public class SupportMessageRepository : IDisposable +{ + private readonly DataContext DataContext; + + public SupportMessageRepository(DataContext dataContext) + { + DataContext = dataContext; + } + + public DbSet Get() + { + return DataContext.SupportMessages; + } + + public SupportMessage Add(SupportMessage message) + { + var x = DataContext.SupportMessages.Add(message); + DataContext.SaveChanges(); + return x.Entity; + } + + public void Update(SupportMessage message) + { + DataContext.SupportMessages.Update(message); + DataContext.SaveChanges(); + } + + public void Delete(SupportMessage message) + { + DataContext.SupportMessages.Remove(message); + DataContext.SaveChanges(); + } + + public void Dispose() + { + DataContext.Dispose(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Repositories/WebsiteRepository.cs b/Moonlight/App/Repositories/WebsiteRepository.cs new file mode 100644 index 00000000..4a45b5da --- /dev/null +++ b/Moonlight/App/Repositories/WebsiteRepository.cs @@ -0,0 +1,44 @@ +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database; +using Moonlight.App.Database.Entities; + +namespace Moonlight.App.Repositories; + +public class WebsiteRepository : IDisposable +{ + private readonly DataContext DataContext; + + public WebsiteRepository(DataContext dataContext) + { + DataContext = dataContext; + } + + public DbSet Get() + { + return DataContext.Websites; + } + + public Website Add(Website website) + { + var x = DataContext.Websites.Add(website); + DataContext.SaveChanges(); + return x.Entity; + } + + public void Update(Website website) + { + DataContext.Websites.Update(website); + DataContext.SaveChanges(); + } + + public void Delete(Website website) + { + DataContext.Websites.Remove(website); + DataContext.SaveChanges(); + } + + public void Dispose() + { + DataContext.Dispose(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/CleanupService.cs b/Moonlight/App/Services/CleanupService.cs index 1ccb78c9..42e046ce 100644 --- a/Moonlight/App/Services/CleanupService.cs +++ b/Moonlight/App/Services/CleanupService.cs @@ -7,7 +7,6 @@ using Moonlight.App.Models.Wings; using Moonlight.App.Repositories; using Moonlight.App.Repositories.Servers; using Logging.Net; -using Moonlight.App.Events; using Newtonsoft.Json; namespace Moonlight.App.Services; @@ -24,24 +23,21 @@ public class CleanupService #endregion private readonly ConfigService ConfigService; - private readonly DateTimeService DateTimeService; - private readonly EventSystem Event; + private readonly MessageService MessageService; private readonly IServiceScopeFactory ServiceScopeFactory; private readonly PeriodicTimer Timer; public CleanupService( ConfigService configService, IServiceScopeFactory serviceScopeFactory, - DateTimeService dateTimeService, - EventSystem eventSystem) + MessageService messageService) { ServiceScopeFactory = serviceScopeFactory; - DateTimeService = dateTimeService; + MessageService = messageService; ConfigService = configService; - Event = eventSystem; - StartedAt = DateTimeService.GetCurrent(); - CompletedAt = DateTimeService.GetCurrent(); + StartedAt = DateTime.Now; + CompletedAt = DateTime.Now; IsRunning = false; var config = ConfigService.GetSection("Moonlight").GetSection("Cleanup"); @@ -149,7 +145,7 @@ public class CleanupService ServersRunning++; } - await Event.Emit("cleanup.updated"); + await MessageService.Emit("cleanup.updated", null); } } else @@ -179,7 +175,7 @@ public class CleanupService ServersRunning++; } - await Event.Emit("cleanup.updated"); + await MessageService.Emit("cleanup.updated", null); } } } @@ -200,7 +196,7 @@ public class CleanupService IsRunning = false; CleanupsPerformed++; - await Event.Emit("cleanup.updated"); + await MessageService.Emit("cleanup.updated", null); } } diff --git a/Moonlight/App/Services/ConfigService.cs b/Moonlight/App/Services/ConfigService.cs index 6aa11c43..27bc5bc7 100644 --- a/Moonlight/App/Services/ConfigService.cs +++ b/Moonlight/App/Services/ConfigService.cs @@ -12,7 +12,6 @@ public class ConfigService : IConfiguration private IConfiguration Configuration; public bool DebugMode { get; private set; } = false; - public bool SqlDebugMode { get; private set; } = false; public ConfigService(StorageService storageService) { @@ -29,14 +28,6 @@ public class ConfigService : IConfiguration if (DebugMode) Logger.Debug("Debug mode enabled"); - - var sqlDebugVar = Environment.GetEnvironmentVariable("ML_SQL_DEBUG"); - - if (sqlDebugVar != null) - SqlDebugMode = bool.Parse(sqlDebugVar); - - if (SqlDebugMode) - Logger.Debug("Sql debug mode enabled"); } public void Reload() diff --git a/Moonlight/App/Services/DateTimeService.cs b/Moonlight/App/Services/DateTimeService.cs deleted file mode 100644 index 40b0231e..00000000 --- a/Moonlight/App/Services/DateTimeService.cs +++ /dev/null @@ -1,31 +0,0 @@ -using Moonlight.App.Helpers; - -namespace Moonlight.App.Services; - -public class DateTimeService -{ - public long GetCurrentUnix() - { - return new DateTimeOffset(GetCurrent()).ToUnixTimeMilliseconds(); - } - - public long GetCurrentUnixSeconds() - { - return new DateTimeOffset(GetCurrent()).ToUnixTimeSeconds(); - } - - public DateTime GetCurrent() - { - return DateTime.UtcNow; - } - - public string GetDate() - { - return Formatter.FormatDateOnly(GetCurrent()); - } - - public string GetDateTime() - { - return Formatter.FormatDate(GetCurrent()); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/DiscordNotificationService.cs b/Moonlight/App/Services/DiscordNotificationService.cs deleted file mode 100644 index 41ea9a0b..00000000 --- a/Moonlight/App/Services/DiscordNotificationService.cs +++ /dev/null @@ -1,99 +0,0 @@ -using Discord; -using Discord.Webhook; -using Logging.Net; -using Moonlight.App.Database.Entities; -using Moonlight.App.Events; - -namespace Moonlight.App.Services; - -public class DiscordNotificationService -{ - private readonly EventSystem Event; - private readonly ResourceService ResourceService; - private readonly DiscordWebhookClient Client; - private readonly string AppUrl; - - public DiscordNotificationService( - EventSystem eventSystem, - ConfigService configService, - ResourceService resourceService) - { - Event = eventSystem; - ResourceService = resourceService; - - var config = configService.GetSection("Moonlight").GetSection("DiscordNotifications"); - - if (config.GetValue("Enable")) - { - Logger.Info("Discord notifications enabled"); - - Client = new(config.GetValue("WebHook")); - AppUrl = configService.GetSection("Moonlight").GetValue("AppUrl"); - - Event.On("supportChat.new", this, OnNewSupportChat); - Event.On("supportChat.message", this, OnSupportChatMessage); - Event.On("supportChat.close", this, OnSupportChatClose); - } - else - { - Logger.Info("Discord notifications disabled"); - } - } - - private async Task OnSupportChatClose(User user) - { - await SendNotification("", builder => - { - builder.Title = "A new support chat has been marked as closed"; - builder.Color = Color.Red; - builder.AddField("Email", user.Email); - builder.AddField("Firstname", user.FirstName); - builder.AddField("Lastname", user.LastName); - builder.Url = $"{AppUrl}/admin/support/view/{user.Id}"; - }); - } - - private async Task OnSupportChatMessage(SupportChatMessage message) - { - if(message.Sender == null) - return; - - await SendNotification("", builder => - { - builder.Title = "New message in support chat"; - builder.Color = Color.Blue; - builder.AddField("Message", message.Content); - builder.Author = new EmbedAuthorBuilder() - .WithName($"{message.Sender.FirstName} {message.Sender.LastName}") - .WithIconUrl(ResourceService.Avatar(message.Sender)); - builder.Url = $"{AppUrl}/admin/support/view/{message.Recipient.Id}"; - }); - } - - private async Task OnNewSupportChat(User user) - { - await SendNotification("", builder => - { - builder.Title = "A new support chat has been marked as active"; - builder.Color = Color.Green; - builder.AddField("Email", user.Email); - builder.AddField("Firstname", user.FirstName); - builder.AddField("Lastname", user.LastName); - builder.Url = $"{AppUrl}/admin/support/view/{user.Id}"; - }); - } - - private async Task SendNotification(string content, Action? embed = null) - { - var e = new EmbedBuilder(); - embed?.Invoke(e); - - await Client.SendMessageAsync( - content, - false, - new []{e.Build()}, - "Moonlight Notification", - ResourceService.Image("logo.svg") - ); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/FabricService.cs b/Moonlight/App/Services/FabricService.cs deleted file mode 100644 index 650ce155..00000000 --- a/Moonlight/App/Services/FabricService.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System.Text; -using Moonlight.App.Helpers; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Moonlight.App.Services; - -public class FabricService -{ - private readonly HttpClient Client; - - public FabricService() - { - Client = new(); - } - - public async Task GetLatestInstallerVersion() - { - var data = await Client - .GetStringAsync("https://meta.fabricmc.net/v2/versions/installer"); - - var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); - - var stableVersions = new List(); - - foreach (var y in x) - { - var section = new ConfigurationBuilder().AddJsonStream( - new MemoryStream(Encoding.ASCII.GetBytes( - y.Root.ToString() - ) - ) - ).Build(); - - if (section.GetValue("stable")) - { - stableVersions.Add(section.GetValue("version")); - } - } - - return ParseHelper.GetHighestVersion(stableVersions.ToArray()); - } - - public async Task GetLatestLoaderVersion() - { - var data = await Client - .GetStringAsync("https://meta.fabricmc.net/v2/versions/loader"); - - var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); - - var stableVersions = new List(); - - foreach (var y in x) - { - var section = new ConfigurationBuilder().AddJsonStream( - new MemoryStream(Encoding.ASCII.GetBytes( - y.Root.ToString() - ) - ) - ).Build(); - - if (section.GetValue("stable")) - { - stableVersions.Add(section.GetValue("version")); - } - } - - return ParseHelper.GetHighestVersion(stableVersions.ToArray()); - } - public async Task GetGameVersions() - { - var data = await Client - .GetStringAsync("https://meta.fabricmc.net/v2/versions/game"); - - var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); - - var stableVersions = new List(); - - foreach (var y in x) - { - var section = new ConfigurationBuilder().AddJsonStream( - new MemoryStream(Encoding.ASCII.GetBytes( - y.Root.ToString() - ) - ) - ).Build(); - - if (section.GetValue("stable")) - { - stableVersions.Add(section.GetValue("version")); - } - } - - return stableVersions.ToArray(); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/FileDownloadService.cs b/Moonlight/App/Services/FileDownloadService.cs deleted file mode 100644 index ad85c010..00000000 --- a/Moonlight/App/Services/FileDownloadService.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Text; -using Microsoft.JSInterop; - -namespace Moonlight.App.Services; - -public class FileDownloadService -{ - private readonly IJSRuntime JSRuntime; - - public FileDownloadService(IJSRuntime jsRuntime) - { - JSRuntime = jsRuntime; - } - - public async Task DownloadStream(string fileName, Stream stream) - { - using var streamRef = new DotNetStreamReference(stream); - - await JSRuntime.InvokeVoidAsync("moonlight.downloads.downloadStream", fileName, streamRef); - } - - public async Task DownloadBytes(string fileName, byte[] bytes) - { - var ms = new MemoryStream(bytes); - - await DownloadStream(fileName, ms); - } - - public async Task DownloadString(string fileName, string content) - { - await DownloadBytes(fileName, Encoding.UTF8.GetBytes(content)); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/ForgeService.cs b/Moonlight/App/Services/ForgeService.cs deleted file mode 100644 index 6171ef44..00000000 --- a/Moonlight/App/Services/ForgeService.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Text; -using Moonlight.App.Helpers; - -namespace Moonlight.App.Services; - -public class ForgeService -{ - private readonly HttpClient Client; - - public ForgeService() - { - Client = new(); - } - - // Key: 1.9.4-recommended Value: 12.17.0.2317 - public async Task> GetVersions() - { - var data = await Client.GetStringAsync( - "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"); - - var json = new ConfigurationBuilder().AddJsonStream( - new MemoryStream(Encoding.ASCII.GetBytes( - data - ) - ) - ).Build(); - - var d = new Dictionary(); - - foreach (var section in json.GetSection("promos").GetChildren()) - { - d.Add(section.Key, section.Value!); - } - - return d; - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/Interop/ClipboardService.cs b/Moonlight/App/Services/Interop/ClipboardService.cs index 6a702282..a7c806c9 100644 --- a/Moonlight/App/Services/Interop/ClipboardService.cs +++ b/Moonlight/App/Services/Interop/ClipboardService.cs @@ -10,9 +10,14 @@ public class ClipboardService { JsRuntime = jsRuntime; } - + + public async Task CopyToClipboard(string data) + { + await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data); + } public async Task Copy(string data) { - await JsRuntime.InvokeVoidAsync("moonlight.clipboard.copy", data); + await JsRuntime.InvokeVoidAsync("copyTextToClipboard", data); } + } \ No newline at end of file diff --git a/Moonlight/App/Services/Interop/ToastService.cs b/Moonlight/App/Services/Interop/ToastService.cs index af66d12a..5e1839d3 100644 --- a/Moonlight/App/Services/Interop/ToastService.cs +++ b/Moonlight/App/Services/Interop/ToastService.cs @@ -13,36 +13,36 @@ public class ToastService public async Task Info(string message) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.info", message); + await JsRuntime.InvokeVoidAsync("showInfoToast", message); } public async Task Error(string message) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.error", message); + await JsRuntime.InvokeVoidAsync("showErrorToast", message); } public async Task Warning(string message) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.warning", message); + await JsRuntime.InvokeVoidAsync("showWarningToast", message); } public async Task Success(string message) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.success", message); + await JsRuntime.InvokeVoidAsync("showSuccessToast", message); } public async Task CreateProcessToast(string id, string text) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.create", id, text); + await JsRuntime.InvokeVoidAsync("createToast", id, text); } public async Task UpdateProcessToast(string id, string text) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.modify", id, text); + await JsRuntime.InvokeVoidAsync("modifyToast", id, text); } public async Task RemoveProcessToast(string id) { - await JsRuntime.InvokeVoidAsync("moonlight.toasts.remove", id); + await JsRuntime.InvokeVoidAsync("removeToast", id); } } \ No newline at end of file diff --git a/Moonlight/App/Services/MailService.cs b/Moonlight/App/Services/MailService.cs index 9bcab325..26764603 100644 --- a/Moonlight/App/Services/MailService.cs +++ b/Moonlight/App/Services/MailService.cs @@ -1,11 +1,9 @@ using System.Net; using System.Net.Mail; using Logging.Net; -using MimeKit; using Moonlight.App.Database.Entities; using Moonlight.App.Exceptions; using Moonlight.App.Helpers; -using SmtpClient = MailKit.Net.Smtp.SmtpClient; namespace Moonlight.App.Services; @@ -15,7 +13,6 @@ public class MailService private readonly string Password; private readonly string Email; private readonly int Port; - private readonly bool Ssl; public MailService(ConfigService configService) { @@ -27,7 +24,6 @@ public class MailService Password = mailConfig.GetValue("Password"); Email = mailConfig.GetValue("Email"); Port = mailConfig.GetValue("Port"); - Ssl = mailConfig.GetValue("Ssl"); } public async Task SendMail( @@ -58,24 +54,20 @@ public class MailService { using var client = new SmtpClient(); - var mailMessage = new MimeMessage(); - mailMessage.From.Add(new MailboxAddress(Email, Email)); - mailMessage.To.Add(new MailboxAddress(user.Email, user.Email)); - mailMessage.Subject = $"Hey {user.FirstName}, there are news from moonlight"; - - var body = new BodyBuilder - { - HtmlBody = parsed - }; - mailMessage.Body = body.ToMessageBody(); + client.Host = Server; + client.Port = Port; + client.EnableSsl = true; + client.Credentials = new NetworkCredential(Email, Password); - using (var smtpClient = new SmtpClient()) + await client.SendMailAsync(new MailMessage() { - await smtpClient.ConnectAsync(Server, Port, Ssl); - await smtpClient.AuthenticateAsync(Email, Password); - await smtpClient.SendAsync(mailMessage); - await smtpClient.DisconnectAsync(true); - } + From = new MailAddress(Email), + Sender = new MailAddress(Email), + Body = parsed, + IsBodyHtml = true, + Subject = $"Hey {user.FirstName}, there are news from moonlight", + To = { new MailAddress(user.Email) } + }); } catch (Exception e) { diff --git a/Moonlight/App/Services/MessageService.cs b/Moonlight/App/Services/MessageService.cs new file mode 100644 index 00000000..1a4c8535 --- /dev/null +++ b/Moonlight/App/Services/MessageService.cs @@ -0,0 +1,11 @@ +using Moonlight.App.MessageSystem; + +namespace Moonlight.App.Services; + +public class MessageService : MessageSender +{ + public MessageService() + { + Debug = false; + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/ServerService.cs b/Moonlight/App/Services/ServerService.cs index d61ae7d4..2e46eb44 100644 --- a/Moonlight/App/Services/ServerService.cs +++ b/Moonlight/App/Services/ServerService.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Moonlight.App.Database; using Moonlight.App.Database.Entities; -using Moonlight.App.Events; using Moonlight.App.Exceptions; using Moonlight.App.Helpers; using Moonlight.App.Helpers.Files; @@ -22,8 +21,8 @@ public class ServerService private readonly UserRepository UserRepository; private readonly ImageRepository ImageRepository; private readonly NodeRepository NodeRepository; - private readonly NodeAllocationRepository NodeAllocationRepository; private readonly WingsApiHelper WingsApiHelper; + private readonly MessageService MessageService; private readonly UserService UserService; private readonly ConfigService ConfigService; private readonly WingsJwtHelper WingsJwtHelper; @@ -31,8 +30,6 @@ public class ServerService private readonly AuditLogService AuditLogService; private readonly ErrorLogService ErrorLogService; private readonly NodeService NodeService; - private readonly DateTimeService DateTimeService; - private readonly EventSystem Event; public ServerService( ServerRepository serverRepository, @@ -40,22 +37,21 @@ public class ServerService UserRepository userRepository, ImageRepository imageRepository, NodeRepository nodeRepository, + MessageService messageService, UserService userService, ConfigService configService, WingsJwtHelper wingsJwtHelper, SecurityLogService securityLogService, AuditLogService auditLogService, ErrorLogService errorLogService, - NodeService nodeService, - NodeAllocationRepository nodeAllocationRepository, - DateTimeService dateTimeService, - EventSystem eventSystem) + NodeService nodeService) { ServerRepository = serverRepository; WingsApiHelper = wingsApiHelper; UserRepository = userRepository; ImageRepository = imageRepository; NodeRepository = nodeRepository; + MessageService = messageService; UserService = userService; ConfigService = configService; WingsJwtHelper = wingsJwtHelper; @@ -63,9 +59,6 @@ public class ServerService AuditLogService = auditLogService; ErrorLogService = errorLogService; NodeService = nodeService; - NodeAllocationRepository = nodeAllocationRepository; - DateTimeService = dateTimeService; - Event = eventSystem; } private Server EnsureNodeData(Server s) @@ -119,9 +112,9 @@ public class ServerService var backup = new ServerBackup() { - Name = $"Created at {DateTimeService.GetCurrent().ToShortDateString()} {DateTimeService.GetCurrent().ToShortTimeString()}", + Name = $"Created at {DateTime.Now.ToShortDateString()} {DateTime.Now.ToShortTimeString()}", Uuid = Guid.NewGuid(), - CreatedAt = DateTimeService.GetCurrent(), + CreatedAt = DateTime.Now, Created = false }; @@ -193,27 +186,15 @@ public class ServerService .Include(x => x.Backups) .First(x => x.Id == server.Id); - try - { - await WingsApiHelper.Delete(serverData.Node, $"api/servers/{serverData.Uuid}/backup/{serverBackup.Uuid}", - null); - } - catch (WingsException e) - { - // when a backup is not longer there we can - // safely delete the backup so we ignore this error - if (e.StatusCode != 404) - { - throw; - } - } - + await WingsApiHelper.Delete(serverData.Node, $"api/servers/{serverData.Uuid}/backup/{serverBackup.Uuid}", + null); + var backup = serverData.Backups.First(x => x.Uuid == serverBackup.Uuid); serverData.Backups.Remove(backup); ServerRepository.Update(serverData); - await Event.Emit("wings.backups.delete", backup); + await MessageService.Emit("wings.backups.delete", backup); await AuditLogService.Log(AuditLogType.DeleteBackup, x => @@ -263,7 +244,7 @@ public class ServerService } public async Task Create(string name, int cpu, long memory, long disk, User u, Image i, Node? n = null, - Action? modifyDetails = null) + Action? modifyDetails = null, int allocations = 1) { var user = UserRepository .Get() @@ -275,21 +256,32 @@ public class ServerService .Include(x => x.DockerImages) .First(x => x.Id == i.Id); - var allocations = image.Allocations; + Node node; - Node node = n ?? NodeRepository.Get().First(); + if (n == null) + { + node = NodeRepository + .Get() + .Include(x => x.Allocations) + .First(); //TODO: Add smart deploy maybe + } + else + { + node = NodeRepository + .Get() + .Include(x => x.Allocations) + .First(x => x.Id == n.Id); + } NodeAllocation[] freeAllocations; try { - // We have sadly no choice to use entity framework to do what the sql call does, there - // are only slower ways, so we will use a raw sql call as a exception - - freeAllocations = NodeAllocationRepository - .Get() - .FromSqlRaw($"SELECT * FROM `NodeAllocations` WHERE ServerId IS NULL AND NodeId={node.Id} LIMIT {allocations}") - .ToArray(); + freeAllocations = node.Allocations + .Where(a => !ServerRepository.Get() + .SelectMany(s => s.Allocations) + .Any(b => b.Id == a.Id)) + .Take(allocations).ToArray(); } catch (Exception) { @@ -380,7 +372,7 @@ public class ServerService var user = await UserService.SftpLogin(id, password); - if (server.Owner.Id == user.Id || user.Admin) + if (server.Owner.Id == user.Id) { return server; } diff --git a/Moonlight/App/Services/Sessions/IdentityService.cs b/Moonlight/App/Services/Sessions/IdentityService.cs index ef98937f..f35519e1 100644 --- a/Moonlight/App/Services/Sessions/IdentityService.cs +++ b/Moonlight/App/Services/Sessions/IdentityService.cs @@ -4,7 +4,6 @@ using JWT.Builder; using JWT.Exceptions; using Logging.Net; using Moonlight.App.Database.Entities; -using Moonlight.App.Helpers; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories; using Moonlight.App.Services.LogServices; @@ -124,9 +123,9 @@ public class IdentityService return null; } - var iatD = DateTimeOffset.FromUnixTimeSeconds(iat).ToUniversalTime().DateTime; - - if (iatD < user.TokenValidTime) + var issuedAt = DateTimeOffset.FromUnixTimeSeconds(iat).DateTime; + + if (issuedAt < user.TokenValidTime.ToUniversalTime()) return null; UserCache = user; diff --git a/Moonlight/App/Services/Sessions/SessionService.cs b/Moonlight/App/Services/Sessions/SessionService.cs index f7b97cef..1ecbd67d 100644 --- a/Moonlight/App/Services/Sessions/SessionService.cs +++ b/Moonlight/App/Services/Sessions/SessionService.cs @@ -12,7 +12,6 @@ public class SessionService private readonly IdentityService IdentityService; private readonly NavigationManager NavigationManager; private readonly AlertService AlertService; - private readonly DateTimeService DateTimeService; private Session? OwnSession; @@ -20,14 +19,12 @@ public class SessionService SessionRepository sessionRepository, IdentityService identityService, NavigationManager navigationManager, - AlertService alertService, - DateTimeService dateTimeService) + AlertService alertService) { SessionRepository = sessionRepository; IdentityService = identityService; NavigationManager = navigationManager; AlertService = alertService; - DateTimeService = dateTimeService; } public async Task Register() @@ -39,7 +36,7 @@ public class SessionService Ip = IdentityService.GetIp(), Url = NavigationManager.Uri, Device = IdentityService.GetDevice(), - CreatedAt = DateTimeService.GetCurrent(), + CreatedAt = DateTime.Now, User = user, Navigation = NavigationManager, AlertService = AlertService @@ -67,8 +64,10 @@ public class SessionService { foreach (var session in SessionRepository.Get()) { - if(session.User != null && session.User.Id == user.Id) + if (session.User.Id == user.Id) + { session.Navigation.NavigateTo(session.Navigation.Uri, true); + } } } } \ No newline at end of file diff --git a/Moonlight/App/Services/SmartDeployService.cs b/Moonlight/App/Services/SmartDeployService.cs index 38d013a0..57aa4bc8 100644 --- a/Moonlight/App/Services/SmartDeployService.cs +++ b/Moonlight/App/Services/SmartDeployService.cs @@ -6,20 +6,18 @@ namespace Moonlight.App.Services; public class SmartDeployService { private readonly NodeRepository NodeRepository; - private readonly Repository CloudPanelRepository; - private readonly WebSpaceService WebSpaceService; + private readonly PleskServerRepository PleskServerRepository; + private readonly WebsiteService WebsiteService; private readonly NodeService NodeService; public SmartDeployService( NodeRepository nodeRepository, - NodeService nodeService, - WebSpaceService webSpaceService, - Repository cloudPanelRepository) + NodeService nodeService, PleskServerRepository pleskServerRepository, WebsiteService websiteService) { NodeRepository = nodeRepository; NodeService = nodeService; - WebSpaceService = webSpaceService; - CloudPanelRepository = cloudPanelRepository; + PleskServerRepository = pleskServerRepository; + WebsiteService = websiteService; } public async Task GetNode() @@ -40,14 +38,16 @@ public class SmartDeployService return data.MaxBy(x => x.Value).Key; } - public async Task GetCloudPanel() + public async Task GetPleskServer() { - var result = new List(); + var result = new List(); - foreach (var cloudPanel in CloudPanelRepository.Get().ToArray()) + foreach (var pleskServer in PleskServerRepository.Get().ToArray()) { - if (await WebSpaceService.IsHostUp(cloudPanel)) - result.Add(cloudPanel); + if (await WebsiteService.IsHostUp(pleskServer)) + { + result.Add(pleskServer); + } } return result.FirstOrDefault(); diff --git a/Moonlight/App/Services/Statistics/StatisticsCaptureService.cs b/Moonlight/App/Services/Statistics/StatisticsCaptureService.cs index 139ece7b..3098e5d1 100644 --- a/Moonlight/App/Services/Statistics/StatisticsCaptureService.cs +++ b/Moonlight/App/Services/Statistics/StatisticsCaptureService.cs @@ -1,78 +1,57 @@ -using Logging.Net; -using Moonlight.App.Database; -using Moonlight.App.Database.Entities; +using Moonlight.App.Database; using Moonlight.App.Repositories; -using Moonlight.App.Services.Sessions; namespace Moonlight.App.Services.Statistics; public class StatisticsCaptureService { + private readonly DataContext DataContext; + private readonly ConfigService ConfigService; + private readonly StatisticsRepository StatisticsRepository; private readonly IServiceScopeFactory ServiceScopeFactory; - private readonly DateTimeService DateTimeService; - private readonly PeriodicTimer Timer; + private readonly WebsiteService WebsiteService; + private readonly PleskServerRepository PleskServerRepository; + private PeriodicTimer Timer; - public StatisticsCaptureService(IServiceScopeFactory serviceScopeFactory, ConfigService configService, DateTimeService dateTimeService) + public StatisticsCaptureService(IServiceScopeFactory serviceScopeFactory, ConfigService configService) { ServiceScopeFactory = serviceScopeFactory; - DateTimeService = dateTimeService; + var provider = ServiceScopeFactory.CreateScope().ServiceProvider; + + DataContext = provider.GetRequiredService(); + ConfigService = configService; + StatisticsRepository = provider.GetRequiredService(); + WebsiteService = provider.GetRequiredService(); + PleskServerRepository = provider.GetRequiredService(); - var config = configService - .GetSection("Moonlight") - .GetSection("Statistics"); - + var config = ConfigService.GetSection("Moonlight").GetSection("Statistics"); if(!config.GetValue("Enabled")) return; - - var period = TimeSpan.FromMinutes(config.GetValue("Wait")); + + var _period = config.GetValue("Wait"); + var period = TimeSpan.FromMinutes(_period); Timer = new(period); - Logger.Info("Starting statistics system"); Task.Run(Run); } private async Task Run() { - try + while (await Timer.WaitForNextTickAsync()) { - while (await Timer.WaitForNextTickAsync()) + StatisticsRepository.Add("statistics.usersCount", DataContext.Users.Count()); + StatisticsRepository.Add("statistics.serversCount", DataContext.Servers.Count()); + StatisticsRepository.Add("statistics.domainsCount", DataContext.Domains.Count()); + StatisticsRepository.Add("statistics.websitesCount", DataContext.Websites.Count()); + + int databases = 0; + + await foreach (var pleskServer in PleskServerRepository.Get()) { - Logger.Warn("Creating statistics"); - - using var scope = ServiceScopeFactory.CreateScope(); - - var statisticsRepo = scope.ServiceProvider.GetRequiredService>(); - var usersRepo = scope.ServiceProvider.GetRequiredService>(); - var serversRepo = scope.ServiceProvider.GetRequiredService>(); - var domainsRepo = scope.ServiceProvider.GetRequiredService>(); - var webspacesRepo = scope.ServiceProvider.GetRequiredService>(); - var databasesRepo = scope.ServiceProvider.GetRequiredService>(); - var sessionService = scope.ServiceProvider.GetRequiredService(); - - void AddEntry(string chart, int value) - { - statisticsRepo!.Add(new StatisticsData() - { - Chart = chart, - Value = value, - Date = DateTimeService.GetCurrent() - }); - } - - AddEntry("usersCount", usersRepo.Get().Count()); - AddEntry("serversCount", serversRepo.Get().Count()); - AddEntry("domainsCount", domainsRepo.Get().Count()); - AddEntry("webspacesCount", webspacesRepo.Get().Count()); - AddEntry("databasesCount", databasesRepo.Get().Count()); - AddEntry("sessionsCount", sessionService.GetAll().Length); + databases += (await WebsiteService.GetDefaultDatabaseServer(pleskServer)).DbCount; } - Logger.Log("Statistics are weird"); - } - catch (Exception e) - { - Logger.Error("An unexpected error occured while capturing statistics"); - Logger.Error(e); + StatisticsRepository.Add("statistics.databasesCount", databases); } } } \ No newline at end of file diff --git a/Moonlight/App/Services/Statistics/StatisticsViewService.cs b/Moonlight/App/Services/Statistics/StatisticsViewService.cs index dfb68f01..329445fe 100644 --- a/Moonlight/App/Services/Statistics/StatisticsViewService.cs +++ b/Moonlight/App/Services/Statistics/StatisticsViewService.cs @@ -7,17 +7,15 @@ namespace Moonlight.App.Services.Statistics; public class StatisticsViewService { private readonly StatisticsRepository StatisticsRepository; - private readonly DateTimeService DateTimeService; - public StatisticsViewService(StatisticsRepository statisticsRepository, DateTimeService dateTimeService) + public StatisticsViewService(StatisticsRepository statisticsRepository) { StatisticsRepository = statisticsRepository; - DateTimeService = dateTimeService; } public StatisticsData[] GetData(string chart, StatisticsTimeSpan timeSpan) { - var startDate = DateTimeService.GetCurrent() - TimeSpan.FromHours((int)timeSpan); + var startDate = DateTime.Now - TimeSpan.FromHours((int)timeSpan); var objs = StatisticsRepository.Get().Where(x => x.Date > startDate && x.Chart == chart); diff --git a/Moonlight/App/Services/SubscriptionService.cs b/Moonlight/App/Services/SubscriptionService.cs index 2dcc797c..de23692a 100644 --- a/Moonlight/App/Services/SubscriptionService.cs +++ b/Moonlight/App/Services/SubscriptionService.cs @@ -1,7 +1,6 @@ using Microsoft.EntityFrameworkCore; using Moonlight.App.Database.Entities; using Moonlight.App.Exceptions; -using Moonlight.App.Helpers; using Moonlight.App.Models.Misc; using Moonlight.App.Repositories; using Moonlight.App.Services.Sessions; @@ -15,18 +14,20 @@ public class SubscriptionService 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 - ) + UserRepository userRepository, + ConfigService configService) { SubscriptionRepository = subscriptionRepository; OneTimeJwtService = oneTimeJwtService; IdentityService = identityService; UserRepository = userRepository; + ConfigService = configService; } public async Task GetCurrent() @@ -89,15 +90,13 @@ public class SubscriptionService } } - public async Task GetLimit(string identifier) // Cache, optimize sql code + public async Task GetLimit(string identifier) { var subscription = await GetCurrent(); - var defaultLimits = await GetDefaultLimits(); if (subscription == null) { - // If the default subscription limit with identifier is found, return it. if not, return empty - return defaultLimits.FirstOrDefault(x => x.Identifier == identifier) ?? new() + return new() { Identifier = identifier, Amount = 0 @@ -112,9 +111,8 @@ public class SubscriptionService if (foundLimit != null) return foundLimit; - - // If the default subscription limit with identifier is found, return it. if not, return empty - return defaultLimits.FirstOrDefault(x => x.Identifier == identifier) ?? new() + + return new() { Identifier = identifier, Amount = 0 @@ -135,17 +133,4 @@ public class SubscriptionService return userWithData; } - - private async Task GetDefaultLimits() // Add cache and reload option - { - var defaultSubscriptionJson = "[]"; - - if (File.Exists(PathBuilder.File("storage", "configs", "default_subscription.json"))) - { - defaultSubscriptionJson = - await File.ReadAllTextAsync(PathBuilder.File("storage", "configs", "default_subscription.json")); - } - - return JsonConvert.DeserializeObject(defaultSubscriptionJson) ?? Array.Empty(); - } } \ No newline at end of file diff --git a/Moonlight/App/Services/Support/SupportAdminService.cs b/Moonlight/App/Services/Support/SupportAdminService.cs new file mode 100644 index 00000000..2dabdef1 --- /dev/null +++ b/Moonlight/App/Services/Support/SupportAdminService.cs @@ -0,0 +1,132 @@ +using Moonlight.App.Database.Entities; +using Moonlight.App.Services.Sessions; + +namespace Moonlight.App.Services.Support; + +public class SupportAdminService +{ + private readonly SupportServerService SupportServerService; + private readonly IdentityService IdentityService; + private readonly MessageService MessageService; + + public EventHandler OnNewMessage; + + public EventHandler OnUpdateTyping; + private List TypingUsers = new(); + + private User Self; + private User Recipient; + + public SupportAdminService( + SupportServerService supportServerService, + IdentityService identityService, + MessageService messageService) + { + SupportServerService = supportServerService; + IdentityService = identityService; + MessageService = messageService; + } + + public async Task Start(User user) + { + Self = (await IdentityService.Get())!; + Recipient = user; + + MessageService.Subscribe( + $"support.{Recipient.Id}.message", + this, + message => + { + OnNewMessage?.Invoke(this, message); + + return Task.CompletedTask; + }); + + MessageService.Subscribe( + $"support.{Self.Id}.typing", + this, + user => + { + HandleTyping(user); + return Task.CompletedTask; + }); + } + + #region Typing + + private void HandleTyping(User user) + { + var name = $"{user.FirstName} {user.LastName}"; + + lock (TypingUsers) + { + if (!TypingUsers.Contains(name)) + { + TypingUsers.Add(name); + OnUpdateTyping!.Invoke(this, null!); + + Task.Run(async () => + { + await Task.Delay(TimeSpan.FromSeconds(5)); + + if (TypingUsers.Contains(name)) + { + TypingUsers.Remove(name); + OnUpdateTyping!.Invoke(this, null!); + } + }); + } + } + } + + public string[] GetTypingUsers() + { + lock (TypingUsers) + { + return TypingUsers.ToArray(); + } + } + + public Task TriggerTyping() + { + Task.Run(async () => + { + await MessageService.Emit($"support.{Recipient.Id}.admintyping", Self); + }); + + return Task.CompletedTask; + } + + #endregion + + public async Task GetMessages() + { + return await SupportServerService.GetMessages(Recipient); + } + + public async Task SendMessage(string content) + { + var message = new SupportMessage() + { + Message = content + }; + + await SupportServerService.SendMessage( + Recipient, + message, + Self, + true + ); + } + + public async Task Close() + { + await SupportServerService.Close(Recipient); + } + + public void Dispose() + { + MessageService.Unsubscribe($"support.{Recipient.Id}.message", this); + MessageService.Unsubscribe($"support.{Recipient.Id}.typing", this); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/Support/SupportClientService.cs b/Moonlight/App/Services/Support/SupportClientService.cs new file mode 100644 index 00000000..5b4f54dc --- /dev/null +++ b/Moonlight/App/Services/Support/SupportClientService.cs @@ -0,0 +1,124 @@ +using Moonlight.App.Database.Entities; +using Moonlight.App.Services.Sessions; + +namespace Moonlight.App.Services.Support; + +public class SupportClientService : IDisposable +{ + private readonly SupportServerService SupportServerService; + private readonly IdentityService IdentityService; + private readonly MessageService MessageService; + + public EventHandler OnNewMessage; + + public EventHandler OnUpdateTyping; + private List TypingUsers = new(); + + private User Self; + + public SupportClientService( + SupportServerService supportServerService, + IdentityService identityService, + MessageService messageService) + { + SupportServerService = supportServerService; + IdentityService = identityService; + MessageService = messageService; + } + + public async Task Start() + { + Self = (await IdentityService.Get())!; + + MessageService.Subscribe( + $"support.{Self.Id}.message", + this, + message => + { + OnNewMessage?.Invoke(this, message); + + return Task.CompletedTask; + }); + + MessageService.Subscribe( + $"support.{Self.Id}.admintyping", + this, + user => + { + HandleTyping(user); + return Task.CompletedTask; + }); + } + + #region Typing + + private void HandleTyping(User user) + { + var name = $"{user.FirstName} {user.LastName}"; + + lock (TypingUsers) + { + if (!TypingUsers.Contains(name)) + { + TypingUsers.Add(name); + OnUpdateTyping!.Invoke(this, null!); + + Task.Run(async () => + { + await Task.Delay(TimeSpan.FromSeconds(5)); + + if (TypingUsers.Contains(name)) + { + TypingUsers.Remove(name); + OnUpdateTyping!.Invoke(this, null!); + } + }); + } + } + } + + public string[] GetTypingUsers() + { + lock (TypingUsers) + { + return TypingUsers.ToArray(); + } + } + + public Task TriggerTyping() + { + Task.Run(async () => + { + await MessageService.Emit($"support.{Self.Id}.typing", Self); + }); + + return Task.CompletedTask; + } + + #endregion + + public async Task GetMessages() + { + return await SupportServerService.GetMessages(Self); + } + + public async Task SendMessage(string content) + { + var message = new SupportMessage() + { + Message = content + }; + + await SupportServerService.SendMessage( + Self, + message, + Self + ); + } + + public void Dispose() + { + MessageService.Unsubscribe($"support.{Self.Id}.message", this); + MessageService.Unsubscribe($"support.{Self.Id}.admintyping", this); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/Support/SupportServerService.cs b/Moonlight/App/Services/Support/SupportServerService.cs new file mode 100644 index 00000000..f2b22b7f --- /dev/null +++ b/Moonlight/App/Services/Support/SupportServerService.cs @@ -0,0 +1,138 @@ +using Logging.Net; +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database.Entities; +using Moonlight.App.Repositories; + +namespace Moonlight.App.Services.Support; + +public class SupportServerService : IDisposable +{ + private SupportMessageRepository SupportMessageRepository; + private MessageService MessageService; + private UserRepository UserRepository; + private readonly IServiceScopeFactory ServiceScopeFactory; + private IServiceScope ServiceScope; + + public SupportServerService(IServiceScopeFactory serviceScopeFactory) + { + ServiceScopeFactory = serviceScopeFactory; + + Task.Run(Run); + } + + public async Task SendMessage(User r, SupportMessage message, User s, bool isSupport = false) + { + var recipient = UserRepository.Get().First(x => x.Id == r.Id); + var sender = UserRepository.Get().First(x => x.Id == s.Id); + + Task.Run(async () => + { + try + { + message.CreatedAt = DateTime.UtcNow; + message.Sender = sender; + message.Recipient = recipient; + message.IsSupport = isSupport; + + SupportMessageRepository.Add(message); + + await MessageService.Emit($"support.{recipient.Id}.message", message); + + if (!recipient.SupportPending) + { + recipient.SupportPending = true; + UserRepository.Update(recipient); + + if (!message.IsSupport) + { + var systemMessage = new SupportMessage() + { + Recipient = recipient, + Sender = null, + IsSystem = true, + Message = "The support team has been notified. Please be patient" + }; + + SupportMessageRepository.Add(systemMessage); + + await MessageService.Emit($"support.{recipient.Id}.message", systemMessage); + } + + await MessageService.Emit($"support.new", recipient); + + Logger.Info("Support ticket created: " + recipient.Id); + //TODO: Ping or so + } + } + catch (Exception e) + { + Logger.Error("Error sending message"); + Logger.Error(e); + } + }); + } + + public async Task Close(User user) + { + var recipient = UserRepository.Get().First(x => x.Id == user.Id); + + recipient.SupportPending = false; + UserRepository.Update(recipient); + + var systemMessage = new SupportMessage() + { + Recipient = recipient, + Sender = null, + IsSystem = true, + Message = "The ticket is now closed. Type a message to open it again" + }; + + SupportMessageRepository.Add(systemMessage); + + await MessageService.Emit($"support.{recipient.Id}.message", systemMessage); + await MessageService.Emit($"support.close", recipient); + } + + public Task GetMessages(User r) + { + var recipient = UserRepository.Get().First(x => x.Id == r.Id); + + var messages = SupportMessageRepository + .Get() + .Include(x => x.Recipient) + .Include(x => x.Sender) + .Where(x => x.Recipient.Id == recipient.Id) + .AsEnumerable() + .TakeLast(50) + .OrderBy(x => x.Id) + .ToArray(); + + return Task.FromResult(messages); + } + + private Task Run() + { + ServiceScope = ServiceScopeFactory.CreateScope(); + + SupportMessageRepository = ServiceScope + .ServiceProvider + .GetRequiredService(); + + MessageService = ServiceScope + .ServiceProvider + .GetRequiredService(); + + UserRepository = ServiceScope + .ServiceProvider + .GetRequiredService(); + + return Task.CompletedTask; + } + + public void Dispose() + { + SupportMessageRepository.Dispose(); + UserRepository.Dispose(); + ServiceScope.Dispose(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/SupportChat/SupportChatAdminService.cs b/Moonlight/App/Services/SupportChat/SupportChatAdminService.cs deleted file mode 100644 index 6369f34a..00000000 --- a/Moonlight/App/Services/SupportChat/SupportChatAdminService.cs +++ /dev/null @@ -1,134 +0,0 @@ -using Moonlight.App.Database.Entities; -using Moonlight.App.Events; -using Moonlight.App.Services.Sessions; - -namespace Moonlight.App.Services.SupportChat; - -public class SupportChatAdminService -{ - private readonly EventSystem Event; - private readonly IdentityService IdentityService; - private readonly SupportChatServerService ServerService; - - public Func? OnMessage { get; set; } - public Func? OnTypingChanged { get; set; } - - private User? User; - private User Recipient = null!; - private readonly List TypingUsers = new(); - - public SupportChatAdminService( - EventSystem eventSystem, - SupportChatServerService serverService, - IdentityService identityService) - { - Event = eventSystem; - ServerService = serverService; - IdentityService = identityService; - } - - public async Task Start(User recipient) - { - User = await IdentityService.Get(); - Recipient = recipient; - - if (User != null) - { - await Event.On($"supportChat.{Recipient.Id}.message", this, async message => - { - if (OnMessage != null) - { - if(message.Sender != null && message.Sender.Id == User.Id) - return; - - await OnMessage.Invoke(message); - } - }); - - await Event.On($"supportChat.{Recipient.Id}.typing", this, async user => - { - await HandleTyping(user); - }); - } - } - - public async Task GetMessages() - { - if (User == null) - return Array.Empty(); - - return await ServerService.GetMessages(Recipient); - } - - public async Task SendMessage(string content) - { - if (User != null) - { - return await ServerService.SendMessage(Recipient, content, User); - } - - return null!; - } - - private Task HandleTyping(User user) - { - lock (TypingUsers) - { - if (!TypingUsers.Contains(user)) - { - TypingUsers.Add(user); - - if (OnTypingChanged != null) - { - OnTypingChanged.Invoke( - TypingUsers - .Where(x => x.Id != User!.Id) - .Select(x => $"{x.FirstName} {x.LastName}") - .ToArray() - ); - } - - Task.Run(async () => - { - await Task.Delay(TimeSpan.FromSeconds(5)); - - if (TypingUsers.Contains(user)) - { - TypingUsers.Remove(user); - - if (OnTypingChanged != null) - { - await OnTypingChanged.Invoke( - TypingUsers - .Where(x => x.Id != User!.Id) - .Select(x => $"{x.FirstName} {x.LastName}") - .ToArray() - ); - } - } - }); - } - } - - return Task.CompletedTask; - } - - public async Task SendTyping() - { - await Event.Emit($"supportChat.{Recipient.Id}.typing", User); - } - - public async Task Close() - { - await ServerService.CloseChat(Recipient); - } - - public async void Dispose() - { - if (User != null) - { - await Event.Off($"supportChat.{Recipient.Id}.message", this); - await Event.Off($"supportChat.{Recipient.Id}.typing", this); - } - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/SupportChat/SupportChatClientService.cs b/Moonlight/App/Services/SupportChat/SupportChatClientService.cs deleted file mode 100644 index ad2b3eb7..00000000 --- a/Moonlight/App/Services/SupportChat/SupportChatClientService.cs +++ /dev/null @@ -1,128 +0,0 @@ -using Logging.Net; -using Moonlight.App.Database.Entities; -using Moonlight.App.Events; -using Moonlight.App.Services.Sessions; - -namespace Moonlight.App.Services.SupportChat; - -public class SupportChatClientService : IDisposable -{ - private readonly EventSystem Event; - private readonly IdentityService IdentityService; - private readonly SupportChatServerService ServerService; - - public Func? OnMessage { get; set; } - public Func? OnTypingChanged { get; set; } - - private User? User; - private readonly List TypingUsers = new(); - - public SupportChatClientService( - EventSystem eventSystem, - SupportChatServerService serverService, - IdentityService identityService) - { - Event = eventSystem; - ServerService = serverService; - IdentityService = identityService; - } - - public async Task Start() - { - User = await IdentityService.Get(); - - if (User != null) - { - await Event.On($"supportChat.{User.Id}.message", this, async message => - { - if (OnMessage != null) - { - if(message.Sender != null && message.Sender.Id == User.Id) - return; - - await OnMessage.Invoke(message); - } - }); - - await Event.On($"supportChat.{User.Id}.typing", this, async user => - { - await HandleTyping(user); - }); - } - } - - public async Task GetMessages() - { - if (User == null) - return Array.Empty(); - - return await ServerService.GetMessages(User); - } - - public async Task SendMessage(string content) - { - if (User != null) - { - return await ServerService.SendMessage(User, content, User); - } - - return null!; - } - - private Task HandleTyping(User user) - { - lock (TypingUsers) - { - if (!TypingUsers.Contains(user)) - { - TypingUsers.Add(user); - - if (OnTypingChanged != null) - { - OnTypingChanged.Invoke( - TypingUsers - .Where(x => x.Id != User!.Id) - .Select(x => $"{x.FirstName} {x.LastName}") - .ToArray() - ); - } - - Task.Run(async () => - { - await Task.Delay(TimeSpan.FromSeconds(5)); - - if (TypingUsers.Contains(user)) - { - TypingUsers.Remove(user); - - if (OnTypingChanged != null) - { - await OnTypingChanged.Invoke( - TypingUsers - .Where(x => x.Id != User!.Id) - .Select(x => $"{x.FirstName} {x.LastName}") - .ToArray() - ); - } - } - }); - } - } - - return Task.CompletedTask; - } - - public async Task SendTyping() - { - await Event.Emit($"supportChat.{User!.Id}.typing", User); - } - - public async void Dispose() - { - if (User != null) - { - await Event.Off($"supportChat.{User.Id}.message", this); - await Event.Off($"supportChat.{User.Id}.typing", this); - } - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/SupportChat/SupportChatServerService.cs b/Moonlight/App/Services/SupportChat/SupportChatServerService.cs deleted file mode 100644 index 7fd0555c..00000000 --- a/Moonlight/App/Services/SupportChat/SupportChatServerService.cs +++ /dev/null @@ -1,146 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using Moonlight.App.Database.Entities; -using Moonlight.App.Events; -using Moonlight.App.Repositories; - -namespace Moonlight.App.Services.SupportChat; - -public class SupportChatServerService -{ - private readonly IServiceScopeFactory ServiceScopeFactory; - private readonly DateTimeService DateTimeService; - private readonly EventSystem Event; - - public SupportChatServerService( - IServiceScopeFactory serviceScopeFactory, - DateTimeService dateTimeService, - EventSystem eventSystem) - { - ServiceScopeFactory = serviceScopeFactory; - DateTimeService = dateTimeService; - Event = eventSystem; - } - - public Task GetMessages(User recipient) - { - using var scope = ServiceScopeFactory.CreateScope(); - var msgRepo = scope.ServiceProvider.GetRequiredService>(); - - var messages = msgRepo - .Get() - .Include(x => x.Recipient) - .Include(x => x.Sender) - .Where(x => x.Recipient.Id == recipient.Id) - .OrderByDescending(x => x.CreatedAt) - .AsEnumerable() - .Take(50) - .ToArray(); - - return Task.FromResult(messages); - } - - public async Task SendMessage(User recipient, string content, User? sender, string? attachment = null) - { - using var scope = ServiceScopeFactory.CreateScope(); - var msgRepo = scope.ServiceProvider.GetRequiredService>(); - var userRepo = scope.ServiceProvider.GetRequiredService>(); - - var message = new SupportChatMessage() - { - CreatedAt = DateTimeService.GetCurrent(), - IsQuestion = false, - Sender = sender == null ? null : userRepo.Get().First(x => x.Id == sender.Id), - Recipient = userRepo.Get().First(x => x.Id == recipient.Id), - Answer = "", - Attachment = attachment ?? "", - Content = content, - UpdatedAt = DateTimeService.GetCurrent() - }; - - var finalMessage = msgRepo.Add(message); - - await Event.Emit($"supportChat.{recipient.Id}.message", finalMessage); - await Event.Emit("supportChat.message", finalMessage); - - if (!userRepo.Get().First(x => x.Id == recipient.Id).SupportPending) - { - var ticketStart = new SupportChatMessage() - { - CreatedAt = DateTimeService.GetCurrent(), - IsQuestion = false, - Sender = null, - Recipient = userRepo.Get().First(x => x.Id == recipient.Id), - Answer = "", - Attachment = "", - Content = "Support ticket open", //TODO: Config - UpdatedAt = DateTimeService.GetCurrent() - }; - - var ticketStartFinal = msgRepo.Add(ticketStart); - - var user = userRepo.Get().First(x => x.Id == recipient.Id); - user.SupportPending = true; - userRepo.Update(user); - - await Event.Emit($"supportChat.{recipient.Id}.message", ticketStartFinal); - await Event.Emit("supportChat.message", ticketStartFinal); - await Event.Emit("supportChat.new", recipient); - } - - return finalMessage; - } - - public Task> GetOpenChats() - { - var result = new Dictionary(); - - using var scope = ServiceScopeFactory.CreateScope(); - var userRepo = scope.ServiceProvider.GetRequiredService>(); - var msgRepo = scope.ServiceProvider.GetRequiredService>(); - - foreach (var user in userRepo.Get().Where(x => x.SupportPending).ToArray()) - { - var lastMessage = msgRepo - .Get() - .Include(x => x.Recipient) - .Include(x => x.Sender) - .Where(x => x.Recipient.Id == user.Id) - .OrderByDescending(x => x.CreatedAt) - .AsEnumerable() - .FirstOrDefault(); - - result.Add(user, lastMessage); - } - - return Task.FromResult(result); - } - - public async Task CloseChat(User recipient) - { - using var scope = ServiceScopeFactory.CreateScope(); - var msgRepo = scope.ServiceProvider.GetRequiredService>(); - var userRepo = scope.ServiceProvider.GetRequiredService>(); - - var ticketEnd = new SupportChatMessage() - { - CreatedAt = DateTimeService.GetCurrent(), - IsQuestion = false, - Sender = null, - Recipient = userRepo.Get().First(x => x.Id == recipient.Id), - Answer = "", - Attachment = "", - Content = "Support ticket closed", //TODO: Config - UpdatedAt = DateTimeService.GetCurrent() - }; - - var ticketEndFinal = msgRepo.Add(ticketEnd); - - var user = userRepo.Get().First(x => x.Id == recipient.Id); - user.SupportPending = false; - userRepo.Update(user); - - await Event.Emit($"supportChat.{recipient.Id}.message", ticketEndFinal); - await Event.Emit("supportChat.message", ticketEndFinal); - await Event.Emit("supportChat.close", recipient); - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/UserService.cs b/Moonlight/App/Services/UserService.cs index 81633b14..6a6fe022 100644 --- a/Moonlight/App/Services/UserService.cs +++ b/Moonlight/App/Services/UserService.cs @@ -19,7 +19,6 @@ public class UserService private readonly MailService MailService; private readonly IdentityService IdentityService; private readonly IpLocateService IpLocateService; - private readonly DateTimeService DateTimeService; private readonly string JwtSecret; @@ -30,9 +29,7 @@ public class UserService SecurityLogService securityLogService, AuditLogService auditLogService, MailService mailService, - IdentityService identityService, - IpLocateService ipLocateService, - DateTimeService dateTimeService) + IdentityService identityService, IpLocateService ipLocateService) { UserRepository = userRepository; TotpService = totpService; @@ -41,7 +38,6 @@ public class UserService MailService = mailService; IdentityService = identityService; IpLocateService = ipLocateService; - DateTimeService = dateTimeService; JwtSecret = configService .GetSection("Moonlight") @@ -74,12 +70,12 @@ public class UserService LastName = lastname, State = "", Status = UserStatus.Unverified, - CreatedAt = DateTimeService.GetCurrent(), + CreatedAt = DateTime.UtcNow, DiscordId = 0, TotpEnabled = false, TotpSecret = "", - UpdatedAt = DateTimeService.GetCurrent(), - TokenValidTime = DateTimeService.GetCurrent().AddDays(-5) + UpdatedAt = DateTime.UtcNow, + TokenValidTime = DateTime.Now.AddDays(-5) }); await MailService.SendMail(user!, "register", values => {}); @@ -172,7 +168,7 @@ public class UserService public async Task ChangePassword(User user, string password, bool isSystemAction = false) { user.Password = BCrypt.Net.BCrypt.HashPassword(password); - user.TokenValidTime = DateTimeService.GetCurrent(); + user.TokenValidTime = DateTime.Now; UserRepository.Update(user); if (isSystemAction) @@ -248,8 +244,8 @@ public class UserService var token = JwtBuilder.Create() .WithAlgorithm(new HMACSHA256Algorithm()) .WithSecret(JwtSecret) - .AddClaim("exp", new DateTimeOffset(DateTimeService.GetCurrent().AddDays(10)).ToUnixTimeSeconds()) - .AddClaim("iat", DateTimeService.GetCurrentUnixSeconds()) + .AddClaim("exp", DateTimeOffset.UtcNow.AddDays(10).ToUnixTimeSeconds()) + .AddClaim("iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()) .AddClaim("userid", user.Id) .Encode(); diff --git a/Moonlight/App/Services/WebSpaceService.cs b/Moonlight/App/Services/WebSpaceService.cs deleted file mode 100644 index 91a3d718..00000000 --- a/Moonlight/App/Services/WebSpaceService.cs +++ /dev/null @@ -1,191 +0,0 @@ -using Logging.Net; -using Microsoft.EntityFrameworkCore; -using Moonlight.App.ApiClients.CloudPanel; -using Moonlight.App.ApiClients.CloudPanel.Requests; -using Moonlight.App.Database.Entities; -using Moonlight.App.Exceptions; -using Moonlight.App.Helpers; -using Moonlight.App.Helpers.Files; -using Moonlight.App.Models.Plesk.Requests; -using Moonlight.App.Models.Plesk.Resources; -using Moonlight.App.Repositories; -using FileAccess = Moonlight.App.Helpers.Files.FileAccess; - -namespace Moonlight.App.Services; - -public class WebSpaceService -{ - private readonly Repository CloudPanelRepository; - private readonly Repository WebSpaceRepository; - private readonly Repository DatabaseRepository; - - private readonly CloudPanelApiHelper CloudPanelApiHelper; - - public WebSpaceService(Repository cloudPanelRepository, Repository webSpaceRepository, CloudPanelApiHelper cloudPanelApiHelper, Repository databaseRepository) - { - CloudPanelRepository = cloudPanelRepository; - WebSpaceRepository = webSpaceRepository; - CloudPanelApiHelper = cloudPanelApiHelper; - DatabaseRepository = databaseRepository; - } - - public async Task Create(string domain, User owner, CloudPanel? ps = null) - { - if (WebSpaceRepository.Get().Any(x => x.Domain == domain)) - throw new DisplayException("A website with this domain does already exist"); - - var cloudPanel = ps ?? CloudPanelRepository.Get().First(); - - var ftpLogin = domain.Replace(".", "_"); - var ftpPassword = StringHelper.GenerateString(16); - - var phpVersion = "8.1"; // TODO: Add config option or smth - - var w = new WebSpace() - { - CloudPanel = cloudPanel, - Owner = owner, - Domain = domain, - UserName = ftpLogin, - Password = ftpPassword, - VHostTemplate = "Generic" //TODO: Implement as select option - }; - - var webSpace = WebSpaceRepository.Add(w); - - try - { - await CloudPanelApiHelper.Post(cloudPanel, "site/php", new AddPhpSite() - { - VHostTemplate = w.VHostTemplate, - DomainName = w.Domain, - PhpVersion = phpVersion, - SiteUser = w.UserName, - SiteUserPassword = w.Password - }); - } - catch (Exception) - { - WebSpaceRepository.Delete(webSpace); - throw; - } - - return webSpace; - } - - public async Task Delete(WebSpace w) - { - var website = EnsureData(w); - - await CloudPanelApiHelper.Delete(website.CloudPanel, $"site/{website.Domain}", null); - - WebSpaceRepository.Delete(website); - } - - public async Task IsHostUp(CloudPanel cloudPanel) - { - try - { - await CloudPanelApiHelper.Post(cloudPanel, "", null); - - return true; - } - catch (CloudPanelException e) - { - if (e.StatusCode == 404) - return true; - } - catch (Exception) - { - // ignored - } - - return false; - } - - public async Task IsHostUp(WebSpace w) - { - var webSpace = EnsureData(w); - - return await IsHostUp(webSpace.CloudPanel); - } - - public async Task IssueSslCertificate(WebSpace w) - { - var webspace = EnsureData(w); - - await CloudPanelApiHelper.Post(webspace.CloudPanel, "letsencrypt/install/certificate", new InstallLetsEncrypt() - { - DomainName = webspace.Domain - }); - } - - #region Databases - - public Task GetDatabases(WebSpace w) - { - return Task.FromResult(WebSpaceRepository - .Get() - .Include(x => x.Databases) - .First(x => x.Id == w.Id) - .Databases.ToArray()); - } - - public async Task CreateDatabase(WebSpace w, string name, string password) - { - if (DatabaseRepository.Get().Any(x => x.UserName == name)) - throw new DisplayException("A database with this name does already exist"); - - var webspace = EnsureData(w); - - var database = new MySqlDatabase() - { - UserName = name, - Password = password - }; - - await CloudPanelApiHelper.Post(webspace.CloudPanel, "db", new AddDatabase() - { - DomainName = webspace.Domain, - DatabaseName = database.UserName, - DatabaseUserName = database.UserName, - DatabaseUserPassword = database.Password - }); - - webspace.Databases.Add(database); - WebSpaceRepository.Update(webspace); - } - - public async Task DeleteDatabase(WebSpace w, MySqlDatabase database) - { - var webspace = EnsureData(w); - - await CloudPanelApiHelper.Delete(webspace.CloudPanel, $"db/{database.UserName}", null); - - webspace.Databases.Remove(database); - WebSpaceRepository.Update(webspace); - } - - #endregion - - public Task CreateFileAccess(WebSpace w) - { - var webspace = EnsureData(w); - - return Task.FromResult( - new SftpFileAccess(webspace.CloudPanel.Host, webspace.UserName, webspace.Password, 22, true) - ); - } - - private WebSpace EnsureData(WebSpace webSpace) - { - if (webSpace.CloudPanel == null || webSpace.Owner == null) - return WebSpaceRepository - .Get() - .Include(x => x.CloudPanel) - .Include(x => x.Owner) - .First(x => x.Id == webSpace.Id); - - return webSpace; - } -} \ No newline at end of file diff --git a/Moonlight/App/Services/WebsiteService.cs b/Moonlight/App/Services/WebsiteService.cs new file mode 100644 index 00000000..11906034 --- /dev/null +++ b/Moonlight/App/Services/WebsiteService.cs @@ -0,0 +1,383 @@ +using Logging.Net; +using Microsoft.EntityFrameworkCore; +using Moonlight.App.Database.Entities; +using Moonlight.App.Exceptions; +using Moonlight.App.Helpers; +using Moonlight.App.Helpers.Files; +using Moonlight.App.Models.Plesk.Requests; +using Moonlight.App.Models.Plesk.Resources; +using Moonlight.App.Repositories; +using FileAccess = Moonlight.App.Helpers.Files.FileAccess; + +namespace Moonlight.App.Services; + +public class WebsiteService +{ + private readonly WebsiteRepository WebsiteRepository; + private readonly PleskServerRepository PleskServerRepository; + private readonly PleskApiHelper PleskApiHelper; + private readonly UserRepository UserRepository; + + public WebsiteService(WebsiteRepository websiteRepository, PleskApiHelper pleskApiHelper, PleskServerRepository pleskServerRepository, UserRepository userRepository) + { + WebsiteRepository = websiteRepository; + PleskApiHelper = pleskApiHelper; + PleskServerRepository = pleskServerRepository; + UserRepository = userRepository; + } + + public async Task Create(string baseDomain, User owner, PleskServer? ps = null) + { + if (WebsiteRepository.Get().Any(x => x.BaseDomain == baseDomain)) + throw new DisplayException("A website with this domain does already exist"); + + var pleskServer = ps ?? PleskServerRepository.Get().First(); + + var ftpLogin = baseDomain; + var ftpPassword = StringHelper.GenerateString(16); + + var w = new Website() + { + PleskServer = pleskServer, + Owner = owner, + BaseDomain = baseDomain, + PleskId = 0, + FtpPassword = ftpPassword, + FtpLogin = ftpLogin + }; + + var website = WebsiteRepository.Add(w); + + try + { + var id = await GetAdminAccount(pleskServer); + + var result = await PleskApiHelper.Post(pleskServer, "domains", new CreateDomain() + { + Description = $"moonlight website {website.Id}", + Name = baseDomain, + HostingType = "virtual", + Plan = new() + { + Name = "Unlimited" + }, + HostingSettings = new() + { + FtpLogin = ftpLogin, + FtpPassword = ftpPassword + }, + OwnerClient = new() + { + Id = id + } + }); + + website.PleskId = result.Id; + + WebsiteRepository.Update(website); + } + catch (Exception e) + { + WebsiteRepository.Delete(website); + throw; + } + + return website; + } + + public async Task Delete(Website w) + { + var website = EnsureData(w); + + await PleskApiHelper.Delete(website.PleskServer, $"domains/{w.PleskId}", null); + + WebsiteRepository.Delete(website); + } + + public async Task IsHostUp(PleskServer pleskServer) + { + try + { + var res = await PleskApiHelper.Get(pleskServer, "server"); + + if (res != null) + return true; + } + catch (Exception e) + { + // ignored + } + + return false; + } + + public async Task IsHostUp(Website w) + { + var website = EnsureData(w); + + try + { + var res = await PleskApiHelper.Get(website.PleskServer, "server"); + + if (res != null) + return true; + } + catch (Exception) + { + // ignored + } + + return false; + } + + #region Get host + + public async Task GetHost(PleskServer pleskServer) + { + return (await PleskApiHelper.Get(pleskServer, "server")).Hostname; + } + + public async Task GetHost(Website w) + { + var website = EnsureData(w); + + return await GetHost(website.PleskServer); + } + + #endregion + + private async Task GetAdminAccount(PleskServer pleskServer) + { + var users = await PleskApiHelper.Get(pleskServer, "clients"); + + var user = users.FirstOrDefault(x => x.Type == "admin"); + + if (user == null) + throw new DisplayException("No admin account in plesk found"); + + return user.Id; + } + + #region SSL + public async Task GetSslCertificates(Website w) + { + var website = EnsureData(w); + var certs = new List(); + + var data = await ExecuteCli(website.PleskServer, "certificate", p => + { + p.Add("-l"); + p.Add("-domain"); + p.Add(w.BaseDomain); + }); + + string[] lines = data.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string line in lines) + { + if (line.Contains("Lets Encrypt")) + { + string[] parts = line.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + if(parts.Length > 6) + certs.Add($"{parts[4]} {parts[5]} {parts[6]}"); + } + else if (line.Contains("Listing of SSL/TLS certificates repository was successful")) + { + // This line indicates the end of the certificate listing, so we can stop parsing + break; + } + } + + return certs.ToArray(); + } + + public async Task CreateSslCertificate(Website w) + { + var website = EnsureData(w); + + await ExecuteCli(website.PleskServer, "extension", p => + { + p.Add("--exec"); + p.Add("letsencrypt"); + p.Add("cli.php"); + p.Add("-d"); + p.Add(website.BaseDomain); + p.Add("-m"); + p.Add(website.Owner.Email); + }); + } + + public async Task DeleteSslCertificate(Website w, string name) + { + var website = EnsureData(w); + + try + { + await ExecuteCli(website.PleskServer, "site", p => + { + p.Add("-u"); + p.Add(website.BaseDomain); + p.Add("-ssl"); + p.Add("false"); + }); + + try + { + await ExecuteCli(website.PleskServer, "certificate", p => + { + p.Add("--remove"); + p.Add(name); + p.Add("-domain"); + p.Add(website.BaseDomain); + }); + } + catch (Exception e) + { + Logger.Warn("Error removing ssl certificate"); + Logger.Warn(e); + + throw new DisplayException("An unknown error occured while removing ssl certificate"); + } + } + catch (DisplayException) + { + // Redirect all display exception to soft error handler + throw; + } + catch (Exception e) + { + Logger.Warn("Error disabling ssl certificate"); + Logger.Warn(e); + + throw new DisplayException("An unknown error occured while disabling ssl certificate"); + } + } + + #endregion + + #region Databases + + public async Task GetDatabases(Website w) + { + var website = EnsureData(w); + + var dbs = await PleskApiHelper.Get( + website.PleskServer, + $"databases?domain={w.BaseDomain}" + ); + + return dbs; + } + + public async Task CreateDatabase(Website w, string name, string password) + { + var website = EnsureData(w); + + var server = await GetDefaultDatabaseServer(website); + + if (server == null) + throw new DisplayException("No database server marked as default found"); + + var dbReq = new CreateDatabase() + { + Name = name, + Type = "mysql", + ParentDomain = new() + { + Name = website.BaseDomain + }, + ServerId = server.Id + }; + + var db = await PleskApiHelper.Post(website.PleskServer, "databases", dbReq); + + if (db == null) + throw new DisplayException("Unable to create database via api"); + + var dbUserReq = new CreateDatabaseUser() + { + DatabaseId = db.Id, + Login = name, + Password = password + }; + + await PleskApiHelper.Post(website.PleskServer, "dbusers", dbUserReq); + } + + public async Task DeleteDatabase(Website w, Models.Plesk.Resources.Database database) + { + var website = EnsureData(w); + + var dbUsers = await PleskApiHelper.Get( + website.PleskServer, + $"dbusers?dbId={database.Id}" + ); + + foreach (var dbUser in dbUsers) + { + await PleskApiHelper.Delete(website.PleskServer, $"dbusers/{dbUser.Id}", null); + } + + await PleskApiHelper.Delete(website.PleskServer, $"databases/{database.Id}", null); + } + + public async Task GetDefaultDatabaseServer(PleskServer pleskServer) + { + var dbServers = await PleskApiHelper.Get(pleskServer, "dbservers"); + + return dbServers.FirstOrDefault(x => x.IsDefault); + } + + public async Task GetDefaultDatabaseServer(Website w) + { + var website = EnsureData(w); + + return await GetDefaultDatabaseServer(website.PleskServer); + } + + #endregion + + public async Task CreateFileAccess(Website w) + { + var website = EnsureData(w); + var host = await GetHost(website.PleskServer); + + return new FtpFileAccess(host, 21, website.FtpLogin, website.FtpPassword); + } + + private async Task ExecuteCli( + PleskServer server, + string cli, Action>? parameters = null, + Action>? variables = null + ) + { + var p = new List(); + var v = new Dictionary(); + + parameters?.Invoke(p); + variables?.Invoke(v); + + var req = new CliCall() + { + Env = v, + Params = p + }; + + var res = await PleskApiHelper.Post(server, $"cli/{cli}/call", req); + + return res.Stdout; + } + + private Website EnsureData(Website website) + { + if (website.PleskServer == null || website.Owner == null) + return WebsiteRepository + .Get() + .Include(x => x.PleskServer) + .Include(x => x.Owner) + .First(x => x.Id == website.Id); + + return website; + } +} \ No newline at end of file diff --git a/Moonlight/Moonlight.csproj b/Moonlight/Moonlight.csproj index a0d9713d..22aba371 100644 --- a/Moonlight/Moonlight.csproj +++ b/Moonlight/Moonlight.csproj @@ -19,12 +19,10 @@ - - @@ -43,7 +41,6 @@ - @@ -70,7 +67,6 @@ - diff --git a/Moonlight/Pages/_Host.cshtml b/Moonlight/Pages/_Host.cshtml index 1eb715d7..7f5640de 100644 --- a/Moonlight/Pages/_Host.cshtml +++ b/Moonlight/Pages/_Host.cshtml @@ -1,54 +1,29 @@ @page "/" -@using Moonlight.App.Services @namespace Moonlight.Pages - -@inject SmartTranslateService SmartTranslateService - @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @{ Layout = "_Layout"; } - +
- +

+
+ Connecting to moonlight servers +

- +

+
+ Connection to moonlight servers failed +

- +

+
+ Connection to moonlight servers rejected +

-
\ No newline at end of file + diff --git a/Moonlight/Pages/_Layout.cshtml b/Moonlight/Pages/_Layout.cshtml index ca9c2287..7a5518e6 100644 --- a/Moonlight/Pages/_Layout.cshtml +++ b/Moonlight/Pages/_Layout.cshtml @@ -1,12 +1,9 @@ @using Microsoft.AspNetCore.Components.Web -@using Moonlight.App.Extensions -@using Moonlight.App.Repositories @using Moonlight.App.Services @namespace Moonlight.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @inject ConfigService ConfigService -@inject LoadingMessageRepository LoadingMessageRepository @{ var headerConfig = ConfigService @@ -54,7 +51,7 @@ - + Loading Logo - @{ - var loadingMessage = LoadingMessageRepository.Get().Random(); - } -
- @(loadingMessage.Message) + CHANGEME
@@ -100,18 +93,25 @@ + + + + + + + + + + + + - - - diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 7621c7bf..76e01893 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -2,9 +2,7 @@ using BlazorDownloadFile; using BlazorTable; using CurrieTechnologies.Razor.SweetAlert2; using Logging.Net; -using Moonlight.App.ApiClients.CloudPanel; using Moonlight.App.Database; -using Moonlight.App.Events; using Moonlight.App.Helpers; using Moonlight.App.LogMigrator; using Moonlight.App.Repositories; @@ -19,7 +17,7 @@ using Moonlight.App.Services.Notifications; using Moonlight.App.Services.OAuth2; using Moonlight.App.Services.Sessions; using Moonlight.App.Services.Statistics; -using Moonlight.App.Services.SupportChat; +using Moonlight.App.Services.Support; namespace Moonlight { @@ -43,13 +41,7 @@ namespace Moonlight // Add services to the container. builder.Services.AddRazorPages(); - builder.Services.AddServerSideBlazor() - .AddHubOptions(options => - { - options.MaximumReceiveMessageSize = 10000000; - options.ClientTimeoutInterval = TimeSpan.FromSeconds(30); - options.HandshakeTimeout = TimeSpan.FromSeconds(10); - }); + builder.Services.AddServerSideBlazor(); builder.Services.AddHttpContextAccessor(); // Databases @@ -62,20 +54,23 @@ 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(); builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(typeof(Repository<>)); // Services builder.Services.AddSingleton(); @@ -90,6 +85,7 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddSingleton(); builder.Services.AddScoped(); @@ -101,13 +97,8 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -115,6 +106,8 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddSingleton(); + // Loggers builder.Services.AddScoped(); builder.Services.AddScoped(); @@ -123,10 +116,10 @@ namespace Moonlight builder.Services.AddScoped(); builder.Services.AddSingleton(); - // Support chat - builder.Services.AddSingleton(); - builder.Services.AddScoped(); - builder.Services.AddScoped(); + // Support + builder.Services.AddSingleton(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); // Helpers builder.Services.AddSingleton(); @@ -137,13 +130,11 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddSingleton(); builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddScoped(); // Background services builder.Services.AddSingleton(); builder.Services.AddSingleton(); - builder.Services.AddSingleton(); - builder.Services.AddSingleton(); // Third party services builder.Services.AddBlazorTable(); @@ -169,12 +160,14 @@ namespace Moonlight app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); - + + // Support service + var supportServerService = app.Services.GetRequiredService(); + // AutoStart services _ = app.Services.GetRequiredService(); _ = app.Services.GetRequiredService(); _ = app.Services.GetRequiredService(); - _ = app.Services.GetRequiredService(); // Discord bot service //var discordBotService = app.Services.GetRequiredService(); diff --git a/Moonlight/Properties/launchSettings.json b/Moonlight/Properties/launchSettings.json index 49e61cf7..778ebef4 100644 --- a/Moonlight/Properties/launchSettings.json +++ b/Moonlight/Properties/launchSettings.json @@ -17,15 +17,12 @@ "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", "dotnetRunMessages": true }, - "Sql Debug": { - "commandName": "Project", + "IIS Express": { + "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "ML_SQL_DEBUG": "true" - }, - "applicationUrl": "http://moonlight.testy:5118;https://localhost:7118;http://localhost:5118", - "dotnetRunMessages": true + "ASPNETCORE_ENVIRONMENT": "Development" + } }, "Docker": { "commandName": "Docker", diff --git a/Moonlight/Shared/Components/ErrorBoundaries/SoftErrorBoundary.razor b/Moonlight/Shared/Components/ErrorBoundaries/SoftErrorBoundary.razor index bff6a292..3d59dd7c 100644 --- a/Moonlight/Shared/Components/ErrorBoundaries/SoftErrorBoundary.razor +++ b/Moonlight/Shared/Components/ErrorBoundaries/SoftErrorBoundary.razor @@ -2,7 +2,6 @@ @using Moonlight.App.Exceptions @using Moonlight.App.Services @using Logging.Net -@using Moonlight.App.ApiClients.CloudPanel @inherits ErrorBoundaryBase @inject AlertService AlertService @@ -58,16 +57,12 @@ else SmartTranslateService.Translate("Error from daemon"), wingsException.Message ); - - //TODO: Error log service - - Logger.Warn($"Wings exception status code: {wingsException.StatusCode}"); } - else if (exception is CloudPanelException cloudPanelException) + else if (exception is PleskException pleskException) { await AlertService.Error( - SmartTranslateService.Translate("Error from cloud panel"), - cloudPanelException.Message + SmartTranslateService.Translate("Error from plesk"), + pleskException.Message ); } else if (exception is NotImplementedException) diff --git a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor index 0c584993..9af01b0f 100644 --- a/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor +++ b/Moonlight/Shared/Components/FileManagerPartials/FileEditor.razor @@ -71,7 +71,7 @@ { if (firstRender) { - await JsRuntime.InvokeVoidAsync("moonlight.loading.loadMonaco"); + await JsRuntime.InvokeVoidAsync("initMonacoTheme"); Editor.OnDidInit = new EventCallback(this, async () => { diff --git a/Moonlight/Shared/Components/FileManagerPartials/FilePath.razor b/Moonlight/Shared/Components/FileManagerPartials/FilePath.razor index 4492bfcf..93982da1 100644 --- a/Moonlight/Shared/Components/FileManagerPartials/FilePath.razor +++ b/Moonlight/Shared/Components/FileManagerPartials/FilePath.razor @@ -1,5 +1,4 @@ @using Moonlight.App.Helpers.Files -@using Logging.Net
diff --git a/Moonlight/Shared/Components/FileManagerPartials/FileView.razor b/Moonlight/Shared/Components/FileManagerPartials/FileView.razor index 0e889e8a..dcf0a346 100644 --- a/Moonlight/Shared/Components/FileManagerPartials/FileView.razor +++ b/Moonlight/Shared/Components/FileManagerPartials/FileView.razor @@ -35,90 +35,88 @@ - + + + + + + + @foreach (var file in Data) + { - + - @foreach (var file in Data) - { - - - - - - - } - + } @@ -140,13 +138,12 @@ @code { - [Parameter] public FileAccess Access { get; set; } [Parameter] public Func>? OnElementClicked { get; set; } - + [Parameter] public Func? OnSelectionChanged { get; set; } @@ -158,7 +155,7 @@ [Parameter] public bool DisableScrolling { get; set; } = false; - + [Parameter] public Func? Filter { get; set; } @@ -172,19 +169,15 @@ private Dictionary ToggleStatusCache = new(); private bool AllToggled = false; - private ContentBlock ContentBlock; - public async Task Refresh() { - ContentBlock?.SetBlocking(true); - var list = new List(); - + foreach (var fileData in await Access.Ls()) { if (Filter != null) { - if (Filter.Invoke(fileData)) + if(Filter.Invoke(fileData)) list.Add(fileData); } else @@ -192,7 +185,7 @@ } Data = list.ToArray(); - + ToggleStatusCache.Clear(); AllToggled = false; @@ -203,8 +196,6 @@ await InvokeAsync(StateHasChanged); OnSelectionChanged?.Invoke(); - - ContentBlock?.SetBlocking(false); } private async Task Load(LazyLoader arg) @@ -266,7 +257,7 @@ if (canceled) return; } - + await Access.Up(); await Refresh(); } @@ -282,4 +273,4 @@ return Task.CompletedTask; } - } \ No newline at end of file +} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Navigations/AdminWebspacesNavigation.razor b/Moonlight/Shared/Components/Navigations/AdminWebsitesNavigation.razor similarity index 72% rename from Moonlight/Shared/Components/Navigations/AdminWebspacesNavigation.razor rename to Moonlight/Shared/Components/Navigations/AdminWebsitesNavigation.razor index b7380cc2..40b98026 100644 --- a/Moonlight/Shared/Components/Navigations/AdminWebspacesNavigation.razor +++ b/Moonlight/Shared/Components/Navigations/AdminWebsitesNavigation.razor @@ -2,13 +2,13 @@
diff --git a/Moonlight/Shared/Components/Partials/ContentBlock.razor b/Moonlight/Shared/Components/Partials/ContentBlock.razor deleted file mode 100644 index c987da71..00000000 --- a/Moonlight/Shared/Components/Partials/ContentBlock.razor +++ /dev/null @@ -1,52 +0,0 @@ -@if (AllowContentOverride) -{ - if (IsBlocking) - { -
-
- @(ChildContent) -
-
-
-
-
-
- } - else - { - @ChildContent - } -} -else -{ -
-
- @(ChildContent) -
- @if (IsBlocking) - { -
-
-
-
- } -
-} - -@code -{ - [Parameter] - public RenderFragment ChildContent { get; set; } - - [Parameter] - public bool AllowContentOverride { get; set; } = false; - - private bool IsBlocking = false; - - public async Task SetBlocking(bool b) - { - IsBlocking = b; - - await InvokeAsync(StateHasChanged); - } -} \ No newline at end of file diff --git a/Moonlight/Shared/Components/Partials/Navbar.razor b/Moonlight/Shared/Components/Partials/Navbar.razor index 79fe3f9d..f0f01e56 100644 --- a/Moonlight/Shared/Components/Partials/Navbar.razor +++ b/Moonlight/Shared/Components/Partials/Navbar.razor @@ -9,36 +9,33 @@ @inject NavigationManager NavigationManager @inject CookieService CookieService -@if (User != null) -{ -