mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-24 02:02:36 -04:00
Handling configuration
This commit is contained in:
parent
84458d3413
commit
6ebf8a8361
@ -9,6 +9,7 @@ using IdentityServer4.Services;
|
||||
using Kyoo.Authentication.Models;
|
||||
using Kyoo.Authentication.Views;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Kyoo.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
@ -64,6 +65,11 @@ namespace Kyoo.Authentication
|
||||
/// The environment information to check if the app runs in debug mode
|
||||
/// </summary>
|
||||
private readonly IWebHostEnvironment _environment;
|
||||
|
||||
/// <summary>
|
||||
/// The configuration manager used to register typed/untyped implementations.
|
||||
/// </summary>
|
||||
[Injected] public IConfigurationManager ConfigurationManager { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -98,9 +104,7 @@ namespace Kyoo.Authentication
|
||||
services.Configure<PermissionOption>(_configuration.GetSection(PermissionOption.Path));
|
||||
services.Configure<CertificateOption>(_configuration.GetSection(CertificateOption.Path));
|
||||
services.Configure<AuthenticationOption>(_configuration.GetSection(AuthenticationOption.Path));
|
||||
services.AddConfiguration<AuthenticationOption>(AuthenticationOption.Path);
|
||||
|
||||
|
||||
|
||||
List<Client> clients = new();
|
||||
_configuration.GetSection("authentication:clients").Bind(clients);
|
||||
CertificateOption certificateOptions = new();
|
||||
@ -139,6 +143,8 @@ namespace Kyoo.Authentication
|
||||
/// <inheritdoc />
|
||||
public void ConfigureAspNet(IApplicationBuilder app)
|
||||
{
|
||||
ConfigurationManager.AddTyped<AuthenticationOption>(AuthenticationOption.Path);
|
||||
|
||||
app.UseCookiePolicy(new CookiePolicyOptions
|
||||
{
|
||||
MinimumSameSitePolicy = SameSiteMode.Strict
|
||||
|
@ -12,6 +12,21 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
public interface IConfigurationManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Add an editable configuration to the editable configuration list
|
||||
/// </summary>
|
||||
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||
/// <typeparam name="T">The type of the configuration</typeparam>
|
||||
void AddTyped<T>(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Add an editable configuration to the editable configuration list.
|
||||
/// WARNING: this method allow you to add an unmanaged type. This type won't be editable. This can be used
|
||||
/// for external libraries or variable arguments.
|
||||
/// </summary>
|
||||
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||
void AddUntyped(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of a setting using it's path.
|
||||
/// </summary>
|
||||
|
@ -1,10 +1,7 @@
|
||||
using System.Linq;
|
||||
using Autofac;
|
||||
using Autofac.Builder;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
@ -75,37 +72,6 @@ namespace Kyoo
|
||||
return builder.RegisterRepository<T2>().As<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an editable configuration to the editable configuration list
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection to edit</param>
|
||||
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||
/// <typeparam name="T">The type of the configuration</typeparam>
|
||||
/// <returns>The given service collection is returned.</returns>
|
||||
public static IServiceCollection AddConfiguration<T>(this IServiceCollection services, string path)
|
||||
where T : class
|
||||
{
|
||||
if (services.Any(x => x.ServiceType == typeof(T)))
|
||||
return services;
|
||||
foreach (ConfigurationReference confRef in ConfigurationReference.CreateReference<T>(path))
|
||||
services.AddSingleton(confRef);
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an editable configuration to the editable configuration list.
|
||||
/// WARNING: this method allow you to add an unmanaged type. This type won't be editable. This can be used
|
||||
/// for external libraries or variable arguments.
|
||||
/// </summary>
|
||||
/// <param name="services">The service collection to edit</param>
|
||||
/// <param name="path">The root path of the editable configuration. It should not be a nested type.</param>
|
||||
/// <returns>The given service collection is returned.</returns>
|
||||
public static IServiceCollection AddUntypedConfiguration(this IServiceCollection services, string path)
|
||||
{
|
||||
services.AddSingleton(ConfigurationReference.CreateUntyped(path));
|
||||
return services;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the public URL of kyoo using the given configuration instance.
|
||||
/// </summary>
|
||||
|
@ -19,8 +19,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options" Version="5.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="5.0.0" />
|
||||
<PackageReference Include="TvDbSharper" Version="3.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Autofac;
|
||||
using Kyoo.Authentication.Models;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using TvDbSharper;
|
||||
|
||||
namespace Kyoo.TheTvdb
|
||||
@ -33,11 +38,44 @@ namespace Kyoo.TheTvdb
|
||||
public ICollection<Type> Requires => ArraySegment<Type>.Empty;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The configuration to use.
|
||||
/// </summary>
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// The configuration manager used to register typed/untyped implementations.
|
||||
/// </summary>
|
||||
[Injected] public IConfigurationManager ConfigurationManager { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create a new tvdb module instance and use the given configuration.
|
||||
/// </summary>
|
||||
/// <param name="configuration">The configuration to use</param>
|
||||
public PluginTvdb(IConfiguration configuration)
|
||||
{
|
||||
_configuration = configuration;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Configure(ContainerBuilder builder)
|
||||
{
|
||||
builder.RegisterType<TvDbClient>().As<ITvDbClient>();
|
||||
builder.RegisterProvider<ProviderTvdb>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Configure(IServiceCollection services, ICollection<Type> availableTypes)
|
||||
{
|
||||
services.Configure<TvdbOption>(_configuration.GetSection(TvdbOption.Path));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ConfigureAspNet(IApplicationBuilder app)
|
||||
{
|
||||
ConfigurationManager.AddTyped<TvdbOption>(TvdbOption.Path);
|
||||
}
|
||||
}
|
||||
}
|
@ -36,7 +36,29 @@ namespace Kyoo.Controllers
|
||||
_references = references.ToDictionary(x => x.Path, x => x.Type, StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private Type GetType(string path)
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddTyped<T>(string path)
|
||||
{
|
||||
foreach (ConfigurationReference confRef in ConfigurationReference.CreateReference<T>(path))
|
||||
_references.Add(confRef.Path, confRef.Type);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddUntyped(string path)
|
||||
{
|
||||
ConfigurationReference config = ConfigurationReference.CreateUntyped(path);
|
||||
_references.Add(config.Path, config.Type);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the type of the resource at the given path
|
||||
/// </summary>
|
||||
/// <param name="path">The path of the resource</param>
|
||||
/// <exception cref="ArgumentException">The path is not editable or readable</exception>
|
||||
/// <exception cref="ItemNotFoundException">No configuration exists for the given path</exception>
|
||||
/// <returns>The type of the resource at the given path</returns>
|
||||
private Type _GetType(string path)
|
||||
{
|
||||
path = path.Replace("__", ":");
|
||||
|
||||
@ -59,7 +81,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
path = path.Replace("__", ":");
|
||||
// TODO handle lists and dictionaries.
|
||||
Type type = GetType(path);
|
||||
Type type = _GetType(path);
|
||||
object ret = _configuration.GetValue(type, path);
|
||||
if (ret != null)
|
||||
return ret;
|
||||
@ -73,7 +95,7 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
path = path.Replace("__", ":");
|
||||
// TODO handle lists and dictionaries.
|
||||
Type type = GetType(path);
|
||||
Type type = _GetType(path);
|
||||
if (typeof(T).IsAssignableFrom(type))
|
||||
throw new InvalidCastException($"The type {typeof(T).Name} is not valid for " +
|
||||
$"a resource of type {type.Name}.");
|
||||
@ -84,12 +106,12 @@ namespace Kyoo.Controllers
|
||||
public async Task EditValue(string path, object value)
|
||||
{
|
||||
path = path.Replace("__", ":");
|
||||
Type type = GetType(path);
|
||||
Type type = _GetType(path);
|
||||
value = JObject.FromObject(value).ToObject(type);
|
||||
if (value == null)
|
||||
throw new ArgumentException("Invalid value format.");
|
||||
|
||||
ExpandoObject config = ToObject(_configuration);
|
||||
ExpandoObject config = _ToObject(_configuration);
|
||||
IDictionary<string, object> configDic = config;
|
||||
configDic[path] = value;
|
||||
JObject obj = JObject.FromObject(config);
|
||||
@ -104,7 +126,7 @@ namespace Kyoo.Controllers
|
||||
/// <param name="config">The configuration to transform</param>
|
||||
/// <returns>A strongly typed representation of the configuration.</returns>
|
||||
[SuppressMessage("ReSharper", "RedundantJumpStatement")]
|
||||
private ExpandoObject ToObject(IConfiguration config)
|
||||
private ExpandoObject _ToObject(IConfiguration config)
|
||||
{
|
||||
ExpandoObject obj = new();
|
||||
|
||||
@ -112,12 +134,12 @@ namespace Kyoo.Controllers
|
||||
{
|
||||
try
|
||||
{
|
||||
Type type = GetType(section.Path);
|
||||
Type type = _GetType(section.Path);
|
||||
obj.TryAdd(section.Key, section.Get(type));
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
obj.TryAdd(section.Key, ToUntyped(section));
|
||||
obj.TryAdd(section.Key, _ToUntyped(section));
|
||||
}
|
||||
catch
|
||||
{
|
||||
@ -133,13 +155,13 @@ namespace Kyoo.Controllers
|
||||
/// </summary>
|
||||
/// <param name="config">The section to convert</param>
|
||||
/// <returns>The converted section</returns>
|
||||
private static object ToUntyped(IConfigurationSection config)
|
||||
private static object _ToUntyped(IConfigurationSection config)
|
||||
{
|
||||
ExpandoObject obj = new();
|
||||
|
||||
foreach (IConfigurationSection section in config.GetChildren())
|
||||
{
|
||||
obj.TryAdd(section.Key, ToUntyped(section));
|
||||
obj.TryAdd(section.Key, _ToUntyped(section));
|
||||
}
|
||||
|
||||
if (!obj.Any())
|
||||
|
@ -22,7 +22,7 @@ namespace Kyoo.Controllers
|
||||
/// <summary>
|
||||
/// The service provider. It allow plugin's activation.
|
||||
/// </summary>
|
||||
private readonly IServiceProvider _provider;
|
||||
private IServiceProvider _provider;
|
||||
/// <summary>
|
||||
/// The configuration to get the plugin's directory.
|
||||
/// </summary>
|
||||
@ -52,6 +52,13 @@ namespace Kyoo.Controllers
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void SetProvider(IServiceProvider provider)
|
||||
{
|
||||
// TODO temporary bullshit to inject services before the configure asp net.
|
||||
// TODO should rework this when the host will be reworked, as well as the asp net configure.
|
||||
_provider = provider;
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public T GetPlugin<T>(string name)
|
||||
@ -128,6 +135,7 @@ namespace Kyoo.Controllers
|
||||
_logger.LogInformation("Plugin enabled: {Plugins}", _plugins.Select(x => x.Name));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void ConfigureContainer(ContainerBuilder builder)
|
||||
{
|
||||
foreach (IPlugin plugin in _plugins)
|
||||
@ -146,7 +154,11 @@ namespace Kyoo.Controllers
|
||||
public void ConfigureAspnet(IApplicationBuilder app)
|
||||
{
|
||||
foreach (IPlugin plugin in _plugins)
|
||||
{
|
||||
using IServiceScope scope = _provider.CreateScope();
|
||||
Helper.InjectServices(plugin, x => scope.ServiceProvider.GetRequiredService(x));
|
||||
plugin.ConfigureAspNet(app);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -165,27 +165,12 @@ namespace Kyoo.Controllers
|
||||
}));
|
||||
|
||||
using IServiceScope scope = _provider.CreateScope();
|
||||
InjectServices(task, x => scope.ServiceProvider.GetRequiredService(x));
|
||||
Helper.InjectServices(task, x => scope.ServiceProvider.GetRequiredService(x));
|
||||
await task.Run(args, progress, _taskToken.Token);
|
||||
InjectServices(task, _ => null);
|
||||
Helper.InjectServices(task, _ => null);
|
||||
_logger.LogInformation("Task finished: {Task}", task.Name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inject services into the <see cref="InjectedAttribute"/> marked properties of the given object.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to inject</param>
|
||||
/// <param name="retrieve">The function used to retrieve services. (The function is called immediately)</param>
|
||||
private static void InjectServices(ITask obj, [InstantHandle] Func<Type, object> retrieve)
|
||||
{
|
||||
IEnumerable<PropertyInfo> properties = obj.GetType().GetProperties()
|
||||
.Where(x => x.GetCustomAttribute<InjectedAttribute>() != null)
|
||||
.Where(x => x.CanWrite);
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
property.SetValue(obj, retrieve(property.PropertyType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start tasks that are scheduled for start.
|
||||
/// </summary>
|
||||
|
@ -5,6 +5,7 @@ using Autofac;
|
||||
using Autofac.Core;
|
||||
using Autofac.Core.Registration;
|
||||
using Kyoo.Controllers;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Kyoo.Models.Options;
|
||||
using Kyoo.Models.Permissions;
|
||||
using Kyoo.Tasks;
|
||||
@ -81,6 +82,11 @@ namespace Kyoo
|
||||
/// The configuration to use.
|
||||
/// </summary>
|
||||
private readonly IConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// The configuration manager used to register typed/untyped implementations.
|
||||
/// </summary>
|
||||
[Injected] public IConfigurationManager ConfigurationManager { private get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
@ -136,14 +142,9 @@ namespace Kyoo
|
||||
string publicUrl = _configuration.GetPublicUrl();
|
||||
|
||||
services.Configure<BasicOptions>(_configuration.GetSection(BasicOptions.Path));
|
||||
services.AddConfiguration<BasicOptions>(BasicOptions.Path);
|
||||
services.Configure<TaskOptions>(_configuration.GetSection(TaskOptions.Path));
|
||||
services.AddConfiguration<TaskOptions>(TaskOptions.Path);
|
||||
services.Configure<MediaOptions>(_configuration.GetSection(MediaOptions.Path));
|
||||
services.AddConfiguration<MediaOptions>(MediaOptions.Path);
|
||||
services.AddUntypedConfiguration("database");
|
||||
services.AddUntypedConfiguration("logging");
|
||||
|
||||
|
||||
services.AddControllers()
|
||||
.AddNewtonsoftJson(x =>
|
||||
{
|
||||
@ -157,6 +158,12 @@ namespace Kyoo
|
||||
/// <inheritdoc />
|
||||
public void ConfigureAspNet(IApplicationBuilder app)
|
||||
{
|
||||
ConfigurationManager.AddTyped<BasicOptions>(BasicOptions.Path);
|
||||
ConfigurationManager.AddTyped<TaskOptions>(TaskOptions.Path);
|
||||
ConfigurationManager.AddTyped<MediaOptions>(MediaOptions.Path);
|
||||
ConfigurationManager.AddUntyped("database");
|
||||
ConfigurationManager.AddUntyped("logging");
|
||||
|
||||
FileExtensionContentTypeProvider contentTypeProvider = new();
|
||||
contentTypeProvider.Mappings[".data"] = "application/octet-stream";
|
||||
app.UseStaticFiles(new StaticFileOptions
|
||||
|
47
Kyoo/Helper.cs
Normal file
47
Kyoo/Helper.cs
Normal file
@ -0,0 +1,47 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Kyoo.Models.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Kyoo
|
||||
{
|
||||
public static class Helper
|
||||
{
|
||||
/// <summary>
|
||||
/// Inject services into the <see cref="InjectedAttribute"/> marked properties of the given object.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to inject</param>
|
||||
/// <param name="retrieve">The function used to retrieve services. (The function is called immediately)</param>
|
||||
public static void InjectServices(object obj, [InstantHandle] Func<Type, object> retrieve)
|
||||
{
|
||||
IEnumerable<PropertyInfo> properties = obj.GetType().GetProperties()
|
||||
.Where(x => x.GetCustomAttribute<InjectedAttribute>() != null)
|
||||
.Where(x => x.CanWrite);
|
||||
|
||||
foreach (PropertyInfo property in properties)
|
||||
property.SetValue(obj, retrieve(property.PropertyType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An helper method to get json content from an http server. This is a temporary thing and will probably be
|
||||
/// replaced by a call to the function of the same name in the <c>System.Net.Http.Json</c> namespace when .net6
|
||||
/// gets released.
|
||||
/// </summary>
|
||||
/// <param name="client">The http server to use.</param>
|
||||
/// <param name="url">The url to retrieve</param>
|
||||
/// <typeparam name="T">The type of object to convert</typeparam>
|
||||
/// <returns>A T representing the json contained at the given url.</returns>
|
||||
public static async Task<T> GetFromJsonAsync<T>(this HttpClient client, string url)
|
||||
{
|
||||
HttpResponseMessage ret = await client.GetAsync(url);
|
||||
ret.EnsureSuccessStatusCode();
|
||||
string content = await ret.Content.ReadAsStringAsync();
|
||||
return JsonConvert.DeserializeObject<T>(content);
|
||||
}
|
||||
}
|
||||
}
|
@ -71,7 +71,6 @@ namespace Kyoo
|
||||
|
||||
services.AddHttpClient();
|
||||
|
||||
// services.AddTransient(typeof(Lazy<>), typeof(LazyDi<>));
|
||||
_plugins.ConfigureServices(services);
|
||||
}
|
||||
|
||||
@ -87,7 +86,7 @@ namespace Kyoo
|
||||
/// </summary>
|
||||
/// <param name="app">The asp net host to configure</param>
|
||||
/// <param name="env">The host environment (is the app in development mode?)</param>
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider provider)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
app.UseDeveloperExceptionPage();
|
||||
@ -114,7 +113,9 @@ namespace Kyoo
|
||||
return next();
|
||||
});
|
||||
app.UseResponseCompression();
|
||||
|
||||
|
||||
if (_plugins is PluginManager manager)
|
||||
manager.SetProvider(provider);
|
||||
_plugins.ConfigureAspnet(app);
|
||||
|
||||
app.UseSpa(spa =>
|
||||
|
Loading…
x
Reference in New Issue
Block a user