Rename ServerLog to ServerConsole. Add console type and RCON properties to model

dhcp-server
Pat Hartl 2023-08-17 19:55:46 -05:00
parent 29ae9157ca
commit da017acab4
14 changed files with 1748 additions and 59 deletions

View File

@ -100,7 +100,7 @@ namespace LANCommander.Data
.OnDelete(DeleteBehavior.NoAction); .OnDelete(DeleteBehavior.NoAction);
builder.Entity<Server>() builder.Entity<Server>()
.HasMany<ServerLog>() .HasMany<ServerConsole>()
.WithOne(sl => sl.Server) .WithOne(sl => sl.Server)
.IsRequired(true) .IsRequired(true)
.OnDelete(DeleteBehavior.Cascade); .OnDelete(DeleteBehavior.Cascade);
@ -121,5 +121,7 @@ namespace LANCommander.Data
public DbSet<GameSave>? GameSaves { get; set; } public DbSet<GameSave>? GameSaves { get; set; }
public DbSet<Server>? Servers { get; set; } public DbSet<Server>? Servers { get; set; }
public DbSet<ServerConsole>? ServerConsoles { get; set; }
} }
} }

View File

@ -0,0 +1,11 @@
using System.ComponentModel.DataAnnotations;
namespace LANCommander.Data.Enums
{
public enum ServerConsoleType
{
[Display(Name = "Log File")]
LogFile,
RCON
}
}

View File

@ -23,6 +23,6 @@ namespace LANCommander.Data.Models
[InverseProperty("Servers")] [InverseProperty("Servers")]
public virtual Game? Game { get; set; } public virtual Game? Game { get; set; }
public virtual ICollection<ServerLog>? ServerLogs { get; set; } public virtual ICollection<ServerConsole>? ServerConsoles { get; set; }
} }
} }

View File

@ -0,0 +1,26 @@
using LANCommander.Data.Enums;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace LANCommander.Data.Models
{
public class ServerConsole : BaseModel
{
public string Name { get; set; } = "";
public ServerConsoleType Type { get; set; }
public string Path { get; set; } = "";
public string Host { get; set; } = "";
public int Port { get; set; }
// Change to a secure string at some point
public string Password { get; set; } = "";
public Guid? ServerId { get; set; }
[JsonIgnore]
[ForeignKey(nameof(ServerId))]
[InverseProperty("ServerConsoles")]
public virtual Server? Server { get; set; }
}
}

View File

