From d115797dd79529decf88f23061b0bfde1b15d481 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 18 May 2021 17:55:48 +0200 Subject: [PATCH] Creating a configuration manager with a start of edit --- .../Controllers/IConfigurationManager.cs | 33 +++++++++ Kyoo.Common/Models/Account.cs | 9 --- Kyoo.Common/Models/ImageTypes.cs | 4 - Kyoo.Common/Utility.cs | 40 ++-------- Kyoo/Controllers/ConfigurationManager.cs | 73 +++++++++++++++++++ Kyoo/CoreModule.cs | 1 + Kyoo/Views/ConfigurationApi.cs | 16 ++-- Kyoo/Views/LibraryApi.cs | 6 +- Kyoo/Views/StudioApi.cs | 4 +- 9 files changed, 128 insertions(+), 58 deletions(-) create mode 100644 Kyoo.Common/Controllers/IConfigurationManager.cs delete mode 100644 Kyoo.Common/Models/Account.cs delete mode 100644 Kyoo.Common/Models/ImageTypes.cs create mode 100644 Kyoo/Controllers/ConfigurationManager.cs diff --git a/Kyoo.Common/Controllers/IConfigurationManager.cs b/Kyoo.Common/Controllers/IConfigurationManager.cs new file mode 100644 index 00000000..ccd2bd05 --- /dev/null +++ b/Kyoo.Common/Controllers/IConfigurationManager.cs @@ -0,0 +1,33 @@ +using System; +using System.Threading.Tasks; +using Kyoo.Models; +using Kyoo.Models.Exceptions; + +namespace Kyoo.Controllers +{ + /// + /// A class to ease configuration management. This work WITH Microsoft's package, you can still use IOptions patterns + /// to access your options, this manager ease dynamic work and editing. + /// It works with . + /// + public interface IConfigurationManager + { + /// + /// Edit the value of a setting using it's path. Save it to the json file. + /// + /// The path of the resource (can be separated by ':' or '__' + /// The new value of the resource + /// The type of the resource + /// No setting found at the given path. + Task EditValue(string path, T value); + + /// + /// Edit the value of a setting using it's path. Save it to the json file. + /// + /// The path of the resource (can be separated by ':' or '__' + /// The new value of the resource + /// The type of the resource + /// No setting found at the given path. + Task EditValue(string path, object value, Type type); + } +} \ No newline at end of file diff --git a/Kyoo.Common/Models/Account.cs b/Kyoo.Common/Models/Account.cs deleted file mode 100644 index a3f51c61..00000000 --- a/Kyoo.Common/Models/Account.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Kyoo.Models -{ - public class Account - { - public string Username { get; set; } - public string Email { get; set; } - public string Picture { get; set; } - } -} \ No newline at end of file diff --git a/Kyoo.Common/Models/ImageTypes.cs b/Kyoo.Common/Models/ImageTypes.cs deleted file mode 100644 index 6dea10d4..00000000 --- a/Kyoo.Common/Models/ImageTypes.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Kyoo.Models -{ - public enum ImageType { Poster, Background, Logo } -} \ No newline at end of file diff --git a/Kyoo.Common/Utility.cs b/Kyoo.Common/Utility.cs index 6583f704..743cf545 100644 --- a/Kyoo.Common/Utility.cs +++ b/Kyoo.Common/Utility.cs @@ -10,7 +10,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using JetBrains.Annotations; -using Kyoo.Models; using Kyoo.Models.Attributes; namespace Kyoo @@ -33,7 +32,7 @@ namespace Kyoo } /// - /// Get the name of a property. Usfull for selectors as members ex: Load(x => x.Shows) + /// Get the name of a property. Useful for selectors as members ex: Load(x => x.Shows) /// /// The expression /// The name of the expression @@ -71,10 +70,10 @@ namespace Kyoo } /// - /// Slugify a string (Replace spaces by -, Uniformise accents é -> e) + /// Slugify a string (Replace spaces by -, Uniformize accents é -> e) /// /// The string to slugify - /// The slugified string + /// The slug version of the given string public static string ToSlug(string str) { if (str == null) @@ -98,37 +97,12 @@ namespace Kyoo str = Regex.Replace(str, @"([-_]){2,}", "$1", RegexOptions.Compiled); return str; } - - - /// - /// Set the image of a show using the type. - /// - /// The owner of the image - /// The url of the image - /// The type of the image - public static void SetImage(Show show, string imgUrl, ImageType type) - { - switch(type) - { - case ImageType.Poster: - show.Poster = imgUrl; - break; - case ImageType.Logo: - show.Logo = imgUrl; - break; - case ImageType.Background: - show.Backdrop = imgUrl; - break; - default: - throw new ArgumentOutOfRangeException(nameof(type), type, null); - } - } /// /// Merge two lists, can keep duplicates or remove them. /// - /// The first enumarble to merge - /// The second enumerable to merge, if items from this list are equals to one from the first, they are not keeped + /// The first enumerable to merge + /// The second enumerable to merge, if items from this list are equals to one from the first, they are not kept /// Equality function to compare items. If this is null, duplicated elements are kept /// The two list merged as an array public static T[] MergeLists(IEnumerable first, @@ -150,7 +124,7 @@ namespace Kyoo /// At the end, the OnMerge method of first will be called if first is a /// /// The object to assign - /// The object containg new values + /// The object containing new values /// Fields of T will be used /// public static T Assign(T first, T second) @@ -339,7 +313,7 @@ namespace Kyoo /// /// The type to check /// The generic type to check against (Only generic types are supported like typeof(IEnumerable<>). - /// The generic definition of genericType that type inherit or null if type does not implement the genric type. + /// The generic definition of genericType that type inherit or null if type does not implement the generic type. /// and can't be null /// must be a generic type public static Type GetGenericDefinition([NotNull] Type type, [NotNull] Type genericType) diff --git a/Kyoo/Controllers/ConfigurationManager.cs b/Kyoo/Controllers/ConfigurationManager.cs new file mode 100644 index 00000000..3d9ddda8 --- /dev/null +++ b/Kyoo/Controllers/ConfigurationManager.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Kyoo.Api; +using Kyoo.Models; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json.Linq; + +namespace Kyoo.Controllers +{ + public class ConfigurationManager : IConfigurationManager + { + /// + /// The configuration to retrieve and edit. + /// + private readonly IConfiguration _configuration; + + /// + /// The strongly typed list of options + /// + private readonly Dictionary _references; + + /// + /// Create a new using the given configuration. + /// + /// The configuration to use. + /// The strongly typed option list. + public ConfigurationManager(IConfiguration configuration, IEnumerable references) + { + _configuration = configuration; + _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); + } + + + /// + public Task EditValue(string path, T value) + { + return EditValue(path, value, typeof(T)); + } + + /// + public async Task EditValue(string path, object value, Type type) + { + JObject obj = JObject.FromObject(ToObject(_configuration)); + // TODO allow path to change + await using StreamWriter writer = new("settings.json"); + await writer.WriteAsync(obj.ToString()); + } + + /// + /// Transform a configuration to a strongly typed object (the root configuration is an + /// but child elements are using strong types. + /// + /// The configuration to transform + /// A strongly typed representation of the configuration. + private object ToObject(IConfiguration config) + { + ExpandoObject obj = new(); + + foreach (IConfigurationSection section in config.GetChildren()) + { + if (!_references.TryGetValue(section.Path, out Type type)) + continue; + obj.TryAdd(section.Key, section.Get(type)); + } + + return obj; + } + } +} \ No newline at end of file diff --git a/Kyoo/CoreModule.cs b/Kyoo/CoreModule.cs index 3c637fce..cbd6cbd9 100644 --- a/Kyoo/CoreModule.cs +++ b/Kyoo/CoreModule.cs @@ -99,6 +99,7 @@ namespace Kyoo x.SerializerSettings.Converters.Add(new PeopleRoleConverter()); }); + services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); diff --git a/Kyoo/Views/ConfigurationApi.cs b/Kyoo/Views/ConfigurationApi.cs index 83cd80d5..dd6dbc9b 100644 --- a/Kyoo/Views/ConfigurationApi.cs +++ b/Kyoo/Views/ConfigurationApi.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; +using Kyoo.Controllers; using Kyoo.Models; using Kyoo.Models.Permissions; using Microsoft.AspNetCore.Mvc; @@ -16,6 +18,8 @@ namespace Kyoo.Api [ApiController] public class ConfigurationApi : Controller { + private readonly ConfigurationManager _manager; + /// /// The configuration to retrieve and edit. /// @@ -31,8 +35,9 @@ namespace Kyoo.Api /// /// The configuration to use. /// The strongly typed option list. - public ConfigurationApi(IConfiguration configuration, IEnumerable references) + public ConfigurationApi(ConfigurationManager manager, IConfiguration configuration, IEnumerable references) { + _manager = manager; _configuration = configuration; _references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase); } @@ -70,16 +75,13 @@ namespace Kyoo.Api /// No configuration exists for the given slug [HttpPut("{slug}")] [Permission(nameof(ConfigurationApi), Kind.Admin)] - public ActionResult EditConfiguration(string slug, [FromBody] object newValue) + public async Task> EditConfiguration(string slug, [FromBody] object newValue) { slug = slug.Replace("__", ":"); if (!_references.TryGetValue(slug, out Type type)) return NotFound(); - // object ret = _configuration.(type, slug); - // if (ret != null) - // return ret; - // object option = Activator.CreateInstance(type); - // _configuration.Bind(slug, option); + await _manager.EditValue(slug, newValue, type); + // await _configuration.SetValue(slug, newValue, type); return newValue; } } diff --git a/Kyoo/Views/LibraryApi.cs b/Kyoo/Views/LibraryApi.cs index 239dcd8e..bbcd7a90 100644 --- a/Kyoo/Views/LibraryApi.cs +++ b/Kyoo/Views/LibraryApi.cs @@ -14,13 +14,13 @@ namespace Kyoo.Api [Route("api/library")] [Route("api/libraries")] [ApiController] - [PartialPermission(nameof(LibraryAPI))] - public class LibraryAPI : CrudApi + [PartialPermission(nameof(LibraryApi))] + public class LibraryApi : CrudApi { private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; - public LibraryAPI(ILibraryManager libraryManager, ITaskManager taskManager, IConfiguration configuration) + public LibraryApi(ILibraryManager libraryManager, ITaskManager taskManager, IConfiguration configuration) : base(libraryManager.LibraryRepository, configuration) { _libraryManager = libraryManager; diff --git a/Kyoo/Views/StudioApi.cs b/Kyoo/Views/StudioApi.cs index 66b6ca5d..657988bb 100644 --- a/Kyoo/Views/StudioApi.cs +++ b/Kyoo/Views/StudioApi.cs @@ -15,11 +15,11 @@ namespace Kyoo.Api [Route("api/studios")] [ApiController] [PartialPermission(nameof(ShowApi))] - public class StudioAPI : CrudApi + public class StudioApi : CrudApi { private readonly ILibraryManager _libraryManager; - public StudioAPI(ILibraryManager libraryManager, IConfiguration config) + public StudioApi(ILibraryManager libraryManager, IConfiguration config) : base(libraryManager.StudioRepository, config) { _libraryManager = libraryManager;