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);
builder.Entity<Server>()
.HasMany<ServerLog>()
.HasMany<ServerConsole>()
.WithOne(sl => sl.Server)
.IsRequired(true)
.OnDelete(DeleteBehavior.Cascade);
@ -121,5 +121,7 @@ namespace LANCommander.Data
public DbSet<GameSave>? GameSaves { 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")]
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")
.HasColumnType("TEXT");
b.Property<string>("Host")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Password")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Path")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Port")
.HasColumnType("INTEGER");
b.Property<Guid?>("ServerId")
.IsRequired()
.HasColumnType("TEXT");
@ -710,6 +721,9 @@ namespace LANCommander.Migrations
b.Property<Guid?>("ServerId1")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid?>("UpdatedById")
.HasColumnType("TEXT");
@ -726,7 +740,7 @@ namespace LANCommander.Migrations
b.HasIndex("UpdatedById");
b.ToTable("ServerLog");
b.ToTable("ServerConsoles");
});
modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>

View File

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

View File

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

View File

@ -17,7 +17,7 @@
@if (Server != null && Server.Id != Guid.Empty)
{
<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>
}
@ -95,7 +95,7 @@
}
<FormItem>
<ServerLogEditor @bind-Value="Server.ServerLogs" ServerId="Id" />
<ServerConsoleEditor @bind-Value="Server.ServerConsoles" ServerId="Id" />
</FormItem>
<FormItem>
@ -106,7 +106,7 @@
@if (Panel == "Console")
{
<Console ServerId="@Server.Id" ServerLogId="@LogId" />
<Console ServerId="@Server.Id" ServerConsoleId="@LogId" />
}
@if (Panel == "Files")

View File

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

View File

@ -4,9 +4,9 @@ using System.Diagnostics;
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)
{

View File

@ -1,4 +1,5 @@
using LANCommander.Data.Models;
using LANCommander.Data.Enums;
using LANCommander.Data.Models;
using LANCommander.Hubs;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
@ -21,26 +22,26 @@ namespace LANCommander.Services
public class ServerLogEventArgs : EventArgs
{
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;
Log = log;
Log = console;
}
}
public class LogMonitor : IDisposable
public class LogFileMonitor : IDisposable
{
private ManualResetEvent Latch;
private FileStream FileStream;
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();
@ -73,7 +74,7 @@ namespace LANCommander.Services
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));
}
@ -101,7 +102,7 @@ namespace LANCommander.Services
{
public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>();
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 event OnLogHandler OnLog;
@ -149,9 +150,9 @@ namespace LANCommander.Services
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();
@ -167,20 +168,20 @@ namespace LANCommander.Services
process.Kill();
}
if (LogMonitors.ContainsKey(server.Id))
if (LogFileMonitors.ContainsKey(server.Id))
{
LogMonitors[server.Id].Dispose();
LogMonitors.Remove(server.Id);
LogFileMonitors[server.Id].Dispose();
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);
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);
}
}