make the version name match the actual name for FTP deployment

fix rare issue with summing session scores
copy font to expected wwwroot dir in debug mode so we get pretty icons when developing
upgrade some packages

pretty much reworked the entire server web config to support better validation and stuff.. not really a small fix

finish web configuration changes (I think)

finish up configuration changes and update shared library nuget
This commit is contained in:
RaidMax
2020-01-17 17:31:53 -06:00
parent 3a1cfba251
commit 697a752be0
38 changed files with 531 additions and 200 deletions

View File

@ -2,8 +2,11 @@
using Microsoft.AspNetCore.Mvc;
using SharedLibraryCore;
using SharedLibraryCore.Configuration;
using SharedLibraryCore.Configuration.Attributes;
using SharedLibraryCore.Configuration.Validation;
using SharedLibraryCore.Interfaces;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using WebfrontCore.ViewModels;
@ -12,11 +15,17 @@ namespace WebfrontCore.Controllers
[Authorize]
public class ConfigurationController : BaseController
{
public ConfigurationController(IManager manager) : base (manager)
{
private readonly ApplicationConfigurationValidator _validator;
public ConfigurationController(IManager manager) : base(manager)
{
_validator = new ApplicationConfigurationValidator();
}
/// <summary>
/// Endpoint to get the current configuration view
/// </summary>
/// <returns></returns>
public IActionResult Edit()
{
if (Client.Level < SharedLibraryCore.Database.Models.EFClient.Permission.Owner)
@ -27,56 +36,132 @@ namespace WebfrontCore.Controllers
return View("Index", Manager.GetApplicationSettings().Configuration());
}
/// <summary>
/// Endpoint for the save action
/// </summary>
/// <param name="newConfiguration">bound configuration</param>
/// <returns></returns>
[HttpPost]
public async Task<IActionResult> Edit(ApplicationConfiguration newConfiguration, bool addNewServer = false, bool shouldSave = false)
public async Task<IActionResult> Save(ApplicationConfiguration newConfiguration)
{
// todo: make this authorization middleware instead of these checks
if (Client.Level < SharedLibraryCore.Database.Models.EFClient.Permission.Owner)
{
return Unauthorized();
}
CleanConfiguration(newConfiguration);
var validationResult = _validator.Validate(newConfiguration);
if (validationResult.IsValid)
{
var currentConfiguration = Manager.GetApplicationSettings().Configuration();
CopyConfiguration(newConfiguration, currentConfiguration);
await Manager.GetApplicationSettings().Save();
return Ok(new { message = new[] { Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CONFIGURATION_SAVED"] } });
}
else
{
return BadRequest(new { message = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CONFIGURATION_SAVE_FAILED"], errors = new[] { validationResult.Errors.Select(_error => _error.ErrorMessage) } });
}
}
/// <summary>
/// Cleans the configuration by removing empty items from from the array
/// </summary>
/// <param name="newConfiguration"></param>
private void CleanConfiguration(ApplicationConfiguration newConfiguration)
{
void cleanProperties(object config)
{
foreach (var property in config.GetType()
.GetProperties().Where(_prop => _prop.CanWrite))
{
var newPropValue = property.GetValue(config);
if (newPropValue is ServerConfiguration[] serverConfig)
{
foreach (var c in serverConfig)
{
cleanProperties(c);
}
}
// this clears out any null or empty items in the string array
if (newPropValue is string[] configArray)
{
newPropValue = configArray.Where(_str => !string.IsNullOrWhiteSpace(_str)).ToArray();
}
property.SetValue(config, newPropValue);
}
}
cleanProperties(newConfiguration);
}
/// <summary>
/// Copies required config fields from new to old
/// </summary>
/// <param name="newConfiguration">Source config</param>
/// <param name="oldConfiguration">Destination config</param>
private void CopyConfiguration(ApplicationConfiguration newConfiguration, ApplicationConfiguration oldConfiguration)
{
foreach (var property in newConfiguration.GetType()
.GetProperties().Where(_prop => _prop.CanWrite))
{
var newPropValue = property.GetValue(newConfiguration);
bool isPropNullArray = property.PropertyType.IsArray && newPropValue == null;
// this prevents us from setting a null array as that could screw reading up
if (!ShouldIgnoreProperty(property) && !isPropNullArray)
{
property.SetValue(oldConfiguration, newPropValue);
}
}
}
/// <summary>
/// Generates the partial view for a new list item
/// </summary>
/// <param name="propertyName">name of the property the input element is generated for</param>
/// <param name="itemCount">how many items exist already</param>
/// <param name="serverIndex">if it's a server property, which one</param>
/// <returns></returns>
public IActionResult GetNewListItem(string propertyName, int itemCount, int serverIndex = -1)
{
if (Client.Level < SharedLibraryCore.Database.Models.EFClient.Permission.Owner)
{
return Unauthorized();
}
if (shouldSave)
// todo: maybe make this cleaner in the future
if (propertyName.StartsWith("Servers") && serverIndex < 0)
{
var currentConfiguration = Manager.GetApplicationSettings().Configuration();
var newConfigurationProperties = newConfiguration.GetType().GetProperties();
foreach (var property in currentConfiguration.GetType().GetProperties())
return PartialView("_ServerItem", new ApplicationConfiguration()
{
var newProp = newConfigurationProperties.First(_prop => _prop.Name == property.Name);
var newPropValue = newProp.GetValue(newConfiguration);
if (newPropValue != null && newProp.CanWrite)
{
property.SetValue(currentConfiguration, newPropValue);
}
}
await Manager.GetApplicationSettings().Save();
Servers = Enumerable.Repeat(new ServerConfiguration(), itemCount + 1).ToArray()
});
}
if (addNewServer)
var model = new BindingHelper()
{
newConfiguration.Servers.Add(new ServerConfiguration());
}
return View("Index", newConfiguration);
}
public IActionResult GetNewListItem(string propertyName, int itemCount)
{
if (Client.Level != SharedLibraryCore.Database.Models.EFClient.Permission.Owner)
{
return Unauthorized();
}
var configInfo = new ConfigurationInfo()
{
NewItemCount = itemCount,
PropertyName = propertyName
Properties = propertyName.Split("."),
ItemIndex = itemCount,
ParentItemIndex = serverIndex
};
return PartialView("_ListItem", configInfo);
return PartialView("_ListItem", model);
}
/// <summary>
/// Indicates if the property should be ignored when cleaning/copying from one config to another
/// </summary>
/// <param name="info">property info of the current property</param>
/// <returns></returns>
private bool ShouldIgnoreProperty(PropertyInfo info) => (info.GetCustomAttributes(false)
.Where(_attr => _attr.GetType() == typeof(ConfigurationIgnore))
.FirstOrDefault() as ConfigurationIgnore) != null;
}
}