Added plesk module. Implemented create and delete actions
This commit is contained in:
@@ -5,4 +5,5 @@ public class PleskServer
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string BaseUrl { get; set; } = "";
|
public string BaseUrl { get; set; } = "";
|
||||||
public string ApiKey { get; set; } = "";
|
public string ApiKey { get; set; } = "";
|
||||||
|
public string Name { get; set; } = "";
|
||||||
}
|
}
|
||||||
@@ -3,11 +3,8 @@
|
|||||||
public class Website
|
public class Website
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int InternalAaPanelId { get; set; }
|
public int PleskId { get; set; }
|
||||||
public AaPanel AaPanel { get; set; }
|
|
||||||
public User Owner { get; set; }
|
public User Owner { get; set; }
|
||||||
public string DomainName { get; set; }
|
public PleskServer PleskServer { get; set; }
|
||||||
public string PhpVersion { get; set; }
|
public string BaseDomain { get; set; }
|
||||||
public string FtpUsername { get; set; }
|
|
||||||
public string FtpPassword { get; set; }
|
|
||||||
}
|
}
|
||||||
1089
Moonlight/App/Database/Migrations/20230322093852_AddedNameToPleskServer.Designer.cs
generated
Normal file
1089
Moonlight/App/Database/Migrations/20230322093852_AddedNameToPleskServer.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1073
Moonlight/App/Database/Migrations/20230322094525_SwitchedToPleskModel.Designer.cs
generated
Normal file
1073
Moonlight/App/Database/Migrations/20230322094525_SwitchedToPleskModel.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,124 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1077
Moonlight/App/Database/Migrations/20230323084631_AddedBaseDomainToWebsite.Designer.cs
generated
Normal file
1077
Moonlight/App/Database/Migrations/20230323084631_AddedBaseDomainToWebsite.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,29 @@
|
|||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -460,6 +460,10 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("PleskServers");
|
b.ToTable("PleskServers");
|
||||||
@@ -814,37 +818,25 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
.ValueGeneratedOnAdd()
|
.ValueGeneratedOnAdd()
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<int>("AaPanelId")
|
b.Property<string>("BaseDomain")
|
||||||
.HasColumnType("int");
|
|
||||||
|
|
||||||
b.Property<string>("DomainName")
|
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("longtext");
|
.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")
|
b.Property<int>("OwnerId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<string>("PhpVersion")
|
b.Property<int>("PleskId")
|
||||||
.IsRequired()
|
.HasColumnType("int");
|
||||||
.HasColumnType("longtext");
|
|
||||||
|
b.Property<int>("PleskServerId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.HasIndex("AaPanelId");
|
|
||||||
|
|
||||||
b.HasIndex("OwnerId");
|
b.HasIndex("OwnerId");
|
||||||
|
|
||||||
|
b.HasIndex("PleskServerId");
|
||||||
|
|
||||||
b.ToTable("Websites");
|
b.ToTable("Websites");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1034,21 +1026,21 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Website", b =>
|
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")
|
b.HasOne("Moonlight.App.Database.Entities.User", "Owner")
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey("OwnerId")
|
.HasForeignKey("OwnerId")
|
||||||
.OnDelete(DeleteBehavior.Cascade)
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
.IsRequired();
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("AaPanel");
|
b.HasOne("Moonlight.App.Database.Entities.PleskServer", "PleskServer")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PleskServerId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
b.Navigation("Owner");
|
b.Navigation("Owner");
|
||||||
|
|
||||||
|
b.Navigation("PleskServer");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.Image", b =>
|
||||||
|
|||||||
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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
120
Moonlight/App/Helpers/PleskApiHelper.cs
Normal file
120
Moonlight/App/Helpers/PleskApiHelper.cs
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
42
Moonlight/App/Models/Plesk/Requests/CreateDomain.cs
Normal file
42
Moonlight/App/Models/Plesk/Requests/CreateDomain.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
39
Moonlight/App/Models/Plesk/Resources/Client.cs
Normal file
39
Moonlight/App/Models/Plesk/Resources/Client.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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; }
|
||||||
|
}
|
||||||
12
Moonlight/App/Models/Plesk/Resources/Identifier.cs
Normal file
12
Moonlight/App/Models/Plesk/Resources/Identifier.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
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,7 +1,9 @@
|
|||||||
using aaPanelSharp;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Moonlight.App.Database.Entities;
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Exceptions;
|
using Moonlight.App.Exceptions;
|
||||||
|
using Moonlight.App.Helpers;
|
||||||
|
using Moonlight.App.Models.Plesk.Requests;
|
||||||
|
using Moonlight.App.Models.Plesk.Resources;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
|
|
||||||
namespace Moonlight.App.Services;
|
namespace Moonlight.App.Services;
|
||||||
@@ -9,31 +11,100 @@ namespace Moonlight.App.Services;
|
|||||||
public class WebsiteService
|
public class WebsiteService
|
||||||
{
|
{
|
||||||
private readonly WebsiteRepository WebsiteRepository;
|
private readonly WebsiteRepository WebsiteRepository;
|
||||||
|
private readonly PleskServerRepository PleskServerRepository;
|
||||||
|
private readonly PleskApiHelper PleskApiHelper;
|
||||||
|
|
||||||
public WebsiteService(WebsiteRepository websiteRepository)
|
public WebsiteService(WebsiteRepository websiteRepository, PleskServerRepository pleskServerRepository,
|
||||||
|
PleskApiHelper pleskApiHelper)
|
||||||
{
|
{
|
||||||
WebsiteRepository = websiteRepository;
|
WebsiteRepository = websiteRepository;
|
||||||
|
PleskServerRepository = pleskServerRepository;
|
||||||
|
PleskApiHelper = pleskApiHelper;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Website Create(AaPanel aaPanel, User user, string name)
|
public async Task<Website> Create(User owner, string baseDomain, string ftpPassword, PleskServer? ps = null)
|
||||||
{
|
{
|
||||||
if (WebsiteRepository.Get().Any(x => x.DomainName == name))
|
var pleskServer = ps ?? PleskServerRepository.Get().FirstOrDefault();
|
||||||
throw new DisplayException("A website with this domain has already been created");
|
|
||||||
|
|
||||||
var access = new aaPanel(aaPanel.Url, aaPanel.Key);
|
if (pleskServer == null)
|
||||||
return null;
|
throw new DisplayException("No plesk server found to deploy the website");
|
||||||
}
|
|
||||||
|
|
||||||
private aaPanel CreateApiAccess(Website website)
|
|
||||||
{
|
|
||||||
if (website.AaPanel == null)
|
|
||||||
{
|
|
||||||
website = WebsiteRepository
|
|
||||||
.Get()
|
|
||||||
.Include(x => x.AaPanel)
|
|
||||||
.First(x => x.Id == website.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new aaPanel(website.AaPanel.Url, website.AaPanel.Key);
|
var website = WebsiteRepository.Add(new Website()
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,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>();
|
||||||
|
|||||||
43
Moonlight/Shared/Components/Forms/WSelect.razor
Normal file
43
Moonlight/Shared/Components/Forms/WSelect.razor
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
@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;
|
||||||
|
}
|
||||||
@@ -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">
|
||||||
|
|||||||
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 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
122
Moonlight/Shared/Views/Admin/Websites/New.razor
Normal file
122
Moonlight/Shared/Views/Admin/Websites/New.razor
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
@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");
|
||||||
|
}
|
||||||
|
}
|
||||||
58
Moonlight/Shared/Views/Admin/Websites/Servers/Index.razor
Normal file
58
Moonlight/Shared/Views/Admin/Websites/Servers/Index.razor
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
Moonlight/Shared/Views/Admin/Websites/Servers/New.razor
Normal file
64
Moonlight/Shared/Views/Admin/Websites/Servers/New.razor
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
@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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -393,3 +393,14 @@ Successfully updated user;Successfully updated user
|
|||||||
Discord id;Discord id
|
Discord id;Discord id
|
||||||
Discord username;Discord username
|
Discord username;Discord username
|
||||||
Discord discriminator;Discord discriminator
|
Discord discriminator;Discord discriminator
|
||||||
|
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
|
||||||
|
|||||||
Reference in New Issue
Block a user