Add importing/exporting of redistributable and server to CLI

This commit is contained in:
Pat Hartl 2024-10-01 17:56:06 -05:00
parent 096b904748
commit 3d9749a9db
7 changed files with 187 additions and 7 deletions

View file

@ -8,7 +8,8 @@ using System.Threading.Tasks;
namespace LANCommander.Launcher.Models
{
public enum ImportArchiveType {
public enum ArchiveType
{
Game,
Redistributable,
Server
@ -66,17 +67,17 @@ namespace LANCommander.Launcher.Models
[Verb("Sync", HelpText = "Sync library items from the server")]
public class SyncCommandLineOptions { }
[Verb("Import", HelpText = "Upload and import an archive to the server (Admin Only)")]
[Verb("Import", HelpText = "Upload and import a game/redistributable/server to the server (Admin Only)")]
public class ImportCommandLineOptions
{
[Option("Path", HelpText = "Path to the archive file", Required = true)]
[Option("Path", HelpText = "Path to the import file", Required = true)]
public string Path { get; set; }
[Option("Type", HelpText = "The type of archive to import", Required = true)]
public ImportArchiveType Type { get; set; }
[Option("Type", HelpText = "The type of import file", Required = true)]
public ArchiveType Type { get; set; }
}
[Verb("Export", HelpText = "Export an archive from the server (Admin Only)")]
[Verb("Export", HelpText = "Export a game/redistributable/server from the server (Admin Only)")]
public class ExportCommandLineOptions
{
[Option("Path", HelpText = "The destination path for the LCX export file", Required = true)]

View file

@ -180,11 +180,23 @@ namespace LANCommander.Launcher.Services
switch (options.Type)
{
case ImportArchiveType.Game:
case ArchiveType.Game:
Logger.LogInformation("Uploading game import file to server...");
await Client.Games.ImportAsync(options.Path);
break;
case ArchiveType.Redistributable:
Logger.LogInformation("Uploading redistributable archive file to server...");
await Client.Redistributables.ImportAsync(options.Path);
break;
case ArchiveType.Server:
Logger.LogInformation("Uploading server archive file to server...");
await Client.Servers.ImportAsync(options.Path);
break;
}
Logger.LogInformation("Import complete!");

View file

@ -41,6 +41,7 @@ namespace LANCommander.SDK
public readonly LauncherService Launcher;
public readonly IssueService Issues;
public readonly LobbyService Lobbies;
public readonly ServerService Servers;
private Settings _Settings { get; set; }
public Settings Settings
@ -67,6 +68,7 @@ namespace LANCommander.SDK
Launcher = new LauncherService(this);
Issues = new IssueService(this);
Lobbies = new LobbyService(this);
Servers = new ServerService(this);
BaseCmdlet.Client = this;
@ -88,6 +90,7 @@ namespace LANCommander.SDK
Launcher = new LauncherService(this);
Issues = new IssueService(this);
Lobbies = new LobbyService(this, logger);
Servers = new ServerService(this, logger);
BaseCmdlet.Client = this;

View file

@ -171,5 +171,16 @@ namespace LANCommander.SDK
return extractionResult;
}
public async Task ImportAsync(string archivePath)
{
using (var fs = new FileStream(archivePath, FileMode.Open, FileAccess.Read))
{
var objectKey = await Client.ChunkedUploadRequestAsync("", fs);
if (objectKey != Guid.Empty)
await Client.PostRequestAsync<object>($"/api/Redistributables/Import/{objectKey}");
}
}
}
}

View file

@ -0,0 +1,73 @@
using LANCommander.SDK.Enums;
using LANCommander.SDK.Extensions;
using LANCommander.SDK.Helpers;
using LANCommander.SDK.Models;
using LANCommander.SDK.PowerShell;
using Microsoft.Extensions.Logging;
using SharpCompress.Common;
using SharpCompress.Readers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LANCommander.SDK
{
public class ServerService
{
private readonly ILogger Logger;
private Client Client { get; set; }
public delegate void OnArchiveEntryExtractionProgressHandler(object sender, ArchiveEntryExtractionProgressArgs e);
public event OnArchiveEntryExtractionProgressHandler OnArchiveEntryExtractionProgress;
public delegate void OnArchiveExtractionProgressHandler(long position, long length);
public event OnArchiveExtractionProgressHandler OnArchiveExtractionProgress;
public ServerService(Client client)
{
Client = client;
}
public ServerService(Client client, ILogger logger)
{
Client = client;
Logger = logger;
}
public async Task ImportAsync(string archivePath)
{
using (var fs = new FileStream(archivePath, FileMode.Open, FileAccess.Read))
{
var objectKey = await Client.ChunkedUploadRequestAsync("", fs);
if (objectKey != Guid.Empty)
await Client.PostRequestAsync<object>($"/api/Servers/Import/{objectKey}");
}
}
public async Task ExportAsync(string destinationPath, Guid serverId)
{
await Client.DownloadRequestAsync($"/Servers/{serverId}/Export/Full", destinationPath);
}
public async Task UploadArchiveAsync(string archivePath, Guid serverId, string version, string changelog = "")
{
using (var fs = new FileStream(archivePath, FileMode.Open, FileAccess.Read))
{
var objectKey = await Client.ChunkedUploadRequestAsync("", fs);
if (objectKey != Guid.Empty)
await Client.PostRequestAsync<object>($"/api/Servers/UploadArchive", new UploadArchiveRequest
{
Id = serverId,
ObjectKey = objectKey,
Version = version,
Changelog = changelog,
});
}
}
}
}

View file

@ -62,5 +62,22 @@ namespace LANCommander.Server.Controllers.Api
return File(new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream", $"{redistributable.Name.SanitizeFilename()}.zip");
}
[Authorize(Roles = "Administrator")]
[HttpPost("Import/{objectKey}")]
public async Task<IActionResult> Import(Guid objectKey)
{
try
{
var game = await RedistributableService.Import(objectKey);
return Ok();
}
catch (Exception ex)
{
Logger?.LogError(ex, "Could not import redistributable from upload");
return BadRequest(ex.Message);
}
}
}
}

View file

@ -0,0 +1,63 @@
using AutoMapper;
using LANCommander.Server.Data.Models;
using LANCommander.Server.Extensions;
using LANCommander.Server.Models;
using LANCommander.Server.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace LANCommander.Server.Controllers.Api
{
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Administrator")]
[Route("api/[controller]")]
[ApiController]
public class ServersController : BaseApiController
{
private readonly IMapper Mapper;
private readonly ServerService ServerService;
public ServersController(
ILogger<ServersController> logger,
IMapper mapper,
ServerService serverService,
ArchiveService archiveService) : base(logger)
{
Mapper = mapper;
ServerService = serverService;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<SDK.Models.Server>>> Get()
{
return Ok(Mapper.Map<IEnumerable<SDK.Models.Server>>(await ServerService.Get()));
}
[HttpGet("{id}")]
public async Task<ActionResult<SDK.Models.Server>> Get(Guid id)
{
var server = await ServerService.Get(id);
if (server == null)
return NotFound();
return Ok(Mapper.Map<SDK.Models.Server>(server));
}
[HttpPost("Import/{objectKey}")]
public async Task<IActionResult> Import(Guid objectKey)
{
try
{
var game = await ServerService.Import(objectKey);
return Ok();
}
catch (Exception ex)
{
Logger?.LogError(ex, "Could not import server from upload");
return BadRequest(ex.Message);
}
}
}
}