// 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; } } }