@ -1,17 +0,0 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
namespace LANCommander.Data.Models
{
public class ServerLog : BaseModel
{
public string Name { get; set; } = "";
public string Path { get; set; } = "";
public Guid? ServerId { get; set; }
[JsonIgnore]
[ForeignKey(nameof(ServerId))]
[InverseProperty("ServerLogs")]
public virtual Server? Server { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,218 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LANCommander.Migrations
{
/// <inheritdoc />
public partial class AddRCON : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ServerLog_AspNetUsers_CreatedById",
table: "ServerLog");
migrationBuilder.DropForeignKey(
name: "FK_ServerLog_AspNetUsers_UpdatedById",
table: "ServerLog");
migrationBuilder.DropForeignKey(
name: "FK_ServerLog_Servers_ServerId",
table: "ServerLog");
migrationBuilder.DropForeignKey(
name: "FK_ServerLog_Servers_ServerId1",
table: "ServerLog");
migrationBuilder.DropPrimaryKey(
name: "PK_ServerLog",
table: "ServerLog");
migrationBuilder.RenameTable(
name: "ServerLog",
newName: "ServerConsoles");
migrationBuilder.RenameIndex(
name: "IX_ServerLog_UpdatedById",
table: "ServerConsoles",
newName: "IX_ServerConsoles_UpdatedById");
migrationBuilder.RenameIndex(
name: "IX_ServerLog_ServerId1",
table: "ServerConsoles",
newName: "IX_ServerConsoles_ServerId1");
migrationBuilder.RenameIndex(
name: "IX_ServerLog_ServerId",
table: "ServerConsoles",
newName: "IX_ServerConsoles_ServerId");
migrationBuilder.RenameIndex(
name: "IX_ServerLog_CreatedById",
table: "ServerConsoles",
newName: "IX_ServerConsoles_CreatedById");
migrationBuilder.AddColumn<string>(
name: "Host",
table: "ServerConsoles",
type: "TEXT",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "Password",
table: "ServerConsoles",
type: "TEXT",
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<int>(
name: "Port",
table: "ServerConsoles",
type: "INTEGER",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "Type",
table: "ServerConsoles",
type: "INTEGER",
nullable: false,
defaultValue: 0);
migrationBuilder.AddPrimaryKey(
name: "PK_ServerConsoles",
table: "ServerConsoles",
column: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerConsoles_AspNetUsers_CreatedById",
table: "ServerConsoles",
column: "CreatedById",
principalTable: "AspNetUsers",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerConsoles_AspNetUsers_UpdatedById",
table: "ServerConsoles",
column: "UpdatedById",
principalTable: "AspNetUsers",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerConsoles_Servers_ServerId",
table: "ServerConsoles",
column: "ServerId",
principalTable: "Servers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ServerConsoles_Servers_ServerId1",
table: "ServerConsoles",
column: "ServerId1",
principalTable: "Servers",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_ServerConsoles_AspNetUsers_CreatedById",
table: "ServerConsoles");
migrationBuilder.DropForeignKey(
name: "FK_ServerConsoles_AspNetUsers_UpdatedById",
table: "ServerConsoles");
migrationBuilder.DropForeignKey(
name: "FK_ServerConsoles_Servers_ServerId",
table: "ServerConsoles");
migrationBuilder.DropForeignKey(
name: "FK_ServerConsoles_Servers_ServerId1",
table: "ServerConsoles");
migrationBuilder.DropPrimaryKey(
name: "PK_ServerConsoles",
table: "ServerConsoles");
migrationBuilder.DropColumn(
name: "Host",
table: "ServerConsoles");
migrationBuilder.DropColumn(
name: "Password",
table: "ServerConsoles");
migrationBuilder.DropColumn(
name: "Port",
table: "ServerConsoles");
migrationBuilder.DropColumn(
name: "Type",
table: "ServerConsoles");
migrationBuilder.RenameTable(
name: "ServerConsoles",
newName: "ServerLog");
migrationBuilder.RenameIndex(
name: "IX_ServerConsoles_UpdatedById",
table: "ServerLog",
newName: "IX_ServerLog_UpdatedById");
migrationBuilder.RenameIndex(
name: "IX_ServerConsoles_ServerId1",
table: "ServerLog",
newName: "IX_ServerLog_ServerId1");
migrationBuilder.RenameIndex(
name: "IX_ServerConsoles_ServerId",
table: "ServerLog",
newName: "IX_ServerLog_ServerId");
migrationBuilder.RenameIndex(
name: "IX_ServerConsoles_CreatedById",
table: "ServerLog",
newName: "IX_ServerLog_CreatedById");
migrationBuilder.AddPrimaryKey(
name: "PK_ServerLog",
table: "ServerLog",
column: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerLog_AspNetUsers_CreatedById",
table: "ServerLog",
column: "CreatedById",
principalTable: "AspNetUsers",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerLog_AspNetUsers_UpdatedById",
table: "ServerLog",
column: "UpdatedById",
principalTable: "AspNetUsers",
principalColumn: "Id");
migrationBuilder.AddForeignKey(
name: "FK_ServerLog_Servers_ServerId",
table: "ServerLog",
column: "ServerId",
principalTable: "Servers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
migrationBuilder.AddForeignKey(
name: "FK_ServerLog_Servers_ServerId1",
table: "ServerLog",
column: "ServerId1",
principalTable: "Servers",
principalColumn: "Id");
}
}
}

View File

@ -695,14 +695,25 @@ namespace LANCommander.Migrations
b.Property<DateTime>("CreatedOn") b.Property<DateTime>("CreatedOn")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<string>("Host")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name") b.Property<string>("Name")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Path") b.Property<string>("Path")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Port")
.HasColumnType("INTEGER");
b.Property<Guid?>("ServerId") b.Property<Guid?>("ServerId")
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -710,6 +721,9 @@ namespace LANCommander.Migrations
b.Property<Guid?>("ServerId1") b.Property<Guid?>("ServerId1")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid?>("UpdatedById") b.Property<Guid?>("UpdatedById")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -726,7 +740,7 @@ namespace LANCommander.Migrations
b.HasIndex("UpdatedById"); b.HasIndex("UpdatedById");
b.ToTable("ServerLog"); b.ToTable("ServerConsoles");
}); });
modelBuilder.Entity("LANCommander.Data.Models.Tag", b => modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>

View File

@ -2,7 +2,7 @@
@using NLog; @using NLog;
@using XtermBlazor @using XtermBlazor
@inject ServerService ServerService @inject ServerService ServerService
@inject ServerLogService ServerLogService @inject ServerConsoleService ServerConsoleService
@inject ServerProcessService ServerProcessService @inject ServerProcessService ServerProcessService
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@implements IAsyncDisposable @implements IAsyncDisposable
@ -11,10 +11,11 @@
@code { @code {
[Parameter] public Guid ServerId { get; set; } [Parameter] public Guid ServerId { get; set; }
[Parameter] public Guid ServerLogId { get; set; } [Parameter] public Guid ServerConsoleId { get; set; }
Xterm? Terminal; Xterm? Terminal;
HubConnection? HubConnection; HubConnection? HubConnection;
ServerConsole ServerConsole;
TerminalOptions TerminalOptions = new TerminalOptions TerminalOptions TerminalOptions = new TerminalOptions
{ {
@ -29,13 +30,15 @@
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
ServerConsole = await ServerConsoleService.Get(ServerConsoleId);
HubConnection = new HubConnectionBuilder() HubConnection = new HubConnectionBuilder()
.WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver")) .WithUrl(NavigationManager.ToAbsoluteUri("/hubs/gameserver"))
.Build(); .Build();
HubConnection.On<Guid, Guid, string>("Log", (serverId, logId, message) => HubConnection.On<Guid, Guid, string>("Log", (serverId, logId, message) =>
{ {
if (serverId == ServerId && logId == ServerLogId) if (serverId == ServerId && logId == ServerConsoleId)
Terminal.WriteLine(message); Terminal.WriteLine(message);
}); });
@ -51,7 +54,7 @@
if (Terminal != null) if (Terminal != null)
await Terminal.InvokeAddonFunctionVoidAsync("xterm-addon-fit", "fit"); await Terminal.InvokeAddonFunctionVoidAsync("xterm-addon-fit", "fit");
var log = await ServerLogService.ReadLog(ServerLogId); var log = await ServerConsoleService.ReadLog(ServerConsoleId);
foreach (var line in log) foreach (var line in log)
{ {

View File

@ -4,7 +4,7 @@
<Space Direction="DirectionVHType.Vertical" Size="@("large")" Style="width: 100%"> <Space Direction="DirectionVHType.Vertical" Size="@("large")" Style="width: 100%">
<SpaceItem> <SpaceItem>
<Table TItem="ServerLog" DataSource="@Value" HidePagination="true"> <Table TItem="ServerConsole" DataSource="@Value" HidePagination="true">
<PropertyColumn Property="m => m.Name"> <PropertyColumn Property="m => m.Name">
<Input Type="text" @bind-Value="context.Name" /> <Input Type="text" @bind-Value="context.Name" />
</PropertyColumn> </PropertyColumn>
@ -14,7 +14,7 @@
<ActionColumn> <ActionColumn>
<Space Style="display: flex; justify-content: end"> <Space Style="display: flex; justify-content: end">
<SpaceItem> <SpaceItem>
<Button OnClick="() => RemoveLog(context)" Type="@ButtonType.Text" Danger Icon="@IconType.Outline.Close" /> <Button OnClick="() => RemoveConsole(context)" Type="@ButtonType.Text" Danger Icon="@IconType.Outline.Close" />
</SpaceItem> </SpaceItem>
</Space> </Space>
</ActionColumn> </ActionColumn>
@ -24,21 +24,21 @@
<SpaceItem> <SpaceItem>
<GridRow Justify="end"> <GridRow Justify="end">
<GridCol> <GridCol>
<Button OnClick="AddLog" Type="@ButtonType.Primary">Add Log</Button> <Button OnClick="AddConsole" Type="@ButtonType.Primary">Add Console</Button>
</GridCol> </GridCol>
</GridRow> </GridRow>
</SpaceItem> </SpaceItem>
</Space> </Space>
@code { @code {
[Parameter] public ICollection<ServerLog> Value { get; set; } [Parameter] public ICollection<ServerConsole> Value { get; set; }
[Parameter] public EventCallback<ICollection<ServerLog>> ValueChanged { get; set; } [Parameter] public EventCallback<ICollection<ServerConsole>> ValueChanged { get; set; }
[Parameter] public Guid ServerId { get; set; } [Parameter] public Guid ServerId { get; set; }
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
if (Value == null) if (Value == null)
Value = new List<ServerLog>(); Value = new List<ServerConsole>();
if (ValueChanged.HasDelegate) if (ValueChanged.HasDelegate)
await ValueChanged.InvokeAsync(Value); await ValueChanged.InvokeAsync(Value);
@ -46,12 +46,12 @@
StateHasChanged(); StateHasChanged();
} }
private async Task AddLog() private async Task AddConsole()
{ {
if (Value == null) if (Value == null)
Value = new List<ServerLog>(); Value = new List<ServerConsole>();
Value.Add(new ServerLog Value.Add(new ServerConsole
{ {
ServerId = ServerId ServerId = ServerId
}); });
@ -62,9 +62,9 @@
StateHasChanged(); StateHasChanged();
} }
private async Task RemoveLog(ServerLog log) private async Task RemoveConsole(ServerConsole console)
{ {
Value.Remove(log); Value.Remove(console);
if (ValueChanged.HasDelegate) if (ValueChanged.HasDelegate)
await ValueChanged.InvokeAsync(Value); await ValueChanged.InvokeAsync(Value);

View File

@ -17,7 +17,7 @@
@if (Server != null && Server.Id != Guid.Empty) @if (Server != null && Server.Id != Guid.Empty)
{ {
<SubMenu Key="sub1" Title="Console"> <SubMenu Key="sub1" Title="Console">
@foreach (var log in Server.ServerLogs) @foreach (var log in Server.ServerConsoles)
{ {
<MenuItem Key="@log.Id.ToString()" RouterLink="@($"/Servers/{Server.Id}/Console/{log.Id}")">@log.Name</MenuItem> <MenuItem Key="@log.Id.ToString()" RouterLink="@($"/Servers/{Server.Id}/Console/{log.Id}")">@log.Name</MenuItem>
} }
@ -95,7 +95,7 @@
} }
<FormItem> <FormItem>
<ServerLogEditor @bind-Value="Server.ServerLogs" ServerId="Id" /> <ServerConsoleEditor @bind-Value="Server.ServerConsoles" ServerId="Id" />
</FormItem> </FormItem>
<FormItem> <FormItem>
@ -106,7 +106,7 @@
@if (Panel == "Console") @if (Panel == "Console")
{ {
<Console ServerId="@Server.Id" ServerLogId="@LogId" /> <Console ServerId="@Server.Id" ServerConsoleId="@LogId" />
} }
@if (Panel == "Files") @if (Panel == "Files")

View File

@ -122,7 +122,7 @@ builder.Services.AddScoped<TagService>();
builder.Services.AddScoped<CompanyService>(); builder.Services.AddScoped<CompanyService>();
builder.Services.AddScoped<IGDBService>(); builder.Services.AddScoped<IGDBService>();
builder.Services.AddScoped<ServerService>(); builder.Services.AddScoped<ServerService>();
builder.Services.AddScoped<ServerLogService>(); builder.Services.AddScoped<ServerConsoleService>();
builder.Services.AddScoped<GameSaveService>(); builder.Services.AddScoped<GameSaveService>();
builder.Services.AddSingleton<ServerProcessService>(); builder.Services.AddSingleton<ServerProcessService>();

View File

@ -4,9 +4,9 @@ using System.Diagnostics;
namespace LANCommander.Services namespace LANCommander.Services
{ {
public class ServerLogService : BaseDatabaseService<ServerLog> public class ServerConsoleService : BaseDatabaseService<ServerConsole>
{ {
public ServerLogService(DatabaseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor) { } public ServerConsoleService(DatabaseContext dbContext, IHttpContextAccessor httpContextAccessor) : base(dbContext, httpContextAccessor) { }
public async Task<string[]> ReadLog(Guid logId) public async Task<string[]> ReadLog(Guid logId)
{ {

View File

@ -1,4 +1,5 @@
using LANCommander.Data.Models; using LANCommander.Data.Enums;
using LANCommander.Data.Models;
using LANCommander.Hubs; using LANCommander.Hubs;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -21,26 +22,26 @@ namespace LANCommander.Services
public class ServerLogEventArgs : EventArgs public class ServerLogEventArgs : EventArgs
{ {
public string Line { get; private set; } public string Line { get; private set; }
public ServerLog Log { get; private set; } public ServerConsole Log { get; private set; }
public ServerLogEventArgs(string line, ServerLog log) public ServerLogEventArgs(string line, ServerConsole console)
{ {
Line = line; Line = line;
Log = log; Log = console;
} }
} }
public class LogMonitor : IDisposable public class LogFileMonitor : IDisposable
{ {
private ManualResetEvent Latch; private ManualResetEvent Latch;
private FileStream FileStream; private FileStream FileStream;
private FileSystemWatcher FileSystemWatcher; private FileSystemWatcher FileSystemWatcher;
public LogMonitor(Server server, ServerLog serverLog, IHubContext<GameServerHub> hubContext) public LogFileMonitor(Server server, ServerConsole serverConsole, IHubContext<GameServerHub> hubContext)
{ {
var logPath = Path.Combine(server.WorkingDirectory, serverLog.Path); var logPath = Path.Combine(server.WorkingDirectory, serverConsole.Path);
if (File.Exists(serverLog.Path)) if (File.Exists(serverConsole.Path))
{ {
var lockMe = new object(); var lockMe = new object();
@ -73,7 +74,7 @@ namespace LANCommander.Services
while ((line = sr.ReadLine()) != null) while ((line = sr.ReadLine()) != null)
{ {
hubContext.Clients.All.SendAsync("Log", serverLog.ServerId, line); hubContext.Clients.All.SendAsync("Log", serverConsole.ServerId, line);
//OnLog?.Invoke(this, new ServerLogEventArgs(line, log)); //OnLog?.Invoke(this, new ServerLogEventArgs(line, log));
} }
@ -101,7 +102,7 @@ namespace LANCommander.Services
{ {
public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>(); public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>();
public Dictionary<Guid, int> Threads { get; set; } = new Dictionary<Guid, int>(); public Dictionary<Guid, int> Threads { get; set; } = new Dictionary<Guid, int>();
public Dictionary<Guid, LogMonitor> LogMonitors { get; set; } = new Dictionary<Guid, LogMonitor>(); public Dictionary<Guid, LogFileMonitor> LogFileMonitors { get; set; } = new Dictionary<Guid, LogFileMonitor>();
public delegate void OnLogHandler(object sender, ServerLogEventArgs e); public delegate void OnLogHandler(object sender, ServerLogEventArgs e);
public event OnLogHandler OnLog; public event OnLogHandler OnLog;
@ -149,9 +150,9 @@ namespace LANCommander.Services
Processes[server.Id] = process; Processes[server.Id] = process;
foreach (var log in server.ServerLogs) foreach (var logFile in server.ServerConsoles.Where(sc => sc.Type == ServerConsoleType.LogFile))
{ {
StartMonitoringLog(log, server); StartMonitoringLog(logFile, server);
} }
await process.WaitForExitAsync(); await process.WaitForExitAsync();
@ -167,20 +168,20 @@ namespace LANCommander.Services
process.Kill(); process.Kill();
} }
if (LogMonitors.ContainsKey(server.Id)) if (LogFileMonitors.ContainsKey(server.Id))
{ {
LogMonitors[server.Id].Dispose(); LogFileMonitors[server.Id].Dispose();
LogMonitors.Remove(server.Id); LogFileMonitors.Remove(server.Id);
} }
} }
private void StartMonitoringLog(ServerLog log, Server server) private void StartMonitoringLog(ServerConsole log, Server server)
{ {
var logPath = Path.Combine(server.WorkingDirectory, log.Path); var logPath = Path.Combine(server.WorkingDirectory, log.Path);
if (!LogMonitors.ContainsKey(server.Id)) if (!LogFileMonitors.ContainsKey(server.Id))
{ {
LogMonitors[server.Id] = new LogMonitor(server, log, HubContext); LogFileMonitors[server.Id] = new LogFileMonitor(server, log, HubContext);
} }
} }