Merge pull request #46 from Moonlight-Panel/PleskIntegration
Plesk integration
This commit is contained in:
commit
9188323594
56 changed files with 4290 additions and 74 deletions
|
@ -39,6 +39,8 @@ public class DataContext : DbContext
|
||||||
public DbSet<NotificationAction> NotificationActions { get; set; }
|
public DbSet<NotificationAction> NotificationActions { get; set; }
|
||||||
public DbSet<DdosAttack> DdosAttacks { get; set; }
|
public DbSet<DdosAttack> DdosAttacks { get; set; }
|
||||||
public DbSet<Subscription> Subscriptions { get; set; }
|
public DbSet<Subscription> Subscriptions { get; set; }
|
||||||
|
public DbSet<PleskServer> PleskServers { get; set; }
|
||||||
|
public DbSet<Website> Websites { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|
9
Moonlight/App/Database/Entities/PleskServer.cs
Normal file
9
Moonlight/App/Database/Entities/PleskServer.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
public class PleskServer
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string ApiUrl { get; set; } = "";
|
||||||
|
public string ApiKey { get; set; } = "";
|
||||||
|
}
|
12
Moonlight/App/Database/Entities/Website.cs
Normal file
12
Moonlight/App/Database/Entities/Website.cs
Normal file
|
@ -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; } = "";
|
||||||
|
}
|
946
Moonlight/App/Database/Migrations/20230404181522_AddedPleskAndWebsiteModels.Designer.cs
generated
Normal file
946
Moonlight/App/Database/Migrations/20230404181522_AddedPleskAndWebsiteModels.Designer.cs
generated
Normal file
|
@ -0,0 +1,946 @@
|
||||||
|
// <auto-generated />
|
||||||
|
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("20230404181522_AddedPleskAndWebsiteModels")]
|
||||||
|
partial class AddedPleskAndWebsiteModels
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
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.DdosAttack", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<long>("Data")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ongoing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.ToTable("DdosAttacks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Default")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("DockerImages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Allocations")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConfigFiles")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallDockerImage")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallEntrypoint")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallScript")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Startup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StartupDetection")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StopCommand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TagsJson")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Images");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ImageTags");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("DefaultValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LoadingMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AuditLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Class")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Stacktrace")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ErrorLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SecurityLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Fqdn")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("HttpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MoonlightDaemonPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("SftpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ssl")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Token")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TokenId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Nodes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Port")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Action")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationClientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NotificationClientId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationActions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ApiKey")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ApiUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PleskServers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Identifier")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Revokes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Disk")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("DockerImageIndex")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Installing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsCleanupException")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("MainAllocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Memory")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("OverrideStartup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Suspended")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<Guid>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Bytes")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Created")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerBackups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SharedDomain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("CloudflareId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SharedDomains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LimitsJson")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Answer")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsQuestion")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSupport")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSystem")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("RecipientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SenderId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("Admin")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<int?>("CurrentSubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("DiscordId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SubscriptionDuration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubscriptionSince")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("SupportPending")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TokenValidTime")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("TotpEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("TotpSecret")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentSubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("BaseDomain")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PleskId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("NodeId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NotificationClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("NotificationClient");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MainAllocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NodeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
|
||||||
|
b.Navigation("MainAllocation");
|
||||||
|
|
||||||
|
b.Navigation("Node");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Backups")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Recipient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RecipientId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Sender")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SenderId");
|
||||||
|
|
||||||
|
b.Navigation("Recipient");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", "CurrentSubscription")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentSubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("CurrentSubscription");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.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");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedPleskAndWebsiteModels : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "PleskServers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ApiUrl = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
ApiKey = table.Column<string>(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<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
BaseDomain = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
PleskId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
PleskServerId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
OwnerId = table.Column<int>(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");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Websites");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "PleskServers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
954
Moonlight/App/Database/Migrations/20230405162507_UpdatedWebsiteModel.Designer.cs
generated
Normal file
954
Moonlight/App/Database/Migrations/20230405162507_UpdatedWebsiteModel.Designer.cs
generated
Normal file
|
@ -0,0 +1,954 @@
|
||||||
|
// <auto-generated />
|
||||||
|
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("20230405162507_UpdatedWebsiteModel")]
|
||||||
|
partial class UpdatedWebsiteModel
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
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.DdosAttack", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<long>("Data")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ongoing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NodeId");
|
||||||
|
|
||||||
|
b.ToTable("DdosAttacks");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Default")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("DockerImages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Domain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Allocations")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ConfigFiles")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallDockerImage")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallEntrypoint")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("InstallScript")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Startup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StartupDetection")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("StopCommand")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TagsJson")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Images");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageTag", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ImageTags");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ImageVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("DefaultValue")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ImageId");
|
||||||
|
|
||||||
|
b.ToTable("ImageVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LoadingMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("LoadingMessages");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.AuditLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AuditLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.ErrorLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Class")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Stacktrace")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ErrorLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.LogsEntries.SecurityLogEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Ip")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("JsonData")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("System")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("Type")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SecurityLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Node", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Fqdn")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("HttpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MoonlightDaemonPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("SftpPort")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Ssl")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Token")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("TokenId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Nodes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Port")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Action")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationClientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NotificationClientId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationActions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("UserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationClients");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ApiKey")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ApiUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PleskServers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Identifier")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Revokes");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Cpu")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Disk")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("DockerImageIndex")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("ImageId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Installing")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsCleanupException")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<int>("MainAllocationId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Memory")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("NodeId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("OverrideStartup")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<bool>("Suspended")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<Guid>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Bytes")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<bool>("Created")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<Guid>("Uuid")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerBackups");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Key")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("ServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Value")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ServerId");
|
||||||
|
|
||||||
|
b.ToTable("ServerVariables");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SharedDomain", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("CloudflareId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SharedDomains");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Subscription", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LimitsJson")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Subscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Answer")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsQuestion")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSupport")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsSystem")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Message")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int?>("RecipientId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("SenderId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Address")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("Admin")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("City")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Country")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<int?>("CurrentSubscriptionId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("DiscordId")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FirstName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("LastName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Password")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("State")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("Status")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SubscriptionDuration")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("SubscriptionSince")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("SupportPending")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("TokenValidTime")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("TotpEnabled")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("TotpSecret")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CurrentSubscriptionId");
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("BaseDomain")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FtpLogin")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FtpPassword")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PleskId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("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.NodeAllocation", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("NodeId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Allocations")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationAction", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Notification.NotificationClient", "NotificationClient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NotificationClientId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("NotificationClient");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Notification.NotificationClient", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("User");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Server", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Image", "Image")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ImageId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.NodeAllocation", "MainAllocation")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("MainAllocationId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NodeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("OwnerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Image");
|
||||||
|
|
||||||
|
b.Navigation("MainAllocation");
|
||||||
|
|
||||||
|
b.Navigation("Node");
|
||||||
|
|
||||||
|
b.Navigation("Owner");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerBackup", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Backups")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.ServerVariable", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Server", null)
|
||||||
|
.WithMany("Variables")
|
||||||
|
.HasForeignKey("ServerId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.SupportMessage", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Recipient")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RecipientId");
|
||||||
|
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.User", "Sender")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("SenderId");
|
||||||
|
|
||||||
|
b.Navigation("Recipient");
|
||||||
|
|
||||||
|
b.Navigation("Sender");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.User", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Subscription", "CurrentSubscription")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrentSubscriptionId");
|
||||||
|
|
||||||
|
b.Navigation("CurrentSubscription");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.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");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class UpdatedWebsiteModel : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "FtpLogin",
|
||||||
|
table: "Websites",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "FtpPassword",
|
||||||
|
table: "Websites",
|
||||||
|
type: "longtext",
|
||||||
|
nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "FtpLogin",
|
||||||
|
table: "Websites");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "FtpPassword",
|
||||||
|
table: "Websites");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -395,6 +395,29 @@ namespace Moonlight.App.Database.Migrations
|
||||||
b.ToTable("NotificationClients");
|
b.ToTable("NotificationClients");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.PleskServer", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ApiKey")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("ApiUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PleskServers");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Revoke", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
@ -697,6 +720,42 @@ namespace Moonlight.App.Database.Migrations
|
||||||
b.ToTable("Users");
|
b.ToTable("Users");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("BaseDomain")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FtpLogin")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("FtpPassword")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<int>("OwnerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PleskId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("PleskServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.HasIndex("PleskServerId");
|
||||||
|
|
||||||
|
b.ToTable("Websites");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
@ -847,6 +906,25 @@ namespace Moonlight.App.Database.Migrations
|
||||||
b.Navigation("CurrentSubscription");
|
b.Navigation("CurrentSubscription");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("DockerImages");
|
b.Navigation("DockerImages");
|
||||||
|
|
32
Moonlight/App/Exceptions/DaemonException.cs
Normal file
32
Moonlight/App/Exceptions/DaemonException.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Exceptions;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class DaemonException : Exception
|
||||||
|
{
|
||||||
|
public int StatusCode { private get; set; }
|
||||||
|
|
||||||
|
public DaemonException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DaemonException(string message, int statusCode) : base(message)
|
||||||
|
{
|
||||||
|
StatusCode = statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DaemonException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public DaemonException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected DaemonException(
|
||||||
|
SerializationInfo info,
|
||||||
|
StreamingContext context) : base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
32
Moonlight/App/Exceptions/PleskException.cs
Normal file
32
Moonlight/App/Exceptions/PleskException.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Exceptions;
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
public class PleskException : Exception
|
||||||
|
{
|
||||||
|
public int StatusCode { private get; set; }
|
||||||
|
|
||||||
|
public PleskException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PleskException(string message, int statusCode) : base(message)
|
||||||
|
{
|
||||||
|
StatusCode = statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PleskException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public PleskException(string message, Exception inner) : base(message, inner)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PleskException(
|
||||||
|
SerializationInfo info,
|
||||||
|
StreamingContext context) : base(info, context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,7 +37,7 @@ public class DaemonApiHelper
|
||||||
{
|
{
|
||||||
if (response.StatusCode != 0)
|
if (response.StatusCode != 0)
|
||||||
{
|
{
|
||||||
throw new WingsException(
|
throw new DaemonException(
|
||||||
$"An error occured: ({response.StatusCode}) {response.Content}",
|
$"An error occured: ({response.StatusCode}) {response.Content}",
|
||||||
(int)response.StatusCode
|
(int)response.StatusCode
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using FluentFTP;
|
using FluentFTP;
|
||||||
|
using Moonlight.App.Exceptions;
|
||||||
|
|
||||||
namespace Moonlight.App.Helpers.Files;
|
namespace Moonlight.App.Helpers.Files;
|
||||||
|
|
||||||
|
@ -78,10 +79,10 @@ public class FtpFileAccess : FileAccess
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
await EnsureConnect();
|
||||||
|
|
||||||
var s = new MemoryStream();
|
var s = new MemoryStream(8 * 1024 * 1204); //TODO: Add config option
|
||||||
await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name);
|
await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name);
|
||||||
var data = s.ToArray();
|
var data = s.ToArray();
|
||||||
s.Dispose();
|
await s.DisposeAsync();
|
||||||
var str = Encoding.UTF8.GetString(data);
|
var str = Encoding.UTF8.GetString(data);
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -90,11 +91,11 @@ public class FtpFileAccess : FileAccess
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
await EnsureConnect();
|
||||||
|
|
||||||
var s = new MemoryStream();
|
var s = new MemoryStream(8 * 1024 * 1204); //TODO: Add config option
|
||||||
s.Write(Encoding.UTF8.GetBytes(content));
|
s.Write(Encoding.UTF8.GetBytes(content));
|
||||||
s.Position = 0;
|
s.Position = 0;
|
||||||
await Client.UploadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name, FtpRemoteExists.Overwrite);
|
await Client.UploadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name, FtpRemoteExists.Overwrite);
|
||||||
s.Dispose();
|
await s.DisposeAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Upload(string name, Stream dataStream, Action<int>? progressUpdated = null)
|
public override async Task Upload(string name, Stream dataStream, Action<int>? progressUpdated = null)
|
||||||
|
@ -103,10 +104,9 @@ public class FtpFileAccess : FileAccess
|
||||||
|
|
||||||
IProgress<FtpProgress> progress = new Progress<FtpProgress>(x =>
|
IProgress<FtpProgress> progress = new Progress<FtpProgress>(x =>
|
||||||
{
|
{
|
||||||
progressUpdated((int) x.Progress);
|
progressUpdated?.Invoke((int)x.Progress);
|
||||||
});
|
});
|
||||||
await Client.UploadStream(dataStream, CurrentPath.TrimEnd('/') + "/" + name, FtpRemoteExists.Overwrite, false, progress);
|
await Client.UploadStream(dataStream, CurrentPath.TrimEnd('/') + "/" + name, FtpRemoteExists.Overwrite, false, progress);
|
||||||
dataStream.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task MkDir(string name)
|
public override async Task MkDir(string name)
|
||||||
|
@ -121,10 +121,8 @@ public class FtpFileAccess : FileAccess
|
||||||
return Task.FromResult(CurrentPath);
|
return Task.FromResult(CurrentPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<string> DownloadUrl(FileData fileData)
|
public override Task<string> DownloadUrl(FileData fileData)
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,8 +130,12 @@ public class FtpFileAccess : FileAccess
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
await EnsureConnect();
|
||||||
|
|
||||||
var s = new MemoryStream();
|
var s = new MemoryStream(8 * 1024 * 1204); //TODO: Add config option
|
||||||
await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name);
|
var downloaded = await Client.DownloadStream(s, CurrentPath.TrimEnd('/') + "/" + fileData.Name);
|
||||||
|
|
||||||
|
if (!downloaded)
|
||||||
|
throw new DisplayException("Unable to download file");
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,17 +159,13 @@ public class FtpFileAccess : FileAccess
|
||||||
await Client.MoveDirectory(CurrentPath.TrimEnd('/') + "/" + fileData.Name, newPath);
|
await Client.MoveDirectory(CurrentPath.TrimEnd('/') + "/" + fileData.Name, newPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Compress(params FileData[] files)
|
public override Task Compress(params FileData[] files)
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task Decompress(FileData fileData)
|
public override Task Decompress(FileData fileData)
|
||||||
{
|
{
|
||||||
await EnsureConnect();
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
220
Moonlight/App/Helpers/PleskApiHelper.cs
Normal file
220
Moonlight/App/Helpers/PleskApiHelper.cs
Normal file
|
@ -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<T> Get<T>(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<T>(response.Content!)!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> 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<T> Post<T>(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<T>(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;
|
||||||
|
}
|
||||||
|
}
|
17
Moonlight/App/Models/Forms/DatabaseDataModel.cs
Normal file
17
Moonlight/App/Models/Forms/DatabaseDataModel.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Forms;
|
||||||
|
|
||||||
|
public class DatabaseDataModel
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "You need to enter a name")]
|
||||||
|
[MinLength(8, ErrorMessage = "The name should be at least 8 characters long")]
|
||||||
|
[MaxLength(32, ErrorMessage = "The database name should be maximal 32 characters")]
|
||||||
|
[RegularExpression(@"^[a-z0-9]+$", ErrorMessage = "The name should only contain of lower case characters and numbers")]
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "You need to enter a password")]
|
||||||
|
[MinLength(8, ErrorMessage = "The password should be at least 8 characters long")]
|
||||||
|
[MaxLength(32, ErrorMessage = "The password name should be maximal 32 characters")]
|
||||||
|
public string Password { get; set; } = "";
|
||||||
|
}
|
16
Moonlight/App/Models/Forms/PleskServerDataModel.cs
Normal file
16
Moonlight/App/Models/Forms/PleskServerDataModel.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Forms;
|
||||||
|
|
||||||
|
public class PleskServerDataModel
|
||||||
|
{
|
||||||
|
[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 enter an api url")]
|
||||||
|
public string ApiUrl { get; set; }
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "You need to enter an api key")]
|
||||||
|
public string ApiKey { get; set; }
|
||||||
|
}
|
14
Moonlight/App/Models/Forms/WebsiteAdminDataModel.cs
Normal file
14
Moonlight/App/Models/Forms/WebsiteAdminDataModel.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Forms;
|
||||||
|
|
||||||
|
public class WebsiteAdminDataModel
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "You need a domain")]
|
||||||
|
[RegularExpression(@"([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+", ErrorMessage = "You need to enter a valid domain")]
|
||||||
|
public string BaseDomain { get; set; } = "";
|
||||||
|
|
||||||
|
[Required(ErrorMessage = "You need to specify a owner")]
|
||||||
|
public User User { get; set; }
|
||||||
|
}
|
10
Moonlight/App/Models/Forms/WebsiteDataModel.cs
Normal file
10
Moonlight/App/Models/Forms/WebsiteDataModel.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Forms;
|
||||||
|
|
||||||
|
public class WebsiteDataModel
|
||||||
|
{
|
||||||
|
[Required(ErrorMessage = "You need a domain")]
|
||||||
|
[RegularExpression(@"([a-z0-9|-]+\.)*[a-z0-9|-]+\.[a-z]+", ErrorMessage = "You need to enter a valid domain")]
|
||||||
|
public string BaseDomain { get; set; } = "";
|
||||||
|
}
|
10
Moonlight/App/Models/Plesk/Requests/CliCall.cs
Normal file
10
Moonlight/App/Models/Plesk/Requests/CliCall.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Requests;
|
||||||
|
|
||||||
|
public class CliCall
|
||||||
|
{
|
||||||
|
[JsonProperty("params")] public List<string> Params { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonProperty("env")] public Dictionary<string, string> Env { get; set; } = new();
|
||||||
|
}
|
23
Moonlight/App/Models/Plesk/Requests/CreateDatabase.cs
Normal file
23
Moonlight/App/Models/Plesk/Requests/CreateDatabase.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Requests;
|
||||||
|
|
||||||
|
public class CreateDatabase
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("parent_domain")] public ParentDomainModel ParentDomain { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonProperty("server_id")]
|
||||||
|
public int ServerId { get; set; }
|
||||||
|
|
||||||
|
public class ParentDomainModel
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
15
Moonlight/App/Models/Plesk/Requests/CreateDatabaseUser.cs
Normal file
15
Moonlight/App/Models/Plesk/Requests/CreateDatabaseUser.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Requests;
|
||||||
|
|
||||||
|
public class CreateDatabaseUser
|
||||||
|
{
|
||||||
|
[JsonProperty("login")]
|
||||||
|
public string Login { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("password")]
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("database_id")]
|
||||||
|
public int DatabaseId { get; set; }
|
||||||
|
}
|
45
Moonlight/App/Models/Plesk/Requests/CreateDomain.cs
Normal file
45
Moonlight/App/Models/Plesk/Requests/CreateDomain.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Requests;
|
||||||
|
|
||||||
|
public class CreateDomain
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("hosting_type")]
|
||||||
|
public string HostingType { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("hosting_settings")]
|
||||||
|
public HostingSettingsModel HostingSettings { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("owner_client")]
|
||||||
|
public OwnerClientModel OwnerClient { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("plan")]
|
||||||
|
public PlanModel Plan { get; set; }
|
||||||
|
|
||||||
|
public partial class HostingSettingsModel
|
||||||
|
{
|
||||||
|
[JsonProperty("ftp_login")]
|
||||||
|
public string FtpLogin { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("ftp_password")]
|
||||||
|
public string FtpPassword { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class OwnerClientModel
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public long Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class PlanModel
|
||||||
|
{
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
}
|
13
Moonlight/App/Models/Plesk/Resources/CliResult.cs
Normal file
13
Moonlight/App/Models/Plesk/Resources/CliResult.cs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class CliResult
|
||||||
|
{
|
||||||
|
[JsonProperty("code")]
|
||||||
|
public int Code { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("stdout")] public string Stdout { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonProperty("stderr")] public string Stderr { get; set; } = "";
|
||||||
|
}
|
45
Moonlight/App/Models/Plesk/Resources/Client.cs
Normal file
45
Moonlight/App/Models/Plesk/Resources/Client.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class Client
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("created")]
|
||||||
|
public DateTimeOffset Created { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("company")]
|
||||||
|
public string Company { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("login")]
|
||||||
|
public string Login { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public long Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("email")]
|
||||||
|
public string Email { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("locale")]
|
||||||
|
public string Locale { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("guid")]
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("owner_login")]
|
||||||
|
public string OwnerLogin { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("external_id")]
|
||||||
|
public string ExternalId { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("description")]
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
12
Moonlight/App/Models/Plesk/Resources/CreateResult.cs
Normal file
12
Moonlight/App/Models/Plesk/Resources/CreateResult.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class CreateResult
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("guid")]
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
}
|
15
Moonlight/App/Models/Plesk/Resources/Database.cs
Normal file
15
Moonlight/App/Models/Plesk/Resources/Database.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class Database
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
30
Moonlight/App/Models/Plesk/Resources/DatabaseServer.cs
Normal file
30
Moonlight/App/Models/Plesk/Resources/DatabaseServer.cs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class DatabaseServer
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("host")]
|
||||||
|
public string Host { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("port")]
|
||||||
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("type")]
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("status")]
|
||||||
|
public string Status { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("db_count")]
|
||||||
|
public int DbCount { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_default")]
|
||||||
|
public bool IsDefault { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("is_local")]
|
||||||
|
public bool IsLocal { get; set; }
|
||||||
|
}
|
15
Moonlight/App/Models/Plesk/Resources/DatabaseUser.cs
Normal file
15
Moonlight/App/Models/Plesk/Resources/DatabaseUser.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class DatabaseUser
|
||||||
|
{
|
||||||
|
[JsonProperty("id")]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("login")]
|
||||||
|
public string Login { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("database_id")]
|
||||||
|
public int DatabaseId { get; set; }
|
||||||
|
}
|
18
Moonlight/App/Models/Plesk/Resources/ServerStatus.cs
Normal file
18
Moonlight/App/Models/Plesk/Resources/ServerStatus.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Models.Plesk.Resources;
|
||||||
|
|
||||||
|
public class ServerStatus
|
||||||
|
{
|
||||||
|
[JsonProperty("platform")]
|
||||||
|
public string Platform { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("hostname")]
|
||||||
|
public string Hostname { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("guid")]
|
||||||
|
public Guid Guid { get; set; }
|
||||||
|
|
||||||
|
[JsonProperty("panel_version")]
|
||||||
|
public string PanelVersion { get; set; }
|
||||||
|
}
|
44
Moonlight/App/Repositories/PleskServerRepository.cs
Normal file
44
Moonlight/App/Repositories/PleskServerRepository.cs
Normal file
|
@ -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<PleskServer> 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();
|
||||||
|
}
|
||||||
|
}
|
44
Moonlight/App/Repositories/WebsiteRepository.cs
Normal file
44
Moonlight/App/Repositories/WebsiteRepository.cs
Normal file
|
@ -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<Website> 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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,4 +41,22 @@ public class NodeService
|
||||||
{
|
{
|
||||||
return await DaemonApiHelper.Get<ContainerStats>(node, "stats/container");
|
return await DaemonApiHelper.Get<ContainerStats>(node, "stats/container");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsHostUp(Node node)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
//TODO: Implement status caching
|
||||||
|
var data = await GetStatus(node);
|
||||||
|
|
||||||
|
if (data != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,6 +29,7 @@ public class ServerService
|
||||||
private readonly SecurityLogService SecurityLogService;
|
private readonly SecurityLogService SecurityLogService;
|
||||||
private readonly AuditLogService AuditLogService;
|
private readonly AuditLogService AuditLogService;
|
||||||
private readonly ErrorLogService ErrorLogService;
|
private readonly ErrorLogService ErrorLogService;
|
||||||
|
private readonly NodeService NodeService;
|
||||||
|
|
||||||
public ServerService(
|
public ServerService(
|
||||||
ServerRepository serverRepository,
|
ServerRepository serverRepository,
|
||||||
|
@ -42,7 +43,8 @@ public class ServerService
|
||||||
WingsJwtHelper wingsJwtHelper,
|
WingsJwtHelper wingsJwtHelper,
|
||||||
SecurityLogService securityLogService,
|
SecurityLogService securityLogService,
|
||||||
AuditLogService auditLogService,
|
AuditLogService auditLogService,
|
||||||
ErrorLogService errorLogService)
|
ErrorLogService errorLogService,
|
||||||
|
NodeService nodeService)
|
||||||
{
|
{
|
||||||
ServerRepository = serverRepository;
|
ServerRepository = serverRepository;
|
||||||
WingsApiHelper = wingsApiHelper;
|
WingsApiHelper = wingsApiHelper;
|
||||||
|
@ -56,6 +58,7 @@ public class ServerService
|
||||||
SecurityLogService = securityLogService;
|
SecurityLogService = securityLogService;
|
||||||
AuditLogService = auditLogService;
|
AuditLogService = auditLogService;
|
||||||
ErrorLogService = errorLogService;
|
ErrorLogService = errorLogService;
|
||||||
|
NodeService = nodeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Server EnsureNodeData(Server s)
|
private Server EnsureNodeData(Server s)
|
||||||
|
@ -252,16 +255,14 @@ public class ServerService
|
||||||
Node node;
|
Node node;
|
||||||
|
|
||||||
if (n == null)
|
if (n == null)
|
||||||
{
|
|
||||||
node = NodeRepository.Get().Include(x => x.Allocations).First(); //TODO: Smart deploy
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
node = NodeRepository
|
node = NodeRepository
|
||||||
.Get()
|
.Get()
|
||||||
.Include(x => x.Allocations)
|
.Include(x => x.Allocations)
|
||||||
.First(x => x.Id == n.Id);
|
.First(x => x.Id == n.Id);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
node = n;
|
||||||
|
|
||||||
NodeAllocation freeAllo;
|
NodeAllocation freeAllo;
|
||||||
|
|
||||||
|
@ -395,4 +396,11 @@ public class ServerService
|
||||||
|
|
||||||
ServerRepository.Delete(s);
|
ServerRepository.Delete(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsHostUp(Server s)
|
||||||
|
{
|
||||||
|
var server = EnsureNodeData(s);
|
||||||
|
|
||||||
|
return await NodeService.IsHostUp(server.Node);
|
||||||
|
}
|
||||||
}
|
}
|
383
Moonlight/App/Services/WebsiteService.cs
Normal file
383
Moonlight/App/Services/WebsiteService.cs
Normal file
|
@ -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<Website> 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<CreateResult>(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<bool> IsHostUp(PleskServer pleskServer)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = await PleskApiHelper.Get<ServerStatus>(pleskServer, "server");
|
||||||
|
|
||||||
|
if (res != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<bool> IsHostUp(Website w)
|
||||||
|
{
|
||||||
|
var website = EnsureData(w);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var res = await PleskApiHelper.Get<ServerStatus>(website.PleskServer, "server");
|
||||||
|
|
||||||
|
if (res != null)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
// ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Get host
|
||||||
|
|
||||||
|
public async Task<string> GetHost(PleskServer pleskServer)
|
||||||
|
{
|
||||||
|
return (await PleskApiHelper.Get<ServerStatus>(pleskServer, "server")).Hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetHost(Website w)
|
||||||
|
{
|
||||||
|
var website = EnsureData(w);
|
||||||
|
|
||||||
|
return await GetHost(website.PleskServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private async Task<int> GetAdminAccount(PleskServer pleskServer)
|
||||||
|
{
|
||||||
|
var users = await PleskApiHelper.Get<Client[]>(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<string[]> GetSslCertificates(Website w)
|
||||||
|
{
|
||||||
|
var website = EnsureData(w);
|
||||||
|
var certs = new List<string>();
|
||||||
|
|
||||||
|
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<Models.Plesk.Resources.Database[]> GetDatabases(Website w)
|
||||||
|
{
|
||||||
|
var website = EnsureData(w);
|
||||||
|
|
||||||
|
var dbs = await PleskApiHelper.Get<Models.Plesk.Resources.Database[]>(
|
||||||
|
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<Models.Plesk.Resources.Database>(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<DatabaseUser[]>(
|
||||||
|
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<DatabaseServer?> GetDefaultDatabaseServer(PleskServer pleskServer)
|
||||||
|
{
|
||||||
|
var dbServers = await PleskApiHelper.Get<DatabaseServer[]>(pleskServer, "dbservers");
|
||||||
|
|
||||||
|
return dbServers.FirstOrDefault(x => x.IsDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<DatabaseServer?> GetDefaultDatabaseServer(Website w)
|
||||||
|
{
|
||||||
|
var website = EnsureData(w);
|
||||||
|
|
||||||
|
return await GetDefaultDatabaseServer(website.PleskServer);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public async Task<FileAccess> 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<string> ExecuteCli(
|
||||||
|
PleskServer server,
|
||||||
|
string cli, Action<List<string>>? parameters = null,
|
||||||
|
Action<Dictionary<string, string>>? variables = null
|
||||||
|
)
|
||||||
|
{
|
||||||
|
var p = new List<string>();
|
||||||
|
var v = new Dictionary<string, string>();
|
||||||
|
|
||||||
|
parameters?.Invoke(p);
|
||||||
|
variables?.Invoke(v);
|
||||||
|
|
||||||
|
var req = new CliCall()
|
||||||
|
{
|
||||||
|
Env = v,
|
||||||
|
Params = p
|
||||||
|
};
|
||||||
|
|
||||||
|
var res = await PleskApiHelper.Post<CliResult>(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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -60,8 +60,10 @@ namespace Moonlight
|
||||||
builder.Services.AddScoped<NotificationRepository>();
|
builder.Services.AddScoped<NotificationRepository>();
|
||||||
builder.Services.AddScoped<DdosAttackRepository>();
|
builder.Services.AddScoped<DdosAttackRepository>();
|
||||||
builder.Services.AddScoped<SubscriptionRepository>();
|
builder.Services.AddScoped<SubscriptionRepository>();
|
||||||
|
builder.Services.AddScoped<PleskServerRepository>();
|
||||||
|
builder.Services.AddScoped<WebsiteRepository>();
|
||||||
builder.Services.AddScoped<LoadingMessageRepository>();
|
builder.Services.AddScoped<LoadingMessageRepository>();
|
||||||
|
|
||||||
builder.Services.AddScoped<AuditLogEntryRepository>();
|
builder.Services.AddScoped<AuditLogEntryRepository>();
|
||||||
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
||||||
builder.Services.AddScoped<SecurityLogEntryRepository>();
|
builder.Services.AddScoped<SecurityLogEntryRepository>();
|
||||||
|
@ -90,6 +92,7 @@ namespace Moonlight
|
||||||
builder.Services.AddScoped<NotificationClientService>();
|
builder.Services.AddScoped<NotificationClientService>();
|
||||||
builder.Services.AddScoped<ModalService>();
|
builder.Services.AddScoped<ModalService>();
|
||||||
builder.Services.AddScoped<SmartDeployService>();
|
builder.Services.AddScoped<SmartDeployService>();
|
||||||
|
builder.Services.AddScoped<WebsiteService>();
|
||||||
|
|
||||||
builder.Services.AddScoped<GoogleOAuth2Service>();
|
builder.Services.AddScoped<GoogleOAuth2Service>();
|
||||||
builder.Services.AddScoped<DiscordOAuth2Service>();
|
builder.Services.AddScoped<DiscordOAuth2Service>();
|
||||||
|
@ -121,6 +124,7 @@ namespace Moonlight
|
||||||
builder.Services.AddSingleton<PaperApiHelper>();
|
builder.Services.AddSingleton<PaperApiHelper>();
|
||||||
builder.Services.AddSingleton<HostSystemHelper>();
|
builder.Services.AddSingleton<HostSystemHelper>();
|
||||||
builder.Services.AddScoped<DaemonApiHelper>();
|
builder.Services.AddScoped<DaemonApiHelper>();
|
||||||
|
builder.Services.AddScoped<PleskApiHelper>();
|
||||||
|
|
||||||
// Background services
|
// Background services
|
||||||
builder.Services.AddSingleton<DiscordBotService>();
|
builder.Services.AddSingleton<DiscordBotService>();
|
||||||
|
|
|
@ -36,6 +36,17 @@
|
||||||
wingsException.Message
|
wingsException.Message
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
else if (exception is PleskException pleskException)
|
||||||
|
{
|
||||||
|
await AlertService.Error(
|
||||||
|
SmartTranslateService.Translate("Error from plesk"),
|
||||||
|
pleskException.Message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if (exception is NotImplementedException)
|
||||||
|
{
|
||||||
|
await AlertService.Error(SmartTranslateService.Translate("This function is not implemented"));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw exception;
|
throw exception;
|
||||||
|
|
|
@ -166,8 +166,8 @@ else
|
||||||
{
|
{
|
||||||
var stream = await Access.DownloadStream(x);
|
var stream = await Access.DownloadStream(x);
|
||||||
await ToastService.Info(SmartTranslateService.Translate("Starting download"));
|
await ToastService.Info(SmartTranslateService.Translate("Starting download"));
|
||||||
await FileService.AddBuffer(stream);
|
stream.Position = 0;
|
||||||
await FileService.DownloadBinaryBuffers(x.Name);
|
await FileService.DownloadFile(fileName: x.Name, stream: stream, contentType: "application/octet-stream");
|
||||||
}
|
}
|
||||||
catch (NotImplementedException)
|
catch (NotImplementedException)
|
||||||
{
|
{
|
||||||
|
|
|
@ -35,12 +35,7 @@ else
|
||||||
{
|
{
|
||||||
if (Confirm)
|
if (Confirm)
|
||||||
{
|
{
|
||||||
var b = await AlertService.YesNo(
|
var b = await AlertService.ConfirmMath();
|
||||||
SmartTranslateService.Translate("Are you sure?"),
|
|
||||||
SmartTranslateService.Translate("Do you really want to delete it?"),
|
|
||||||
SmartTranslateService.Translate("Yes"),
|
|
||||||
SmartTranslateService.Translate("No")
|
|
||||||
);
|
|
||||||
|
|
||||||
if (b)
|
if (b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<div class="card mb-5 mb-xl-10">
|
||||||
|
<div class="card-body pt-0 pb-0">
|
||||||
|
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/websites">
|
||||||
|
<TL>Websites</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/websites/servers">
|
||||||
|
<TL>Plesk servers</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Index { get; set; } = 0;
|
||||||
|
}
|
|
@ -155,32 +155,13 @@ else
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div data-kt-menu-trigger="click" class="menu-item menu-accordion">
|
<div class="menu-item">
|
||||||
<span class="menu-link">
|
<a class="menu-link" href="/admin/websites">
|
||||||
<span class="menu-icon">
|
<span class="menu-icon">
|
||||||
<i class="bx bx-cube"></i>
|
<i class="bx bx-globe"></i>
|
||||||
</span>
|
</span>
|
||||||
<span class="menu-title"><TL>aaPanel</TL></span>
|
<span class="menu-title"><TL>Websites</TL></span>
|
||||||
<span class="menu-arrow"></span>
|
</a>
|
||||||
</span>
|
|
||||||
<div class="menu-sub menu-sub-accordion">
|
|
||||||
<div class="menu-item">
|
|
||||||
<a class="menu-link" href="/admin/aapanel/">
|
|
||||||
<span class="menu-bullet">
|
|
||||||
<span class="bullet bullet-dot"></span>
|
|
||||||
</span>
|
|
||||||
<span class="menu-title"><TL>Overview</TL></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<div class="menu-item">
|
|
||||||
<a class="menu-link" href="/admin/aapanel/databases">
|
|
||||||
<span class="menu-bullet">
|
|
||||||
<span class="bullet bullet-dot"></span>
|
|
||||||
</span>
|
|
||||||
<span class="menu-title"><TL>Databases</TL></span>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="menu-item">
|
<div class="menu-item">
|
||||||
<a class="menu-link" href="/admin/users">
|
<a class="menu-link" href="/admin/users">
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
|
||||||
|
<div class="row gy-5 g-xl-10">
|
||||||
|
<div class="col-xl-4 mb-xl-10">
|
||||||
|
<div class="card h-md-100">
|
||||||
|
<div class="card-body d-flex flex-column flex-center">
|
||||||
|
<img class="img-fluid" src="https://image.thum.io/get/http://@(CurrentWebsite.BaseDomain)" alt="Website screenshot"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-8 mb-5 mb-xl-10">
|
||||||
|
<div class="card card-flush h-xl-100">
|
||||||
|
<div class="card-body pt-2">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<div class="row mt-5">
|
||||||
|
<div class="card border">
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-title">
|
||||||
|
<TL>SSL certificates</TL>
|
||||||
|
</span>
|
||||||
|
<div class="card-toolbar">
|
||||||
|
<WButton Text="@(SmartTranslateService.Translate("Issue certificate"))"
|
||||||
|
WorkingText="@(SmartTranslateService.Translate("Working"))"
|
||||||
|
CssClasses="btn-success"
|
||||||
|
OnClick="CreateCertificate">
|
||||||
|
</WButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
@if (Certs.Any())
|
||||||
|
{
|
||||||
|
<table class="table align-middle gs-0 gy-3">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="p-0 w-50px"></th>
|
||||||
|
<th class="p-0 min-w-150px"></th>
|
||||||
|
<th class="p-0 min-w-120px"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach (var cert in Certs)
|
||||||
|
{
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<div class="symbol symbol-50px me-2">
|
||||||
|
<span class="symbol-label">
|
||||||
|
<i class="bx bx-md bx-receipt text-dark"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="text-dark fw-bold fs-6">@(cert)</span>
|
||||||
|
</td>
|
||||||
|
<td class="text-end">
|
||||||
|
<WButton Text="@(SmartTranslateService.Translate("Delete"))"
|
||||||
|
WorkingText="@(SmartTranslateService.Translate("Working"))"
|
||||||
|
CssClasses="btn btn-danger"
|
||||||
|
OnClick="() => DeleteCertificate(cert)">
|
||||||
|
</WButton>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<TL>No SSL certificates found</TL>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
public Website CurrentWebsite { get; set; }
|
||||||
|
|
||||||
|
private string[] Certs;
|
||||||
|
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader lazyLoader)
|
||||||
|
{
|
||||||
|
await lazyLoader.SetText("Loading certificates");
|
||||||
|
Certs = await WebsiteService.GetSslCertificates(CurrentWebsite);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task CreateCertificate()
|
||||||
|
{
|
||||||
|
await WebsiteService.CreateSslCertificate(CurrentWebsite);
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteCertificate(string name)
|
||||||
|
{
|
||||||
|
await WebsiteService.DeleteSslCertificate(CurrentWebsite, name);
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,135 @@
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Models.Forms
|
||||||
|
@using Moonlight.App.Models.Plesk.Resources
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
|
||||||
|
<div class="card card-flush h-xl-100">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<div class="card-header">
|
||||||
|
<span class="card-toolbar">
|
||||||
|
<div class="mt-4">
|
||||||
|
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
|
||||||
|
<div class="input-group">
|
||||||
|
<InputText @bind-Value="Model.Name" type="text" class="form-control" placeholder="@(SmartTranslateService.Translate("Name"))"></InputText>
|
||||||
|
<InputText @bind-Value="Model.Password" type="password" class="form-control" placeholder="@(SmartTranslateService.Translate("Password"))"></InputText>
|
||||||
|
<button class="btn btn-primary" type="submit">
|
||||||
|
<TL>Create</TL>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</SmartForm>
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-body pt-2">
|
||||||
|
@if (Databases.Any())
|
||||||
|
{
|
||||||
|
<div class="accordion" id="databases">
|
||||||
|
@foreach (var database in Databases)
|
||||||
|
{
|
||||||
|
<div class="accordion-item">
|
||||||
|
<h2 class="accordion-header" id="databases_header_@(database.Id)">
|
||||||
|
<button class="accordion-button fs-4 fw-semibold" type="button" data-bs-toggle="collapse" data-bs-target="#databases_body_@(database.Id)">
|
||||||
|
@(database.Name) - @(database.Type.ToUpper())
|
||||||
|
</button>
|
||||||
|
</h2>
|
||||||
|
<div id="databases_body_@(database.Id)" class="accordion-collapse collapse" data-bs-parent="#databases">
|
||||||
|
<div class="accordion-body">
|
||||||
|
<div class="mt-7 row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Host</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(Host)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-7 row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Port</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(DatabaseServer.Port)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-7 row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Username</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(database.Name)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mt-7 row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Database</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(database.Name)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="text-end">
|
||||||
|
<DeleteButton Confirm="true" OnClick="() => DeleteDatabase(database)" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<TL>No databases found for this website</TL>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
public Website CurrentWebsite { get; set; }
|
||||||
|
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
private Database[] Databases;
|
||||||
|
private DatabaseServer DatabaseServer;
|
||||||
|
private string Host;
|
||||||
|
|
||||||
|
private DatabaseDataModel Model = new();
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
Databases = await WebsiteService.GetDatabases(CurrentWebsite);
|
||||||
|
|
||||||
|
if (Databases.Any())
|
||||||
|
{
|
||||||
|
DatabaseServer = (await WebsiteService.GetDefaultDatabaseServer(CurrentWebsite))!;
|
||||||
|
Host = await WebsiteService.GetHost(CurrentWebsite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnValidSubmit()
|
||||||
|
{
|
||||||
|
await WebsiteService.CreateDatabase(CurrentWebsite, Model.Name, Model.Password);
|
||||||
|
Model = new();
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DeleteDatabase(Database database)
|
||||||
|
{
|
||||||
|
await WebsiteService.DeleteDatabase(CurrentWebsite, database);
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Helpers.Files
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.Shared.Components.FileManagerPartials
|
||||||
|
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
<FileManager Access="Access">
|
||||||
|
</FileManager>
|
||||||
|
</LazyLoader>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
public Website CurrentWebsite { get; set; }
|
||||||
|
|
||||||
|
private FileAccess Access;
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
Access = await WebsiteService.CreateFileAccess(CurrentWebsite);
|
||||||
|
}
|
||||||
|
}
|
64
Moonlight/Shared/Components/WebsiteControl/WebsiteFtp.razor
Normal file
64
Moonlight/Shared/Components/WebsiteControl/WebsiteFtp.razor
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
|
||||||
|
<div class="card card-flush h-xl-100">
|
||||||
|
<div class="card-body pt-2">
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
<div class="mt-7 row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Ftp Host</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(FtpHost)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Ftp Port</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="21">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Ftp Username</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled" disabled="disabled" value="@(Website.FtpLogin)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row fv-row mb-7">
|
||||||
|
<div class="col-md-3 text-md-start">
|
||||||
|
<label class="fs-6 fw-semibold form-label mt-3">
|
||||||
|
<TL>Ftp Password</TL>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control form-control-solid disabled blur-unless-hover" disabled="disabled" value="@(Website.FtpPassword)">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[CascadingParameter]
|
||||||
|
public Website Website { get; set; }
|
||||||
|
|
||||||
|
private string FtpHost = "N/A";
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
FtpHost = await WebsiteService.GetHost(Website.PleskServer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
|
||||||
|
<div class="card card-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-8">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<div class="symbol symbol-circle me-5">
|
||||||
|
<div class="symbol-label bg-transparent text-primary border border-secondary border-dashed">
|
||||||
|
<i class="bx bx-globe bx-md"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="d-flex flex-column">
|
||||||
|
<div class="mb-1 fs-4">@(Website.BaseDomain)</div>
|
||||||
|
<div class="text-muted fs-5">@(Website.PleskServer.Name)</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="separator my-5"></div>
|
||||||
|
</div>
|
||||||
|
<div class="card mb-5 mb-xl-10">
|
||||||
|
<div class="card-body pt-0 pb-0">
|
||||||
|
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/website/@(Website.Id)">
|
||||||
|
<TL>Dashboard</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/website/@(Website.Id)/files">
|
||||||
|
<TL>Files</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 2 ? "active" : "")" href="/website/@(Website.Id)/ftp">
|
||||||
|
<TL>Ftp</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item mt-2">
|
||||||
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 3 ? "active" : "")" href="/website/@(Website.Id)/databases">
|
||||||
|
<TL>Databases</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public Website Website { get; set; }
|
||||||
|
}
|
|
@ -1,12 +1,10 @@
|
||||||
@page "/admin/servers/new"
|
@page "/admin/servers/new"
|
||||||
@using Moonlight.App.Repositories
|
@using Moonlight.App.Repositories
|
||||||
@using Moonlight.App.Repositories.Servers
|
|
||||||
@using Moonlight.App.Database.Entities
|
@using Moonlight.App.Database.Entities
|
||||||
@using Moonlight.App.Services
|
@using Moonlight.App.Services
|
||||||
@using Microsoft.EntityFrameworkCore
|
@using Microsoft.EntityFrameworkCore
|
||||||
@using Moonlight.App.Exceptions
|
@using Moonlight.App.Exceptions
|
||||||
@using Moonlight.App.Services.Interop
|
@using Moonlight.App.Services.Interop
|
||||||
@using Moonlight.App.Services.Sessions
|
|
||||||
@using Logging.Net
|
@using Logging.Net
|
||||||
@using Blazored.Typeahead
|
@using Blazored.Typeahead
|
||||||
|
|
||||||
|
|
93
Moonlight/Shared/Views/Admin/Websites/Index.razor
Normal file
93
Moonlight/Shared/Views/Admin/Websites/Index.razor
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
@page "/admin/websites/"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using BlazorTable
|
||||||
|
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject WebsiteRepository WebsiteRepository
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminWebsitesNavigation Index="0"/>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header border-0 pt-5">
|
||||||
|
<h3 class="card-title align-items-start flex-column">
|
||||||
|
<span class="card-label fw-bold fs-3 mb-1">
|
||||||
|
<TL>Websites</TL>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div class="card-toolbar">
|
||||||
|
<a href="/admin/websites/new" class="btn btn-sm btn-light-success">
|
||||||
|
<i class="bx bx-user-plus"></i>
|
||||||
|
<TL>New website</TL>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<Table TableItem="Website" Items="Websites" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
||||||
|
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Base domain"))" Field="@(x => x.BaseDomain)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
<a href="/website/@(context.Id)/">
|
||||||
|
@(context.BaseDomain)
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Owner"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/users/view/@(context.Owner.Id)">
|
||||||
|
@(context.Owner.Email)
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Plesk server"))" Field="@(x => x.PleskServer.Id)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/websites/servers/edit/@(context.PleskServer.Id)/">
|
||||||
|
@(context.PleskServer.Name)
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Manage"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<DeleteButton Confirm="true" OnClick="() => Delete(context)">
|
||||||
|
</DeleteButton>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
|
||||||
|
private Website[] Websites;
|
||||||
|
|
||||||
|
private Task Load(LazyLoader lazyLoader)
|
||||||
|
{
|
||||||
|
Websites = WebsiteRepository
|
||||||
|
.Get()
|
||||||
|
.Include(x => x.Owner)
|
||||||
|
.Include(x => x.PleskServer)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Delete(Website website)
|
||||||
|
{
|
||||||
|
await WebsiteService.Delete(website);
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
79
Moonlight/Shared/Views/Admin/Websites/New.razor
Normal file
79
Moonlight/Shared/Views/Admin/Websites/New.razor
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
@page "/admin/websites/new"
|
||||||
|
|
||||||
|
@using Moonlight.App.Models.Forms
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Blazored.Typeahead
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
@inject UserRepository UserRepository
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<div class="card card-body p-10">
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Base domain</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.BaseDomain" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Owner</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<BlazoredTypeahead SearchMethod="SearchUsers"
|
||||||
|
@bind-Value="Model.User">
|
||||||
|
<SelectedTemplate>
|
||||||
|
@(context.Email)
|
||||||
|
</SelectedTemplate>
|
||||||
|
<ResultTemplate>
|
||||||
|
@(context.Email)
|
||||||
|
</ResultTemplate>
|
||||||
|
</BlazoredTypeahead>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="btn btn-primary float-end">
|
||||||
|
<TL>Create</TL>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</SmartForm>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private WebsiteAdminDataModel Model = new();
|
||||||
|
private User[] Users;
|
||||||
|
|
||||||
|
private async Task OnValidSubmit()
|
||||||
|
{
|
||||||
|
await WebsiteService.Create(Model.BaseDomain, Model.User);
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo("/admin/websites");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
Users = UserRepository
|
||||||
|
.Get()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<User>> SearchUsers(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
return Task.FromResult(Array.Empty<User>().Cast<User>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Task.FromResult(Users.Where(x => x.Email.ToLower().StartsWith(input)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
98
Moonlight/Shared/Views/Admin/Websites/Servers/Edit.razor
Normal file
98
Moonlight/Shared/Views/Admin/Websites/Servers/Edit.razor
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
@page "/admin/websites/servers/edit/{Id:int}"
|
||||||
|
|
||||||
|
@using Moonlight.App.Models.Forms
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
|
||||||
|
@inject PleskServerRepository PleskServerRepository
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
@if (PleskServer == null)
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-center flex-center">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/assets/media/svg/nodata.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h1 class="card-title">
|
||||||
|
<TL>Plesk server not found</TL>
|
||||||
|
</h1>
|
||||||
|
<p class="card-text fs-4">
|
||||||
|
<TL>A plesk server with that id cannot be found</TL>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="card card-body p-10">
|
||||||
|
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Name</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.Name" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Api Url</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.ApiUrl" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Api Key</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.ApiKey" class="blur-unless-hover form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="btn btn-primary float-end">
|
||||||
|
<TL>Save</TL>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</SmartForm>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</LazyLoader>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
private PleskServer? PleskServer;
|
||||||
|
|
||||||
|
private PleskServerDataModel Model = new();
|
||||||
|
|
||||||
|
private Task OnValidSubmit()
|
||||||
|
{
|
||||||
|
PleskServer!.Name = Model.Name;
|
||||||
|
PleskServer.ApiUrl = Model.ApiUrl;
|
||||||
|
PleskServer.ApiKey = Model.ApiKey;
|
||||||
|
|
||||||
|
PleskServerRepository.Update(PleskServer);
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo("/admin/websites/servers");
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
PleskServer = PleskServerRepository
|
||||||
|
.Get()
|
||||||
|
.FirstOrDefault(x => x.Id == Id);
|
||||||
|
|
||||||
|
if (PleskServer != null)
|
||||||
|
{
|
||||||
|
Model.Name = PleskServer.Name;
|
||||||
|
Model.ApiUrl = PleskServer.ApiUrl;
|
||||||
|
Model.ApiKey = PleskServer.ApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
115
Moonlight/Shared/Views/Admin/Websites/Servers/Index.razor
Normal file
115
Moonlight/Shared/Views/Admin/Websites/Servers/Index.razor
Normal file
|
@ -0,0 +1,115 @@
|
||||||
|
@page "/admin/websites/servers"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using BlazorTable
|
||||||
|
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject PleskServerRepository PleskServerRepository
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminWebsitesNavigation Index="1"/>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header border-0 pt-5">
|
||||||
|
<h3 class="card-title align-items-start flex-column">
|
||||||
|
<span class="card-label fw-bold fs-3 mb-1">
|
||||||
|
<TL>Plesk servers</TL>
|
||||||
|
</span>
|
||||||
|
</h3>
|
||||||
|
<div class="card-toolbar">
|
||||||
|
<a href="/admin/websites/servers/new" class="btn btn-sm btn-light-success">
|
||||||
|
<i class="bx bx-user-plus"></i>
|
||||||
|
<TL>New plesk server</TL>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<Table TableItem="PleskServer" Items="PleskServers" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Name)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Api url"))" Field="@(x => x.ApiUrl)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Status"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
@if (OnlineCache.ContainsKey(context))
|
||||||
|
{
|
||||||
|
if (OnlineCache[context])
|
||||||
|
{
|
||||||
|
<span class="text-success">
|
||||||
|
<TL>Online</TL>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="text-danger">
|
||||||
|
<TL>Offline</TL>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="text-muted">
|
||||||
|
<TL>Loading</TL>
|
||||||
|
</span>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Edit"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/websites/servers/edit/@(context.Id)/">
|
||||||
|
<TL>Manage</TL>
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="PleskServer" Title="@(SmartTranslateService.Translate("Manage"))" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<DeleteButton Confirm="true" OnClick="() => OnClick(context)">
|
||||||
|
</DeleteButton>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private PleskServer[] PleskServers;
|
||||||
|
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
private Dictionary<PleskServer, bool> OnlineCache = new();
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
PleskServers = PleskServerRepository
|
||||||
|
.Get()
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
foreach (var pleskServer in PleskServers)
|
||||||
|
{
|
||||||
|
OnlineCache.Add(pleskServer, await WebsiteService.IsHostUp(pleskServer));
|
||||||
|
|
||||||
|
await InvokeAsync(StateHasChanged);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnClick(PleskServer pleskServer)
|
||||||
|
{
|
||||||
|
PleskServerRepository.Delete(pleskServer);
|
||||||
|
|
||||||
|
await LazyLoader.Reload();
|
||||||
|
}
|
||||||
|
}
|
55
Moonlight/Shared/Views/Admin/Websites/Servers/New.razor
Normal file
55
Moonlight/Shared/Views/Admin/Websites/Servers/New.razor
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
@page "/admin/websites/servers/new"
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Moonlight.App.Models.Forms
|
||||||
|
|
||||||
|
@inject PleskServerRepository PleskServerRepository
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<div class="card card-body p-10">
|
||||||
|
<SmartForm Model="Model" OnValidSubmit="OnValidSubmit">
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Name</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.Name" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Api Url</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.ApiUrl" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<label class="form-label">
|
||||||
|
<TL>Api Key</TL>
|
||||||
|
</label>
|
||||||
|
<div class="input-group mb-5">
|
||||||
|
<InputText @bind-Value="Model.ApiKey" class="form-control"></InputText>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type="submit" class="btn btn-primary float-end">
|
||||||
|
<TL>Create</TL>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</SmartForm>
|
||||||
|
</div>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private PleskServerDataModel Model = new();
|
||||||
|
|
||||||
|
private Task OnValidSubmit()
|
||||||
|
{
|
||||||
|
PleskServerRepository.Add(new()
|
||||||
|
{
|
||||||
|
Name = Model.Name,
|
||||||
|
ApiUrl = Model.ApiUrl,
|
||||||
|
ApiKey = Model.ApiKey
|
||||||
|
});
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo("/admin/websites/servers");
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
@inject ServerRepository ServerRepository
|
@inject ServerRepository ServerRepository
|
||||||
@inject WingsConsoleHelper WingsConsoleHelper
|
@inject WingsConsoleHelper WingsConsoleHelper
|
||||||
@inject MessageService MessageService
|
@inject MessageService MessageService
|
||||||
@inject NodeService NodeService
|
@inject ServerService ServerService
|
||||||
@inject NavigationManager NavigationManager
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
@ -227,31 +227,23 @@
|
||||||
.Include(x => x.MainAllocation)
|
.Include(x => x.MainAllocation)
|
||||||
.Include(x => x.Owner)
|
.Include(x => x.Owner)
|
||||||
.First(x => x.Uuid == uuid);
|
.First(x => x.Uuid == uuid);
|
||||||
|
|
||||||
if (CurrentServer.Owner.Id != User!.Id && !User.Admin)
|
|
||||||
CurrentServer = null;
|
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (CurrentServer != null)
|
||||||
|
{
|
||||||
|
if (CurrentServer.Owner.Id != User!.Id && !User.Admin)
|
||||||
|
CurrentServer = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (CurrentServer != null)
|
if (CurrentServer != null)
|
||||||
{
|
{
|
||||||
await lazyLoader.SetText("Checking node online status");
|
await lazyLoader.SetText("Checking node online status");
|
||||||
|
|
||||||
try
|
NodeOnline = await ServerService.IsHostUp(CurrentServer);
|
||||||
{
|
|
||||||
//TODO: Implement status caching
|
|
||||||
var data = await NodeService.GetStatus(CurrentServer.Node);
|
|
||||||
|
|
||||||
if (data != null)
|
|
||||||
NodeOnline = true;
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
// ignored
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NodeOnline)
|
if (NodeOnline)
|
||||||
{
|
{
|
||||||
|
|
132
Moonlight/Shared/Views/Website/Index.razor
Normal file
132
Moonlight/Shared/Views/Website/Index.razor
Normal file
|
@ -0,0 +1,132 @@
|
||||||
|
@page "/website/{Id:int}/{Route?}"
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
@using Moonlight.Shared.Components.WebsiteControl
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using Moonlight.App.Services.Interop
|
||||||
|
|
||||||
|
@inject WebsiteRepository WebsiteRepository
|
||||||
|
@inject WebsiteService WebsiteService
|
||||||
|
@inject ToastService ToastService
|
||||||
|
|
||||||
|
<LazyLoader Load="Load">
|
||||||
|
@if (CurrentWebsite == null)
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-center flex-center">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/assets/media/svg/nodata.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h1 class="card-title">
|
||||||
|
<TL>Website not found</TL>
|
||||||
|
</h1>
|
||||||
|
<p class="card-text fs-4">
|
||||||
|
<TL>A website with that id cannot be found or you have no access for this server</TL>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (HostOnline)
|
||||||
|
{
|
||||||
|
<CascadingValue Value="CurrentWebsite">
|
||||||
|
@{
|
||||||
|
var index = 0;
|
||||||
|
|
||||||
|
switch (Route)
|
||||||
|
{
|
||||||
|
case "files":
|
||||||
|
index = 1;
|
||||||
|
break;
|
||||||
|
case "ftp":
|
||||||
|
index = 2;
|
||||||
|
break;
|
||||||
|
case "databases":
|
||||||
|
index = 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
index = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
<WebsiteNavigation Index="index" Website="CurrentWebsite" />
|
||||||
|
|
||||||
|
@switch (Route)
|
||||||
|
{
|
||||||
|
case "files":
|
||||||
|
<WebsiteFiles />
|
||||||
|
break;
|
||||||
|
case "ftp":
|
||||||
|
<WebsiteFtp />
|
||||||
|
break;
|
||||||
|
case "databases":
|
||||||
|
<WebsiteDatabases />
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
<WebsiteDashboard />
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</CascadingValue>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="d-flex justify-content-center flex-center">
|
||||||
|
<div class="card">
|
||||||
|
<img src="/assets/media/svg/serverdown.svg" class="card-img-top w-50 mx-auto pt-5" alt="Not found image"/>
|
||||||
|
<div class="card-body text-center">
|
||||||
|
<h1 class="card-title">
|
||||||
|
<TL>Host system offline</TL>
|
||||||
|
</h1>
|
||||||
|
<p class="card-text fs-4">
|
||||||
|
<TL>The host system the website is running on is currently offline</TL>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</LazyLoader>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public string? Route { get; set; }
|
||||||
|
|
||||||
|
[CascadingParameter]
|
||||||
|
public User User { get; set; }
|
||||||
|
|
||||||
|
private Website? CurrentWebsite;
|
||||||
|
private bool HostOnline = false;
|
||||||
|
|
||||||
|
private async Task Load(LazyLoader lazyLoader)
|
||||||
|
{
|
||||||
|
CurrentWebsite = WebsiteRepository
|
||||||
|
.Get()
|
||||||
|
.Include(x => x.PleskServer)
|
||||||
|
.Include(x => x.Owner)
|
||||||
|
.FirstOrDefault(x => x.Id == Id);
|
||||||
|
|
||||||
|
if (CurrentWebsite != null)
|
||||||
|
{
|
||||||
|
if (CurrentWebsite.Owner.Id != User!.Id && !User.Admin)
|
||||||
|
CurrentWebsite = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CurrentWebsite != null)
|
||||||
|
{
|
||||||
|
await lazyLoader.SetText("Checking host system online status");
|
||||||
|
|
||||||
|
HostOnline = await WebsiteService.IsHostUp(CurrentWebsite);
|
||||||
|
|
||||||
|
if (HostOnline)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
Moonlight/Shared/Views/Websites/Index.razor
Normal file
1
Moonlight/Shared/Views/Websites/Index.razor
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@page "/websites"
|
1
Moonlight/Shared/Views/Websites/New.razor
Normal file
1
Moonlight/Shared/Views/Websites/New.razor
Normal file
|
@ -0,0 +1 @@
|
||||||
|
@page "/websites/new"
|
|
@ -487,3 +487,28 @@ Decompress;Decompress
|
||||||
Moving;Moving
|
Moving;Moving
|
||||||
Compressing;Compressing
|
Compressing;Compressing
|
||||||
selected;selected
|
selected;selected
|
||||||
|
New website;New website
|
||||||
|
Plesk servers;Plesk servers
|
||||||
|
Base domain;Base domain
|
||||||
|
Plesk server;Plesk server
|
||||||
|
Ftp;Ftp
|
||||||
|
No SSL certificate found;No SSL certificate found
|
||||||
|
Ftp Host;Ftp Host
|
||||||
|
Ftp Port;Ftp Port
|
||||||
|
Ftp Username;Ftp Username
|
||||||
|
Ftp Password;Ftp Password
|
||||||
|
Use;Use
|
||||||
|
SSL Certificates;SSL Certificates
|
||||||
|
SSL certificates;SSL certificates
|
||||||
|
Issue certificate;Issue certificate
|
||||||
|
New plesk server;New plesk server
|
||||||
|
Api url;Api url
|
||||||
|
Host system offline;Host system offline
|
||||||
|
The host system the website is running on is currently offline;The host system the website is running on is currently offline
|
||||||
|
No SSL certificates found;No SSL certificates found
|
||||||
|
No databases found for this website;No databases found for this website
|
||||||
|
The name should be at least 8 characters long;The name should be at least 8 characters long
|
||||||
|
The name should only contain of lower case characters and numbers;The name should only contain of lower case characters and numbers
|
||||||
|
Error from plesk;Error from plesk
|
||||||
|
Host;Host
|
||||||
|
Username;Username
|
||||||
|
|
21
Moonlight/resources/lang/en_us.lang
Normal file
21
Moonlight/resources/lang/en_us.lang
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Open support;Open support
|
||||||
|
About us;About us
|
||||||
|
Imprint;Imprint
|
||||||
|
Privacy;Privacy
|
||||||
|
Create;Create
|
||||||
|
Server;Server
|
||||||
|
Domain;Domain
|
||||||
|
Website;Website
|
||||||
|
Login;Login
|
||||||
|
Register;Register
|
||||||
|
Email;Email
|
||||||
|
Password;Password
|
||||||
|
Sign In;Sign In
|
||||||
|
Sign in to start with moonlight;Sign in to start with moonlight
|
||||||
|
Sign in with Discord;Sign in with Discord
|
||||||
|
Sign in with Google;Sign in with Google
|
||||||
|
Or with email;Or with email
|
||||||
|
Forgot password?;Forgot password?
|
||||||
|
Sign-in;Sign-in
|
||||||
|
Not registered yet?;Not registered yet?
|
||||||
|
Sign up;Sign up
|
Loading…
Reference in a new issue