Implemented frontend ddos detection view. Added missing translations
This commit is contained in:
@@ -41,6 +41,7 @@ public class DataContext : DbContext
|
|||||||
public DbSet<NotificationAction> NotificationActions { get; set; }
|
public DbSet<NotificationAction> NotificationActions { get; set; }
|
||||||
public DbSet<AaPanel> AaPanels { get; set; }
|
public DbSet<AaPanel> AaPanels { get; set; }
|
||||||
public DbSet<Website> Websites { get; set; }
|
public DbSet<Website> Websites { get; set; }
|
||||||
|
public DbSet<DdosAttack> DdosAttacks { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
11
Moonlight/App/Database/Entities/DdosAttack.cs
Normal file
11
Moonlight/App/Database/Entities/DdosAttack.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
public class DdosAttack
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public bool Ongoing { get; set; }
|
||||||
|
public long Data { get; set; }
|
||||||
|
public string Ip { get; set; } = "";
|
||||||
|
public Node Node { get; set; } = null!;
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
}
|
||||||
1066
Moonlight/App/Database/Migrations/20230320153817_AddedDdosAttacks.Designer.cs
generated
Normal file
1066
Moonlight/App/Database/Migrations/20230320153817_AddedDdosAttacks.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,53 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Moonlight.App.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddedDdosAttacks : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "DdosAttacks",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||||
|
Ongoing = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
Data = table.Column<long>(type: "bigint", nullable: false),
|
||||||
|
Ip = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
NodeId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_DdosAttacks", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_DdosAttacks_Nodes_NodeId",
|
||||||
|
column: x => x.NodeId,
|
||||||
|
principalTable: "Nodes",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_DdosAttacks_NodeId",
|
||||||
|
table: "DdosAttacks",
|
||||||
|
column: "NodeId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "DdosAttacks");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,6 +70,35 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
b.ToTable("Databases");
|
b.ToTable("Databases");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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 =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -819,6 +848,17 @@ namespace Moonlight.App.Database.Migrations
|
|||||||
b.Navigation("Owner");
|
b.Navigation("Owner");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DdosAttack", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Moonlight.App.Database.Entities.Node", "Node")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("NodeId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Node");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
modelBuilder.Entity("Moonlight.App.Database.Entities.DockerImage", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
b.HasOne("Moonlight.App.Database.Entities.Image", null)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Logging.Net;
|
using Logging.Net;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
using Moonlight.App.Http.Requests.Daemon;
|
using Moonlight.App.Http.Requests.Daemon;
|
||||||
using Moonlight.App.Repositories;
|
using Moonlight.App.Repositories;
|
||||||
using Moonlight.App.Services;
|
using Moonlight.App.Services;
|
||||||
@@ -12,11 +13,13 @@ public class DdosController : Controller
|
|||||||
{
|
{
|
||||||
private readonly NodeRepository NodeRepository;
|
private readonly NodeRepository NodeRepository;
|
||||||
private readonly MessageService MessageService;
|
private readonly MessageService MessageService;
|
||||||
|
private readonly DdosAttackRepository DdosAttackRepository;
|
||||||
|
|
||||||
public DdosController(NodeRepository nodeRepository, MessageService messageService)
|
public DdosController(NodeRepository nodeRepository, MessageService messageService, DdosAttackRepository ddosAttackRepository)
|
||||||
{
|
{
|
||||||
NodeRepository = nodeRepository;
|
NodeRepository = nodeRepository;
|
||||||
MessageService = messageService;
|
MessageService = messageService;
|
||||||
|
DdosAttackRepository = ddosAttackRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("update")]
|
[HttpPost("update")]
|
||||||
@@ -34,7 +37,17 @@ public class DdosController : Controller
|
|||||||
if (token != node.Token)
|
if (token != node.Token)
|
||||||
return Unauthorized();
|
return Unauthorized();
|
||||||
|
|
||||||
await MessageService.Emit("node.ddos", ddosStatus);
|
var ddosAttack = new DdosAttack()
|
||||||
|
{
|
||||||
|
Ongoing = ddosStatus.Ongoing,
|
||||||
|
Data = ddosStatus.Data,
|
||||||
|
Ip = ddosStatus.Ip,
|
||||||
|
Node = node
|
||||||
|
};
|
||||||
|
|
||||||
|
ddosAttack = DdosAttackRepository.Add(ddosAttack);
|
||||||
|
|
||||||
|
await MessageService.Emit("node.ddos", ddosAttack);
|
||||||
|
|
||||||
return Ok();
|
return Ok();
|
||||||
}
|
}
|
||||||
|
|||||||
39
Moonlight/App/Repositories/DdosAttackRepository.cs
Normal file
39
Moonlight/App/Repositories/DdosAttackRepository.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Moonlight.App.Database;
|
||||||
|
using Moonlight.App.Database.Entities;
|
||||||
|
|
||||||
|
namespace Moonlight.App.Repositories;
|
||||||
|
|
||||||
|
public class DdosAttackRepository
|
||||||
|
{
|
||||||
|
private readonly DataContext DataContext;
|
||||||
|
|
||||||
|
public DdosAttackRepository(DataContext dataContext)
|
||||||
|
{
|
||||||
|
DataContext = dataContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DbSet<DdosAttack> Get()
|
||||||
|
{
|
||||||
|
return DataContext.DdosAttacks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DdosAttack Add(DdosAttack ddosAttack)
|
||||||
|
{
|
||||||
|
var x = DataContext.DdosAttacks.Add(ddosAttack);
|
||||||
|
DataContext.SaveChanges();
|
||||||
|
return x.Entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(DdosAttack ddosAttack)
|
||||||
|
{
|
||||||
|
DataContext.DdosAttacks.Update(ddosAttack);
|
||||||
|
DataContext.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Delete(DdosAttack ddosAttack)
|
||||||
|
{
|
||||||
|
DataContext.DdosAttacks.Remove(ddosAttack);
|
||||||
|
DataContext.SaveChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -64,6 +64,7 @@ namespace Moonlight
|
|||||||
builder.Services.AddScoped<NotificationRepository>();
|
builder.Services.AddScoped<NotificationRepository>();
|
||||||
builder.Services.AddScoped<AaPanelRepository>();
|
builder.Services.AddScoped<AaPanelRepository>();
|
||||||
builder.Services.AddScoped<WebsiteRepository>();
|
builder.Services.AddScoped<WebsiteRepository>();
|
||||||
|
builder.Services.AddScoped<DdosAttackRepository>();
|
||||||
|
|
||||||
builder.Services.AddScoped<AuditLogEntryRepository>();
|
builder.Services.AddScoped<AuditLogEntryRepository>();
|
||||||
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
builder.Services.AddScoped<ErrorLogEntryRepository>();
|
||||||
|
|||||||
@@ -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/nodes">
|
||||||
|
<TL>Nodes</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/nodes/ddos">
|
||||||
|
<TL>DDos</TL>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
[Parameter]
|
||||||
|
public int Index { get; set; } = 0;
|
||||||
|
}
|
||||||
@@ -3,12 +3,12 @@
|
|||||||
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
<ul class="nav nav-stretch nav-line-tabs nav-line-tabs-2x border-transparent fs-5 fw-bold">
|
||||||
<li class="nav-item mt-2">
|
<li class="nav-item mt-2">
|
||||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/users">
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 0 ? "active" : "")" href="/admin/users">
|
||||||
Users
|
<TL>Users</TL>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item mt-2">
|
<li class="nav-item mt-2">
|
||||||
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/users/sessions">
|
<a class="nav-link text-active-primary ms-0 me-10 py-5 @(Index == 1 ? "active" : "")" href="/admin/users/sessions">
|
||||||
Sessions
|
<TL>Sessions</TL>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
100
Moonlight/Shared/Views/Admin/Nodes/Ddos.razor
Normal file
100
Moonlight/Shared/Views/Admin/Nodes/Ddos.razor
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
@page "/admin/nodes/ddos"
|
||||||
|
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
|
@using Moonlight.App.Repositories
|
||||||
|
@using BlazorTable
|
||||||
|
@using Microsoft.EntityFrameworkCore
|
||||||
|
@using Moonlight.App.Database.Entities
|
||||||
|
@using Moonlight.App.Helpers
|
||||||
|
@using Moonlight.App.Services
|
||||||
|
|
||||||
|
@implements IDisposable
|
||||||
|
|
||||||
|
@inject DdosAttackRepository DdosAttackRepository
|
||||||
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
@inject MessageService MessageService
|
||||||
|
|
||||||
|
<OnlyAdmin>
|
||||||
|
<AdminNodesNavigation Index="1"/>
|
||||||
|
|
||||||
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body pt-0">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<Table TableItem="DdosAttack" Items="DdosAttacks" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
||||||
|
<Column TableItem="DdosAttack" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="DdosAttack" Title="@(SmartTranslateService.Translate("Status"))" Field="@(x => x.Ongoing)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
@if (context.Ongoing)
|
||||||
|
{
|
||||||
|
<TL>DDos attack started</TL>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<TL>DDos attack stopped</TL>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="DdosAttack" Title="@(SmartTranslateService.Translate("Node"))" Field="@(x => x.Node)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/nodes/view/@(context.Id)">
|
||||||
|
@(context.Node.Name)
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="DdosAttack" Title="Ip" Field="@(x => x.Ip)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="DdosAttack" Title="@(SmartTranslateService.Translate("Status"))" Field="@(x => x.Ongoing)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
@if (context.Ongoing)
|
||||||
|
{
|
||||||
|
@(context.Data)
|
||||||
|
<TL> packets</TL>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
@(context.Data)
|
||||||
|
<span> MB</span>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="DdosAttack" Title="@(SmartTranslateService.Translate("Date"))" Field="@(x => x.Ongoing)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
@(Formatter.FormatDate(context.CreatedAt))
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
|
</OnlyAdmin>
|
||||||
|
|
||||||
|
@code
|
||||||
|
{
|
||||||
|
private DdosAttack[] DdosAttacks;
|
||||||
|
private LazyLoader LazyLoader;
|
||||||
|
|
||||||
|
protected override Task OnAfterRenderAsync(bool firstRender)
|
||||||
|
{
|
||||||
|
MessageService.Subscribe<Ddos, DdosAttack>("node.ddos", this, async attack => { Task.Run(async () => await LazyLoader.Reload()); });
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task Load(LazyLoader arg)
|
||||||
|
{
|
||||||
|
DdosAttacks = DdosAttackRepository
|
||||||
|
.Get()
|
||||||
|
.Include(x => x.Node)
|
||||||
|
.OrderByDescending(x => x.CreatedAt)
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
MessageService.Unsubscribe("node.ddos", this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
@using Moonlight.App.Repositories
|
@using Moonlight.App.Repositories
|
||||||
@using Moonlight.App.Database.Entities
|
@using Moonlight.App.Database.Entities
|
||||||
@using Moonlight.App.Models.Wings.Resources
|
@using Moonlight.App.Models.Wings.Resources
|
||||||
|
@using Moonlight.Shared.Components.Navigations
|
||||||
@using Moonlight.App.Services
|
@using Moonlight.App.Services
|
||||||
@using Moonlight.App.Services.Interop
|
@using Moonlight.App.Services.Interop
|
||||||
@using Logging.Net
|
@using Logging.Net
|
||||||
@@ -13,87 +14,87 @@
|
|||||||
@inject SmartTranslateService SmartTranslateService
|
@inject SmartTranslateService SmartTranslateService
|
||||||
|
|
||||||
<OnlyAdmin>
|
<OnlyAdmin>
|
||||||
<div class="row">
|
<AdminNodesNavigation 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>Nodes</TL>
|
|
||||||
</span>
|
|
||||||
</h3>
|
|
||||||
<div class="card-toolbar">
|
|
||||||
<a href="/admin/nodes/new" class="btn btn-sm btn-light-success">
|
|
||||||
<i class="bx bx-layer-plus"></i>
|
|
||||||
<TL>New node</TL>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="card-body pt-0">
|
|
||||||
@if (Nodes.Any())
|
|
||||||
{
|
|
||||||
<div class="table-responsive">
|
|
||||||
<Table TableItem="Node" Items="Nodes" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
|
||||||
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
|
|
||||||
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Status"))" Field="@(x => x.Id)" Sortable="true" Filterable="true">
|
|
||||||
<Template>
|
|
||||||
@{
|
|
||||||
var ss = StatusCache.ContainsKey(context) ? StatusCache[context] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@if (ss == null)
|
<LazyLoader @ref="LazyLoader" Load="Load">
|
||||||
{
|
<div class="card">
|
||||||
<span class="text-danger">Offline</span>
|
<div class="card-header border-0 pt-5">
|
||||||
}
|
<h3 class="card-title align-items-start flex-column">
|
||||||
else
|
<span class="card-label fw-bold fs-3 mb-1">
|
||||||
{
|
<TL>Nodes</TL>
|
||||||
<span class="text-success">Online (@(ss.Version))</span>
|
</span>
|
||||||
}
|
</h3>
|
||||||
</Template>
|
<div class="card-toolbar">
|
||||||
</Column>
|
<a href="/admin/nodes/new" class="btn btn-sm btn-light-success">
|
||||||
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Name)" Sortable="true" Filterable="true">
|
<i class="bx bx-layer-plus"></i>
|
||||||
<Template>
|
<TL>New node</TL>
|
||||||
<a href="/admin/nodes/view/@(context.Id)">@(context.Name)</a>
|
</a>
|
||||||
</Template>
|
|
||||||
</Column>
|
|
||||||
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Fqdn"))" Field="@(x => x.Fqdn)" Sortable="true" Filterable="true"/>
|
|
||||||
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
|
||||||
<Template>
|
|
||||||
<a href="/admin/nodes/edit/@(context.Id)">
|
|
||||||
@(SmartTranslateService.Translate("Edit"))
|
|
||||||
</a>
|
|
||||||
</Template>
|
|
||||||
</Column>
|
|
||||||
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
|
||||||
<Template>
|
|
||||||
<a href="/admin/nodes/setup/@(context.Id)">
|
|
||||||
@(SmartTranslateService.Translate("Setup"))
|
|
||||||
</a>
|
|
||||||
</Template>
|
|
||||||
</Column>
|
|
||||||
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
|
||||||
<Template>
|
|
||||||
<WButton Text="@(SmartTranslateService.Translate("Delete"))"
|
|
||||||
WorkingText="@(SmartTranslateService.Translate("Deleting"))"
|
|
||||||
CssClasses="btn-sm btn-danger"
|
|
||||||
OnClick="() => Delete(context)">
|
|
||||||
</WButton>
|
|
||||||
</Template>
|
|
||||||
</Column>
|
|
||||||
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
|
||||||
</Table>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
<div class="alert alert-info">
|
|
||||||
<TL>No nodes found</TL>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</LazyLoader>
|
<div class="card-body pt-0">
|
||||||
</div>
|
@if (Nodes.Any())
|
||||||
|
{
|
||||||
|
<div class="table-responsive">
|
||||||
|
<Table TableItem="Node" Items="Nodes" PageSize="25" TableClass="table table-row-bordered table-row-gray-100 align-middle gs-0 gy-3" TableHeadClass="fw-bold text-muted">
|
||||||
|
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Id"))" Field="@(x => x.Id)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Status"))" Field="@(x => x.Id)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
@{
|
||||||
|
var ss = StatusCache.ContainsKey(context) ? StatusCache[context] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@if (ss == null)
|
||||||
|
{
|
||||||
|
<span class="text-danger">Offline</span>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<span class="text-success">Online (@(ss.Version))</span>
|
||||||
|
}
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Name"))" Field="@(x => x.Name)" Sortable="true" Filterable="true">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/nodes/view/@(context.Id)">@(context.Name)</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Node" Title="@(SmartTranslateService.Translate("Fqdn"))" Field="@(x => x.Fqdn)" Sortable="true" Filterable="true"/>
|
||||||
|
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/nodes/edit/@(context.Id)">
|
||||||
|
@(SmartTranslateService.Translate("Edit"))
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<a href="/admin/nodes/setup/@(context.Id)">
|
||||||
|
@(SmartTranslateService.Translate("Setup"))
|
||||||
|
</a>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Column TableItem="Node" Title="" Field="@(x => x.Id)" Sortable="false" Filterable="false">
|
||||||
|
<Template>
|
||||||
|
<WButton Text="@(SmartTranslateService.Translate("Delete"))"
|
||||||
|
WorkingText="@(SmartTranslateService.Translate("Deleting"))"
|
||||||
|
CssClasses="btn-sm btn-danger"
|
||||||
|
OnClick="() => Delete(context)">
|
||||||
|
</WButton>
|
||||||
|
</Template>
|
||||||
|
</Column>
|
||||||
|
<Pager ShowPageNumber="true" ShowTotalCount="true"/>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="alert alert-info">
|
||||||
|
<TL>No nodes found</TL>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</LazyLoader>
|
||||||
</OnlyAdmin>
|
</OnlyAdmin>
|
||||||
|
|
||||||
@code
|
@code
|
||||||
|
|||||||
@@ -366,3 +366,11 @@ Docker containers running;Docker containers running
|
|||||||
details;details
|
details;details
|
||||||
1;1
|
1;1
|
||||||
2;2
|
2;2
|
||||||
|
DDos;DDos
|
||||||
|
No ddos attacks found;No ddos attacks found
|
||||||
|
Node;Node
|
||||||
|
Date;Date
|
||||||
|
DDos attack started;DDos attack started
|
||||||
|
packets;packets
|
||||||
|
DDos attack stopped;DDos attack stopped
|
||||||
|
packets; packets
|
||||||
|
|||||||
Reference in New Issue
Block a user