LANCommander/LANCommander.Server/Controllers/ServerController.cs
Pat Hartl add770b227 Refactor Settings
Settings for the server are now combined with the settings from the SDK. This introduces a large breaking change and a migration should be created. This refactor utilizes .NET Configuration and the Options pattern. This will allow for the overriding of any setting using envionment variables. It also means that Settings.yml can be used to override any .NET configuration. A SettingsProvider implementation was created, and any updating of settings was changed from SettingsService.SaveSettings() to SettingsProvider.Update(s => { ... })
2025-11-16 12:31:25 -06:00

150 lines
5.6 KiB
C#

using AutoMapper;
using LANCommander.SDK.Helpers;
using LANCommander.Server.Services;
using Microsoft.AspNetCore.Mvc;
using System.IO.Compression;
namespace LANCommander.Server.Controllers
{
public class ServerController : BaseController
{
private readonly ServerService ServerService;
private readonly IMapper Mapper;
public ServerController(
ILogger<ServerController> logger,
SettingsProvider<Settings.Settings> settingsProvider,
IMapper mapper,
ServerService serverService) : base(logger, settingsProvider)
{
ServerService = serverService;
Mapper = mapper;
}
[HttpGet("/Server/{id:guid}/Export/Full")]
public async Task ExportFullAsync(Guid id)
{
var server = await ServerService
.Include(s => s.Actions)
.Include(s => s.HttpPaths)
.Include(s => s.Scripts)
.Include(s => s.ServerConsoles)
.GetAsync(id);
if (server == null)
{
Response.StatusCode = StatusCodes.Status404NotFound;
return;
}
Response.ContentType = "application/octet-stream";
Response.Headers.Append("Content-Disposition", @$"attachment; filename=""{server.Name}.lcx""");
using (ZipArchive export = new ZipArchive(Response.BodyWriter.AsStream(), ZipArchiveMode.Create))
{
var manifest = Mapper.Map<SDK.Models.Server>(server);
var serializedManifest = ManifestHelper.Serialize(manifest);
using (var manistream = new MemoryStream())
using (var sw = new StreamWriter(manistream))
{
sw.Write(serializedManifest);
sw.Flush();
var manifestEntry = export.CreateEntry(ManifestHelper.ManifestFilename, CompressionLevel.NoCompression);
using (var entryStream = manifestEntry.Open())
{
manistream.Seek(0, SeekOrigin.Begin);
manistream.CopyTo(entryStream);
}
}
if (server.Scripts != null)
foreach (var script in server.Scripts)
{
using (var scriptStream = new MemoryStream())
using (var sw = new StreamWriter(scriptStream))
{
sw.Write(script.Contents);
sw.Flush();
var scriptEntry = export.CreateEntry($"Scripts/{script.Id}", CompressionLevel.NoCompression);
using (var entryStream = scriptEntry.Open())
{
scriptStream.Seek(0, SeekOrigin.Begin);
scriptStream.CopyTo(entryStream);
}
}
}
var files = Directory.EnumerateFileSystemEntries($"{server.WorkingDirectory}", "*", SearchOption.AllDirectories);
foreach (var file in files)
{
var entryName = file.Substring(server.WorkingDirectory.Length, file.Length - server.WorkingDirectory.Length).Replace(Path.DirectorySeparatorChar, '/').TrimStart('/');
if (System.IO.File.Exists(file))
{
export.CreateEntryFromFile(file, $"Files/{entryName}", CompressionLevel.NoCompression);
}
else if (System.IO.Directory.Exists(file))
{
export.CreateEntry($"Files/{entryName}/");
}
}
}
}
[HttpGet("/Server/{id:guid}/{*path}")]
public async Task<IActionResult> WebAsync(Guid id, string path)
{
var server = await ServerService
.Include(s => s.HttpPaths)
.GetAsync(id);
if (server == null)
return NotFound();
if (server.HttpPaths == null || server.HttpPaths.Count == 0)
return NotFound();
// Sanitize
if (path == null)
path = "/";
path = path.Trim('/');
path = path + "/";
var httpPath = server.HttpPaths.FirstOrDefault(hp => path.StartsWith(hp.Path.TrimStart('/')));
// Check to see if there's a root path defined if nothing else matches
if (httpPath == null)
httpPath = server.HttpPaths.FirstOrDefault(hp => hp.Path == "/");
if (httpPath == null)
return Forbid();
var relativePath = path.Substring(httpPath.Path.TrimStart('/').Length).Replace('/', Path.DirectorySeparatorChar).TrimStart('\\');
var localPath = Path.Combine(httpPath.LocalPath, relativePath).TrimEnd('\\');
var attrs = System.IO.File.GetAttributes(localPath);
if ((attrs & FileAttributes.Directory) == FileAttributes.Directory)
{
if (!System.IO.Directory.Exists(localPath))
return NotFound();
return Json(Directory.GetFileSystemEntries(localPath).Select(fse => fse.Substring(localPath.Length)));
}
else
{
if (!System.IO.File.Exists(localPath))
return NotFound();
return File(new FileStream(localPath, FileMode.Open, FileAccess.Read, FileShare.Read), "application/octet-stream", Path.GetFileName(localPath));
}
}
}
}