// Copyright Epic Games, Inc. All Rights Reserved.
using EpicGames.Core;
using HordeServer.Api;
using HordeServer.Models;
using HordeServer.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using System.Runtime.InteropServices;
namespace HordeServer.Controllers
{
///
/// Controller managing server configuration
///
[ApiController]
[Authorize]
[Route("[controller]")]
public class ConfigController : ControllerBase
{
///
/// The database service singleton
///
DatabaseService DatabaseService;
///
/// The acl service singleton
///
AclService AclService;
///
/// The config service singleton
///
ConfigService ConfigService;
///
/// Settings for the server
///
IOptionsMonitor Settings;
///
/// Logger for controller
///
private readonly ILogger Logger;
///
/// Constructor
///
/// The database service singleton
/// The ACL service singleton
/// The Config service singleton
/// Logger for the controller
/// Server settings
public ConfigController(DatabaseService DatabaseService, AclService AclService, ConfigService ConfigService, IOptionsMonitor Settings, ILogger Logger)
{
this.DatabaseService = DatabaseService;
this.AclService = AclService;
this.ConfigService = ConfigService;
this.Settings = Settings;
this.Logger = Logger;
}
// Global Configuration
///
/// Update global config
///
[HttpPut]
[Route("/api/v1/config/global")]
public async Task UpdateGlobalSettings([FromBody] UpdateGlobalConfigRequest Request)
{
if (!await AclService.AuthorizeAsync(AclAction.AdminWrite, User))
{
return Forbid();
}
if (!Settings.CurrentValue.SingleInstance)
{
Logger.LogError("Updating global configuration settings with ConfigController currently only supported in single instance mode");
return BadRequest();
}
await ConfigService.UpdateGlobalConfig(Request);
return Ok();
}
///
/// Get global config settings
///
/// Administrative settings for the server
[HttpGet]
[Route("/api/v1/config/global")]
public async Task> GetGlobalConfig()
{
if (!await AclService.AuthorizeAsync(AclAction.AdminRead, User))
{
return Forbid();
}
if (string.IsNullOrEmpty(Settings.CurrentValue.ConfigPath))
{
return BadRequest();
}
FileReference GlobalConfigFile = new FileReference(Settings.CurrentValue.ConfigPath);
byte[] Data = await FileReference.ReadAllBytesAsync(GlobalConfigFile);
JsonSerializerOptions Options = new JsonSerializerOptions();
Startup.ConfigureJsonSerializer(Options);
return JsonSerializer.Deserialize(Data, Options);
}
// Administrative Server Settings
///
/// Get administrative server settings
///
/// Administrative settings for the server
[HttpGet]
[Route("/api/v1/config/serversettings")]
public async Task> GetServerSettings()
{
if (!await AclService.AuthorizeAsync(AclAction.AdminRead, User))
{
return Forbid();
}
GetServerSettingsResponse Response = new GetServerSettingsResponse(Settings.CurrentValue);
Response.NumServerUpdates = ConfigService.NumUserConfigUpdates;
return Response;
}
///
/// Update administrative server settings
///
/// Administrative settings for the server
[HttpPut]
[Route("/api/v1/config/serversettings")]
public async Task> UpdateServerSettings([FromBody] UpdateServerSettingsRequest Request)
{
if (!await AclService.AuthorizeAsync(AclAction.AdminWrite, User))
{
return Forbid();
}
if (!Settings.CurrentValue.SingleInstance)
{
Logger.LogError("Updating server settings from ConfigController currently only supported in single instance mode");
return BadRequest();
}
if (Request.Settings == null || Request.Settings.Count == 0)
{
return new ServerUpdateResponse() { RestartRequired = false };
}
ServerUpdateResponse Response = await ConfigService.UpdateServerSettings(Request);
return Response;
}
}
}