Revert "Merge branch 'PleskIntegration' into main"
This reverts commit18c205d8a0
, reversing changes made toc5be86b695
.
This commit is contained in:
parent
18c205d8a0
commit
3611b745ff
|
@ -42,7 +42,6 @@ public class DataContext : DbContext
|
|||
public DbSet<AaPanel> AaPanels { get; set; }
|
||||
public DbSet<Website> Websites { get; set; }
|
||||
public DbSet<DdosAttack> DdosAttacks { get; set; }
|
||||
public DbSet<PleskServer> PleskServers { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
namespace Moonlight.App.Database.Entities;
|
||||
|
||||
public class PleskServer
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string BaseUrl { get; set; } = "";
|
||||
public string ApiKey { get; set; } = "";
|
||||
public string Name { get; set; } = "";
|
||||
}
|
|
@ -3,8 +3,11 @@
|
|||
public class Website
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public int PleskId { get; set; }
|
||||
public int InternalAaPanelId { get; set; }
|
||||
public AaPanel AaPanel { get; set; }
|
||||
public User Owner { get; set; }
|
||||
public PleskServer PleskServer { get; set; }
|
||||
public string BaseDomain { get; set; }
|
||||
public string DomainName { get; set; }
|
||||
public string PhpVersion { get; set; }
|
||||
public string FtpUsername { get; set; }
|
||||
public string FtpPassword { get; set; }
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,39 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedPleskServer : 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),
|
||||
BaseUrl = 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");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "PleskServers");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedNameToPleskServer : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Name",
|
||||
table: "PleskServers",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Name",
|
||||
table: "PleskServers");
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,124 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class SwitchedToPleskModel : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Websites_AaPanels_AaPanelId",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Websites_AaPanelId",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DomainName",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "FtpPassword",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "FtpUsername",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PhpVersion",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "InternalAaPanelId",
|
||||
table: "Websites",
|
||||
newName: "PleskServerId");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "AaPanelId",
|
||||
table: "Websites",
|
||||
newName: "PleskId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Websites_PleskServerId",
|
||||
table: "Websites",
|
||||
column: "PleskServerId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Websites_PleskServers_PleskServerId",
|
||||
table: "Websites",
|
||||
column: "PleskServerId",
|
||||
principalTable: "PleskServers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Websites_PleskServers_PleskServerId",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Websites_PleskServerId",
|
||||
table: "Websites");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "PleskServerId",
|
||||
table: "Websites",
|
||||
newName: "InternalAaPanelId");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "PleskId",
|
||||
table: "Websites",
|
||||
newName: "AaPanelId");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "DomainName",
|
||||
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");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "FtpUsername",
|
||||
table: "Websites",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "PhpVersion",
|
||||
table: "Websites",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Websites_AaPanelId",
|
||||
table: "Websites",
|
||||
column: "AaPanelId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Websites_AaPanels_AaPanelId",
|
||||
table: "Websites",
|
||||
column: "AaPanelId",
|
||||
principalTable: "AaPanels",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,29 +0,0 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Moonlight.App.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddedBaseDomainToWebsite : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "BaseDomain",
|
||||
table: "Websites",
|
||||
type: "longtext",
|
||||
nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "BaseDomain",
|
||||
table: "Websites");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -446,29 +446,6 @@ namespace Moonlight.App.Database.Migrations
|
|||
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>("BaseUrl")
|
||||
.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")
|
||||
|
@ -810,24 +787,36 @@ namespace Moonlight.App.Database.Migrations
|
|||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("BaseDomain")
|
||||
b.Property<int>("AaPanelId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("DomainName")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("FtpPassword")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<string>("FtpUsername")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<int>("InternalAaPanelId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("OwnerId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PleskId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<int>("PleskServerId")
|
||||
.HasColumnType("int");
|
||||
b.Property<string>("PhpVersion")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
b.HasIndex("AaPanelId");
|
||||
|
||||
b.HasIndex("PleskServerId");
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Websites");
|
||||
});
|
||||
|
@ -1018,21 +1007,21 @@ namespace Moonlight.App.Database.Migrations
|
|||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
||||
{
|
||||
b.HasOne("Moonlight.App.Database.Entities.AaPanel", "AaPanel")
|
||||
.WithMany()
|
||||
.HasForeignKey("AaPanelId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||
.WithMany()
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Moonlight.App.Database.Entities.PleskServer", "PleskServer")
|
||||
.WithMany()
|
||||
.HasForeignKey("PleskServerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
b.Navigation("AaPanel");
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("PleskServer");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
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)
|
||||
{
|
||||
}
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
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);
|
||||
|
||||
var response = await Client.GetAsync(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<T> Post<T>(PleskServer server, string resource, object? body)
|
||||
{
|
||||
var request = CreateRequest(server, resource);
|
||||
|
||||
request.AddParameter("text/plain",
|
||||
JsonConvert.SerializeObject(body),
|
||||
ParameterType.RequestBody
|
||||
);
|
||||
|
||||
var response = await Client.PostAsync(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 Delete(PleskServer server, string resource, object? body)
|
||||
{
|
||||
var request = CreateRequest(server, resource);
|
||||
|
||||
if(body != null)
|
||||
request.AddParameter("text/plain", JsonConvert.SerializeObject(body), ParameterType.RequestBody);
|
||||
|
||||
var response = await Client.DeleteAsync(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 server, string resource)
|
||||
{
|
||||
RestRequest request = new(server.BaseUrl + "/" + resource);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
request.AddHeader("Accept", "application/json");
|
||||
|
||||
// Implementation of auth method using auth header and api key
|
||||
// https://docs.plesk.com/en-US/obsidian/api-rpc/about-rest-api.79359/#authentication-methods
|
||||
|
||||
if (server.ApiKey.Contains(":"))
|
||||
{
|
||||
var base64 = Convert.ToBase64String(
|
||||
Encoding.ASCII.GetBytes(server.ApiKey)
|
||||
);
|
||||
|
||||
request.AddHeader("Authorization", "Basic " + base64);
|
||||
}
|
||||
else
|
||||
request.AddHeader("X-API-Key", server.ApiKey);
|
||||
|
||||
|
||||
return request;
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
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 HostingSettings HostingSettings { get; set; } = new();
|
||||
|
||||
[JsonProperty("owner_client")] public OwnerClient OwnerClient { get; set; } = new();
|
||||
|
||||
[JsonProperty("plan")] public Plan Plan { get; set; } = new();
|
||||
}
|
||||
|
||||
public partial class HostingSettings
|
||||
{
|
||||
[JsonProperty("ftp_login")]
|
||||
public string FtpLogin { get; set; }
|
||||
|
||||
[JsonProperty("ftp_password")]
|
||||
public string FtpPassword { get; set; }
|
||||
}
|
||||
|
||||
public partial class OwnerClient
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public long Id { get; set; }
|
||||
}
|
||||
|
||||
public partial class Plan
|
||||
{
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
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("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
using Newtonsoft.Json;
|
||||
|
||||
namespace Moonlight.App.Models.Plesk.Resources;
|
||||
|
||||
public class Identifier
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public int Id { get; set; }
|
||||
|
||||
[JsonProperty("guid")]
|
||||
public Guid Guid { get; set; }
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
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();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,7 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using aaPanelSharp;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moonlight.App.Database.Entities;
|
||||
using Moonlight.App.Exceptions;
|
||||
using Moonlight.App.Helpers;
|
||||
using Moonlight.App.Models.Plesk.Requests;
|
||||
using Moonlight.App.Models.Plesk.Resources;
|
||||
using Moonlight.App.Repositories;
|
||||
|
||||
namespace Moonlight.App.Services;
|
||||
|
@ -11,100 +9,31 @@ namespace Moonlight.App.Services;
|
|||
public class WebsiteService
|
||||
{
|
||||
private readonly WebsiteRepository WebsiteRepository;
|
||||
private readonly PleskServerRepository PleskServerRepository;
|
||||
private readonly PleskApiHelper PleskApiHelper;
|
||||
|
||||
public WebsiteService(WebsiteRepository websiteRepository, PleskServerRepository pleskServerRepository,
|
||||
PleskApiHelper pleskApiHelper)
|
||||
public WebsiteService(WebsiteRepository websiteRepository)
|
||||
{
|
||||
WebsiteRepository = websiteRepository;
|
||||
PleskServerRepository = pleskServerRepository;
|
||||
PleskApiHelper = pleskApiHelper;
|
||||
}
|
||||
|
||||
public async Task<Website> Create(User owner, string baseDomain, string ftpPassword, PleskServer? ps = null)
|
||||
public Website Create(AaPanel aaPanel, User user, string name)
|
||||
{
|
||||
var pleskServer = ps ?? PleskServerRepository.Get().FirstOrDefault();
|
||||
if (WebsiteRepository.Get().Any(x => x.DomainName == name))
|
||||
throw new DisplayException("A website with this domain has already been created");
|
||||
|
||||
if (pleskServer == null)
|
||||
throw new DisplayException("No plesk server found to deploy the website");
|
||||
|
||||
var website = WebsiteRepository.Add(new Website()
|
||||
var access = new aaPanel(aaPanel.Url, aaPanel.Key);
|
||||
return null;
|
||||
}
|
||||
|
||||
private aaPanel CreateApiAccess(Website website)
|
||||
{
|
||||
if (website.AaPanel == null)
|
||||
{
|
||||
PleskServer = pleskServer,
|
||||
Owner = owner,
|
||||
BaseDomain = baseDomain
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
var userId = await GetAdminAccountForDeploy(pleskServer);
|
||||
|
||||
string ftpUsername = baseDomain.Replace(".", "_");
|
||||
|
||||
var createDomain = new CreateDomain()
|
||||
{
|
||||
Description = "Moonlight website " + website.Id,
|
||||
Name = baseDomain,
|
||||
OwnerClient = new()
|
||||
{
|
||||
Id = userId
|
||||
},
|
||||
Plan = new()
|
||||
{
|
||||
Name = "Unlimited"
|
||||
},
|
||||
HostingType = "virtual",
|
||||
HostingSettings = new()
|
||||
{
|
||||
FtpLogin = ftpUsername,
|
||||
FtpPassword = ftpPassword
|
||||
}
|
||||
};
|
||||
|
||||
var identifier = await PleskApiHelper.Post<Identifier>(
|
||||
pleskServer,
|
||||
"domains",
|
||||
createDomain
|
||||
);
|
||||
|
||||
website.PleskId = identifier.Id;
|
||||
|
||||
WebsiteRepository.Update(website);
|
||||
|
||||
return website;
|
||||
website = WebsiteRepository
|
||||
.Get()
|
||||
.Include(x => x.AaPanel)
|
||||
.First(x => x.Id == website.Id);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
WebsiteRepository.Delete(website);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Delete(Website w)
|
||||
{
|
||||
var website = WebsiteRepository
|
||||
.Get()
|
||||
.Include(x => x.PleskServer)
|
||||
.FirstOrDefault(x => x.Id == w.Id);
|
||||
|
||||
if (website == null)
|
||||
throw new DisplayException("Website not found");
|
||||
|
||||
await PleskApiHelper.Delete(website.PleskServer, $"domains/{website.PleskId}", null);
|
||||
|
||||
WebsiteRepository.Delete(website);
|
||||
}
|
||||
|
||||
private async Task<int> GetAdminAccountForDeploy(PleskServer pleskServer)
|
||||
{
|
||||
var clients = await PleskApiHelper.Get<Client[]>(pleskServer, "clients");
|
||||
var adminClient = clients.FirstOrDefault(x => x.Type == "admin");
|
||||
|
||||
if (adminClient == null)
|
||||
throw new DisplayException("Unable to deploy website. Plesk admin account is missing");
|
||||
|
||||
return adminClient.Id;
|
||||
return new aaPanel(website.AaPanel.Url, website.AaPanel.Key);
|
||||
}
|
||||
}
|
|
@ -65,7 +65,6 @@ namespace Moonlight
|
|||
builder.Services.AddScoped<AaPanelRepository>();
|
||||
builder.Services.AddScoped<WebsiteRepository>();
|
||||
builder.Services.AddScoped<DdosAttackRepository>();
|
||||
builder.Services.AddScoped<PleskServerRepository>();
|
||||
|
||||
builder.Services.AddScoped<AuditLogEntryRepository>();
|
||||
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
||||
|
@ -121,7 +120,6 @@ namespace Moonlight
|
|||
builder.Services.AddSingleton<PaperApiHelper>();
|
||||
builder.Services.AddSingleton<HostSystemHelper>();
|
||||
builder.Services.AddScoped<DaemonApiHelper>();
|
||||
builder.Services.AddScoped<PleskApiHelper>();
|
||||
|
||||
// Background services
|
||||
builder.Services.AddSingleton<DiscordBotService>();
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
@typeparam TItem
|
||||
|
||||
<select class="form-select" @bind="Binding">
|
||||
@foreach(var item in Items)
|
||||
{
|
||||
<option value="@(item!.GetHashCode())">@(DisplayField(item))</option>
|
||||
}
|
||||
</select>
|
||||
|
||||
@code
|
||||
{
|
||||
[Parameter]
|
||||
public TItem[] Items { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<TItem, string> DisplayField { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Action<TItem> OnChange { get; set; }
|
||||
|
||||
private int Binding
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Value == null)
|
||||
return -1;
|
||||
|
||||
return Value.GetHashCode();
|
||||
}
|
||||
set
|
||||
{
|
||||
var i = Items.FirstOrDefault(x => x!.GetHashCode() == value);
|
||||
|
||||
if (i != null)
|
||||
{
|
||||
Value = i;
|
||||
OnChange?.Invoke(Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TItem Value;
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
<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,13 +155,32 @@ else
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-item">
|
||||
<a class="menu-link" href="/admin/websites">
|
||||
<div data-kt-menu-trigger="click" class="menu-item menu-accordion">
|
||||
<span class="menu-link">
|
||||
<span class="menu-icon">
|
||||
<i class="bx bx-globe"></i>
|
||||
<i class="bx bx-cube"></i>
|
||||
</span>
|
||||
<span class="menu-title"><TL>Websites</TL></span>
|
||||
</a>
|
||||
<span class="menu-title"><TL>aaPanel</TL></span>
|
||||
<span class="menu-arrow"></span>
|
||||
</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 class="menu-item">
|
||||
<a class="menu-link" href="/admin/users">
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
@page "/admin/websites/"
|
||||
|
||||
@using Moonlight.Shared.Components.Navigations
|
||||
@using BlazorTable
|
||||
@using Microsoft.EntityFrameworkCore
|
||||
@using Moonlight.App.Database.Entities
|
||||
@using Moonlight.App.Repositories
|
||||
@using Moonlight.App.Services
|
||||
@using Moonlight.App.Services.Interop
|
||||
|
||||
@inject WebsiteRepository WebsiteRepository
|
||||
@inject SmartTranslateService SmartTranslateService
|
||||
@inject ToastService ToastService
|
||||
@inject WebsiteService WebsiteService
|
||||
|
||||
<OnlyAdmin>
|
||||
<AdminWebsiteNavigation Index="0"/>
|
||||
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
<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-layer-plus"></i>
|
||||
<TL>Add new website</TL>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<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">
|
||||
<Template>
|
||||
<a href="/website/@(context.Id)">@(context.Id)</a>
|
||||
</Template>
|
||||
</Column>
|
||||
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Plesk id"))" Field="@(x => x.PleskId)" Sortable="true" Filterable="true"/>
|
||||
<Column TableItem="Website" Title="@(SmartTranslateService.Translate("Owner"))" Field="@(x => x.Owner)" Sortable="true" Filterable="true">
|
||||
<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)" Sortable="true" Filterable="true">
|
||||
<Template>
|
||||
<a href="/admin/websites/servers/edit/@(context.PleskServer.Id)">@(context.PleskServer.Name)</a>
|
||||
</Template>
|
||||
</Column>
|
||||
<Column TableItem="Website" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||
<Template>
|
||||
<WButton Text="@(SmartTranslateService.Translate("Delete"))"
|
||||
WorkingText="@(SmartTranslateService.Translate("Deleting"))"
|
||||
CssClasses="btn-danger"
|
||||
OnClick="() => Delete(context)">
|
||||
</WButton>
|
||||
</Template>
|
||||
</Column>
|
||||
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LazyLoader>
|
||||
</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 ToastService.Success(SmartTranslateService.Translate("Successfully deleted website"));
|
||||
await LazyLoader.Reload();
|
||||
}
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
@page "/admin/websites/new"
|
||||
|
||||
@using Blazored.Typeahead
|
||||
@using Logging.Net
|
||||
@using Moonlight.App.Database.Entities
|
||||
@using Moonlight.App.Repositories
|
||||
@using Moonlight.App.Services
|
||||
@using Moonlight.App.Services.Interop
|
||||
|
||||
@inject UserRepository UserRepository
|
||||
@inject PleskServerRepository PleskServerRepository
|
||||
@inject SmartTranslateService SmartTranslateService
|
||||
@inject WebsiteService WebsiteService
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ToastService ToastService
|
||||
|
||||
<OnlyAdmin>
|
||||
<div class="d-flex flex-center">
|
||||
<LazyLoader Load="Load">
|
||||
<div class="card rounded-3 w-md-550px">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-center flex-column-fluid">
|
||||
<div class="form w-100 fv-plugins-bootstrap5 fv-plugins-framework">
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Base domain</TL>
|
||||
</label>
|
||||
<input @bind="BaseDomain" type="text" class="form-control"/>
|
||||
</div>
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Ftp password</TL>
|
||||
</label>
|
||||
<input @bind="FtpPassword" type="text" class="form-control"/>
|
||||
</div>
|
||||
<div class="fv-row mb-8">
|
||||
<div class="form-select">
|
||||
<BlazoredTypeahead SearchMethod="SearchUsers"
|
||||
@bind-Value="User">
|
||||
<SelectedTemplate>
|
||||
@(context.Email)
|
||||
</SelectedTemplate>
|
||||
<ResultTemplate>
|
||||
@(context.Email)
|
||||
</ResultTemplate>
|
||||
</BlazoredTypeahead>
|
||||
</div>
|
||||
</div>
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Plesk server</TL>
|
||||
</label>
|
||||
<WSelect TItem="PleskServer"
|
||||
Items="PleskServers"
|
||||
DisplayField="@(x => x.Name)"
|
||||
OnChange="@(x => PleskServer = x)">
|
||||
</WSelect>
|
||||
</div>
|
||||
<div class="fv-row mb-9">
|
||||
<WButton Text="@(SmartTranslateService.Translate("Create"))"
|
||||
WorkingText="@(SmartTranslateService.Translate("Creating"))"
|
||||
CssClasses="btn-success"
|
||||
OnClick="Create">
|
||||
</WButton>
|
||||
<a href="/admin/websites/servers" class="btn btn-primary">
|
||||
<TL>Back</TL>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LazyLoader>
|
||||
</div>
|
||||
</OnlyAdmin>
|
||||
|
||||
@code
|
||||
{
|
||||
// Cached data
|
||||
private User[] Users;
|
||||
private PleskServer[] PleskServers;
|
||||
|
||||
private User User;
|
||||
private PleskServer? PleskServer;
|
||||
private string BaseDomain = "";
|
||||
private string FtpPassword = "";
|
||||
|
||||
private Task Load(LazyLoader lazyLoader)
|
||||
{
|
||||
Users = UserRepository
|
||||
.Get()
|
||||
.ToArray();
|
||||
|
||||
User = Users.First();
|
||||
|
||||
PleskServers = PleskServerRepository
|
||||
.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)));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task Create()
|
||||
{
|
||||
await WebsiteService.Create(User, BaseDomain, FtpPassword, PleskServer);
|
||||
|
||||
await ToastService.Success(SmartTranslateService.Translate("Website successfully created"));
|
||||
NavigationManager.NavigateTo("/admin/websites");
|
||||
}
|
||||
}
|
|
@ -1,58 +0,0 @@
|
|||
@page "/admin/websites/servers"
|
||||
|
||||
@using Moonlight.App.Repositories
|
||||
@using Moonlight.App.Services
|
||||
@using BlazorTable
|
||||
@using Moonlight.App.Database.Entities
|
||||
@using Moonlight.Shared.Components.Navigations
|
||||
|
||||
@inject PleskServerRepository PleskServerRepository
|
||||
@inject SmartTranslateService SmartTranslateService
|
||||
|
||||
<OnlyAdmin>
|
||||
<AdminWebsiteNavigation Index="1" />
|
||||
|
||||
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||
<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-layer-plus"></i>
|
||||
<TL>Add new plesk server</TL>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body pt-0">
|
||||
<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("Base url"))" Field="@(x => x.BaseUrl)" Sortable="true" Filterable="true"/>
|
||||
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</LazyLoader>
|
||||
</OnlyAdmin>
|
||||
|
||||
@code
|
||||
{
|
||||
private LazyLoader LazyLoader;
|
||||
|
||||
private PleskServer[] PleskServers;
|
||||
|
||||
private Task Load(LazyLoader lazyLoader)
|
||||
{
|
||||
PleskServers = PleskServerRepository
|
||||
.Get()
|
||||
.ToArray();
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
@page "/admin/websites/servers/new"
|
||||
@using Moonlight.App.Repositories
|
||||
@using Moonlight.App.Services
|
||||
@using Microsoft.AspNetCore.Components
|
||||
@using Moonlight.App.Database.Entities
|
||||
|
||||
@inject PleskServerRepository PleskServerRepository
|
||||
@inject SmartTranslateService SmartTranslateService
|
||||
@inject NavigationManager NavigationManager
|
||||
|
||||
<OnlyAdmin>
|
||||
<div class="d-flex flex-center">
|
||||
<div class="card rounded-3 w-md-550px">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-center flex-column-fluid">
|
||||
<div class="form w-100 fv-plugins-bootstrap5 fv-plugins-framework">
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Name</TL>
|
||||
</label>
|
||||
<input @bind="NewServer.Name" type="text" placeholder="@(SmartTranslateService.Translate("Name"))" class="form-control bg-transparent">
|
||||
</div>
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Base url</TL>
|
||||
</label>
|
||||
<input @bind="NewServer.BaseUrl" type="text" placeholder="@(SmartTranslateService.Translate("Base url"))" class="form-control bg-transparent">
|
||||
</div>
|
||||
<div class="fv-row mb-8">
|
||||
<label class="form-label">
|
||||
<TL>Api key</TL>
|
||||
</label>
|
||||
<input @bind="NewServer.ApiKey" type="text" placeholder="@(SmartTranslateService.Translate("Api key"))" class="form-control bg-transparent">
|
||||
</div>
|
||||
<div class="fv-row mb-9">
|
||||
<WButton Text="@(SmartTranslateService.Translate("Create"))"
|
||||
WorkingText="@(SmartTranslateService.Translate("Creating"))"
|
||||
CssClasses="btn-success"
|
||||
OnClick="Create">
|
||||
</WButton>
|
||||
<a href="/admin/websites/servers" class="btn btn-primary">
|
||||
<TL>Back</TL>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</OnlyAdmin>
|
||||
|
||||
@code
|
||||
{
|
||||
private PleskServer NewServer = new();
|
||||
|
||||
private Task Create()
|
||||
{
|
||||
PleskServerRepository.Add(NewServer);
|
||||
|
||||
NavigationManager.NavigateTo("/admin/websites/servers");
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
|
@ -394,14 +394,3 @@ Discord id;Discord id
|
|||
Discord username;Discord username
|
||||
Discord discriminator;Discord discriminator
|
||||
The Name field is required.;The Name field is required.
|
||||
Plesk servers;Plesk servers
|
||||
Add new plesk server;Add new plesk server
|
||||
Base url;Base url
|
||||
Api key;Api key
|
||||
Add new website;Add new website
|
||||
Plesk id;Plesk id
|
||||
Plesk server;Plesk server
|
||||
Base domain;Base domain
|
||||
Ftp password;Ftp password
|
||||
Website successfully created;Website successfully created
|
||||
Successfully deleted website;Successfully deleted website
|
Loading…
Reference in a new issue