Started adding basic support for servers
This commit is contained in:
parent
ac8773c363
commit
4d058649db
11 changed files with 1601 additions and 0 deletions
|
@ -106,5 +106,7 @@ namespace LANCommander.Data
|
||||||
public DbSet<Key>? Keys { get; set; }
|
public DbSet<Key>? Keys { get; set; }
|
||||||
|
|
||||||
public DbSet<GameSave>? GameSaves { get; set; }
|
public DbSet<GameSave>? GameSaves { get; set; }
|
||||||
|
|
||||||
|
public DbSet<Server>? Servers { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
15
LANCommander/Data/Models/Server.cs
Normal file
15
LANCommander/Data/Models/Server.cs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
namespace LANCommander.Data.Models
|
||||||
|
{
|
||||||
|
public class Server : BaseModel
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string Arguments { get; set; }
|
||||||
|
public string WorkingDirectory { get; set; }
|
||||||
|
|
||||||
|
public string OnStartScriptPath { get; set; }
|
||||||
|
public string OnStopScriptPath { get; set; }
|
||||||
|
|
||||||
|
public bool Autostart { get; set; }
|
||||||
|
}
|
||||||
|
}
|
1246
LANCommander/Migrations/20230317234303_AddBasicServerModel.Designer.cs
generated
Normal file
1246
LANCommander/Migrations/20230317234303_AddBasicServerModel.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace LANCommander.Migrations
|
||||||
|
{
|
||||||
|
public partial class AddBasicServerModel : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Servers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "TEXT", nullable: false),
|
||||||
|
Name = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
Path = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
Arguments = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
WorkingDirectory = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
OnStartScriptPath = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
OnStopScriptPath = table.Column<string>(type: "TEXT", nullable: false),
|
||||||
|
Autostart = table.Column<bool>(type: "INTEGER", nullable: false),
|
||||||
|
CreatedOn = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||||
|
CreatedById = table.Column<Guid>(type: "TEXT", nullable: true),
|
||||||
|
UpdatedOn = table.Column<DateTime>(type: "TEXT", nullable: false),
|
||||||
|
UpdatedById = table.Column<Guid>(type: "TEXT", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Servers", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Servers_AspNetUsers_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Servers_AspNetUsers_UpdatedById",
|
||||||
|
column: x => x.UpdatedById,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Servers_CreatedById",
|
||||||
|
table: "Servers",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Servers_UpdatedById",
|
||||||
|
table: "Servers",
|
||||||
|
column: "UpdatedById");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Servers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -575,6 +575,60 @@ namespace LANCommander.Migrations
|
||||||
b.ToTable("Scripts");
|
b.ToTable("Scripts");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LANCommander.Data.Models.Server", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Arguments")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<bool>("Autostart")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<Guid?>("CreatedById")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedOn")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("OnStartScriptPath")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("OnStopScriptPath")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("Path")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UpdatedById")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedOn")
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.Property<string>("WorkingDirectory")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedById");
|
||||||
|
|
||||||
|
b.HasIndex("UpdatedById");
|
||||||
|
|
||||||
|
b.ToTable("Servers");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>
|
modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
@ -1079,6 +1133,21 @@ namespace LANCommander.Migrations
|
||||||
b.Navigation("UpdatedBy");
|
b.Navigation("UpdatedBy");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("LANCommander.Data.Models.Server", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("LANCommander.Data.Models.User", "CreatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatedById");
|
||||||
|
|
||||||
|
b.HasOne("LANCommander.Data.Models.User", "UpdatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UpdatedById");
|
||||||
|
|
||||||
|
b.Navigation("CreatedBy");
|
||||||
|
|
||||||
|
b.Navigation("UpdatedBy");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>
|
modelBuilder.Entity("LANCommander.Data.Models.Tag", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("LANCommander.Data.Models.User", "CreatedBy")
|
b.HasOne("LANCommander.Data.Models.User", "CreatedBy")
|
||||||
|
|
66
LANCommander/Pages/Servers/Edit.razor
Normal file
66
LANCommander/Pages/Servers/Edit.razor
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
@page "/Servers/{id:guid}/Edit"
|
||||||
|
@page "/Servers/Add"
|
||||||
|
@inject ServerService ServerService
|
||||||
|
@inject IMessageService MessageService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<Card Title="Server Details">
|
||||||
|
<Body>
|
||||||
|
<Form Model="@Server" Layout="@FormLayout.Vertical">
|
||||||
|
<FormItem Label="Name">
|
||||||
|
<Input @bind-Value="@context.Name" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem Label="Path">
|
||||||
|
<Input @bind-Value="@context.Path" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem Label="Arguments">
|
||||||
|
<Input @bind-Value="@context.Arguments" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem Label="Working Directory">
|
||||||
|
<Input @bind-Value="@context.WorkingDirectory" />
|
||||||
|
</FormItem>
|
||||||
|
<FormItem>
|
||||||
|
<Button Type="@ButtonType.Primary" OnClick="Save" Icon="@IconType.Fill.Save">Save</Button>
|
||||||
|
</FormItem>
|
||||||
|
</Form>
|
||||||
|
</Body>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
[Parameter] public Guid Id { get; set; }
|
||||||
|
|
||||||
|
Server Server;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
if (Id == Guid.Empty)
|
||||||
|
Server = new Server();
|
||||||
|
else
|
||||||
|
Server = await ServerService.Get(Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Save()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Server.Id != Guid.Empty)
|
||||||
|
{
|
||||||
|
Server = await ServerService.Update(Server);
|
||||||
|
|
||||||
|
await MessageService.Success("Server updated!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Server = await ServerService.Add(Server);
|
||||||
|
|
||||||
|
await MessageService.Success("Server added!");
|
||||||
|
|
||||||
|
NavigationManager.NavigateTo($"/Servers/{Server.Id}/Edit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
await MessageService.Error("Could not save!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
88
LANCommander/Pages/Servers/Index.razor
Normal file
88
LANCommander/Pages/Servers/Index.razor
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
@page "/Servers"
|
||||||
|
@attribute [Authorize]
|
||||||
|
@inject ServerService ServerService
|
||||||
|
@inject ServerProcessService ServerProcessService
|
||||||
|
@inject NavigationManager NavigationManager
|
||||||
|
|
||||||
|
<PageHeader Title="Servers">
|
||||||
|
<PageHeaderExtra>
|
||||||
|
<Button OnClick="() => Add()" Type="@ButtonType.Primary">Add Server</Button>
|
||||||
|
</PageHeaderExtra>
|
||||||
|
</PageHeader>
|
||||||
|
|
||||||
|
<Table TItem="Server" DataSource="@Servers" Loading="@Loading">
|
||||||
|
<PropertyColumn Property="s => s.Name" Sortable />
|
||||||
|
<PropertyColumn Property="s => s.CreatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable />
|
||||||
|
<PropertyColumn Property="s => s.CreatedBy" Sortable>
|
||||||
|
@context.CreatedBy?.UserName
|
||||||
|
</PropertyColumn>
|
||||||
|
<PropertyColumn Property="g => g.UpdatedOn" Format="MM/dd/yyyy hh:mm tt" Sortable />
|
||||||
|
<PropertyColumn Property="g => g.UpdatedBy" Sortable>
|
||||||
|
@context.UpdatedBy?.UserName
|
||||||
|
</PropertyColumn>
|
||||||
|
<ActionColumn Title="">
|
||||||
|
<Space Direction="DirectionVHType.Horizontal">
|
||||||
|
<SpaceItem>
|
||||||
|
<Button OnClick="() => Edit(context)">Edit</Button>
|
||||||
|
<Button OnClick="() => Start(context)">Start</Button>
|
||||||
|
<Button OnClick="() => Stop(context)">Stop</Button>
|
||||||
|
</SpaceItem>
|
||||||
|
<SpaceItem>
|
||||||
|
<Popconfirm OnConfirm="() => Delete(context)" Title="Are you sure you want to delete this game?">
|
||||||
|
<Button Icon="@IconType.Outline.Close" Type="@ButtonType.Text" Danger />
|
||||||
|
</Popconfirm>
|
||||||
|
</SpaceItem>
|
||||||
|
</Space>
|
||||||
|
</ActionColumn>
|
||||||
|
</Table>
|
||||||
|
|
||||||
|
@code {
|
||||||
|
IEnumerable<Server> Servers { get; set; } = new List<Server>();
|
||||||
|
|
||||||
|
bool Loading = true;
|
||||||
|
|
||||||
|
protected override void OnAfterRender(bool firstRender)
|
||||||
|
{
|
||||||
|
if (firstRender)
|
||||||
|
{
|
||||||
|
Servers = ServerService.Get().OrderBy(s => s.Name).ToList();
|
||||||
|
|
||||||
|
Loading = false;
|
||||||
|
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Add()
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo("/Servers/Add");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Edit(Server server)
|
||||||
|
{
|
||||||
|
NavigationManager.NavigateTo($"/Servers/{server.Id}/Edit");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start(Server server)
|
||||||
|
{
|
||||||
|
ServerProcessService.StartServer(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Stop(Server server)
|
||||||
|
{
|
||||||
|
ServerProcessService.StopServer(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Delete(Server server)
|
||||||
|
{
|
||||||
|
Servers = new List<Server>();
|
||||||
|
|
||||||
|
Loading = true;
|
||||||
|
|
||||||
|
await ServerService.Delete(server);
|
||||||
|
|
||||||
|
Servers = ServerService.Get().OrderBy(s => s.Name).ToList();
|
||||||
|
|
||||||
|
Loading = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -78,6 +78,7 @@ builder.Services.AddControllers().AddJsonOptions(x =>
|
||||||
x.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
|
x.JsonSerializerOptions.ReferenceHandler = System.Text.Json.Serialization.ReferenceHandler.IgnoreCycles;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddFusionCache();
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
|
@ -108,6 +109,9 @@ builder.Services.AddScoped<KeyService>();
|
||||||
builder.Services.AddScoped<TagService>();
|
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.AddSingleton<ServerProcessService>();
|
||||||
|
|
||||||
if (settings.Beacon)
|
if (settings.Beacon)
|
||||||
builder.Services.AddHostedService<BeaconService>();
|
builder.Services.AddHostedService<BeaconService>();
|
||||||
|
|
33
LANCommander/Services/ServerProcessService.cs
Normal file
33
LANCommander/Services/ServerProcessService.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using LANCommander.Data.Models;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace LANCommander.Services
|
||||||
|
{
|
||||||
|
public class ServerProcessService
|
||||||
|
{
|
||||||
|
public Dictionary<Guid, Process> Processes = new Dictionary<Guid, Process>();
|
||||||
|
public Dictionary<Guid, int> Threads { get; set; } = new Dictionary<Guid, int>();
|
||||||
|
|
||||||
|
public async Task StartServer(Server server)
|
||||||
|
{
|
||||||
|
var process = new Process();
|
||||||
|
|
||||||
|
process.StartInfo.FileName = server.Path;
|
||||||
|
process.StartInfo.WorkingDirectory = server.WorkingDirectory;
|
||||||
|
process.StartInfo.Arguments = server.Arguments;
|
||||||
|
process.StartInfo.UseShellExecute = true;
|
||||||
|
|
||||||
|
process.Start();
|
||||||
|
|
||||||
|
Processes[server.Id] = process;
|
||||||
|
|
||||||
|
await process.WaitForExitAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopServer(Server server)
|
||||||
|
{
|
||||||
|
if (Processes.ContainsKey(server.Id))
|
||||||
|
Processes[server.Id].Kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
16
LANCommander/Services/ServerService.cs
Normal file
16
LANCommander/Services/ServerService.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using LANCommander.Data;
|
||||||
|
using LANCommander.Data.Models;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using ZiggyCreatures.Caching.Fusion;
|
||||||
|
|
||||||
|
namespace LANCommander.Services
|
||||||
|
{
|
||||||
|
public class ServerService : BaseDatabaseService<Server>
|
||||||
|
{
|
||||||
|
private IFusionCache Cache;
|
||||||
|
public ServerService(DatabaseContext dbContext, IHttpContextAccessor httpContextAccessor, IFusionCache cache) : base(dbContext, httpContextAccessor)
|
||||||
|
{
|
||||||
|
Cache = cache;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Horizontal">
|
<Menu Theme="MenuTheme.Dark" Mode="MenuMode.Horizontal">
|
||||||
<MenuItem RouterLink="/Dashboard">Dashboard</MenuItem>
|
<MenuItem RouterLink="/Dashboard">Dashboard</MenuItem>
|
||||||
<MenuItem RouterLink="/Games">Games</MenuItem>
|
<MenuItem RouterLink="/Games">Games</MenuItem>
|
||||||
|
<MenuItem RouterLink="/Servers">Servers</MenuItem>
|
||||||
<MenuItem RouterLink="/Settings">Settings</MenuItem>
|
<MenuItem RouterLink="/Settings">Settings</MenuItem>
|
||||||
</Menu>
|
</Menu>
|
||||||
</Header>
|
</Header>
|
||||||
|
|
Loading…
Add table
Reference in a new issue