diff --git a/Kyoo.Authentication/Kyoo.Authentication.csproj b/Kyoo.Authentication/Kyoo.Authentication.csproj
index 29c2a08a..17107035 100644
--- a/Kyoo.Authentication/Kyoo.Authentication.csproj
+++ b/Kyoo.Authentication/Kyoo.Authentication.csproj
@@ -16,13 +16,13 @@
-
-
-
-
-
+
+
+
+
+
-
+
diff --git a/Kyoo.CommonAPI/DatabaseContext.cs b/Kyoo.CommonAPI/DatabaseContext.cs
index b58710f3..d92c208f 100644
--- a/Kyoo.CommonAPI/DatabaseContext.cs
+++ b/Kyoo.CommonAPI/DatabaseContext.cs
@@ -84,6 +84,20 @@ namespace Kyoo
return Set>();
}
+
+ ///
+ /// The default constructor
+ ///
+ protected DatabaseContext() { }
+
+ ///
+ /// Create a new using specific options
+ ///
+ /// The options to use.
+ protected DatabaseContext(DbContextOptions options)
+ : base(options)
+ { }
+
///
/// Set basic configurations (like preventing query tracking)
///
diff --git a/Kyoo.CommonAPI/Kyoo.CommonAPI.csproj b/Kyoo.CommonAPI/Kyoo.CommonAPI.csproj
index 3a2b6456..5288b814 100644
--- a/Kyoo.CommonAPI/Kyoo.CommonAPI.csproj
+++ b/Kyoo.CommonAPI/Kyoo.CommonAPI.csproj
@@ -12,10 +12,9 @@
-
-
+
+
-
diff --git a/Kyoo.Postgresql/Kyoo.Postgresql.csproj b/Kyoo.Postgresql/Kyoo.Postgresql.csproj
index 65f2f5e5..10887b80 100644
--- a/Kyoo.Postgresql/Kyoo.Postgresql.csproj
+++ b/Kyoo.Postgresql/Kyoo.Postgresql.csproj
@@ -16,11 +16,7 @@
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
+
diff --git a/Kyoo.Postgresql/PostgresContext.cs b/Kyoo.Postgresql/PostgresContext.cs
index ea220cfc..36ca803e 100644
--- a/Kyoo.Postgresql/PostgresContext.cs
+++ b/Kyoo.Postgresql/PostgresContext.cs
@@ -21,6 +21,11 @@ namespace Kyoo.Postgresql
/// Is this instance in debug mode?
///
private readonly bool _debugMode;
+
+ ///
+ /// Should the configure step be skipped? This is used when the database is created via DbContextOptions.
+ ///
+ private readonly bool _skipConfigure;
///
/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
@@ -32,6 +37,19 @@ namespace Kyoo.Postgresql
NpgsqlConnection.GlobalTypeMapper.MapEnum();
}
+ ///
+ /// Create a new using specific options
+ ///
+ /// The options to use.
+ public PostgresContext(DbContextOptions options)
+ : base(options)
+ {
+ NpgsqlConnection.GlobalTypeMapper.MapEnum();
+ NpgsqlConnection.GlobalTypeMapper.MapEnum();
+ NpgsqlConnection.GlobalTypeMapper.MapEnum();
+ _skipConfigure = true;
+ }
+
///
/// A basic constructor that set default values (query tracker behaviors, mapping enums...)
///
@@ -49,10 +67,13 @@ namespace Kyoo.Postgresql
/// An option builder to fill.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
- optionsBuilder.UseNpgsql(_connection);
- if (_debugMode)
- optionsBuilder.EnableDetailedErrors()
- .EnableSensitiveDataLogging();
+ if (!_skipConfigure)
+ {
+ optionsBuilder.UseNpgsql(_connection);
+ if (_debugMode)
+ optionsBuilder.EnableDetailedErrors().EnableSensitiveDataLogging();
+ }
+
base.OnConfiguring(optionsBuilder);
}
diff --git a/Kyoo.Postgresql/PostgresModule.cs b/Kyoo.Postgresql/PostgresModule.cs
index 52453540..df829fdd 100644
--- a/Kyoo.Postgresql/PostgresModule.cs
+++ b/Kyoo.Postgresql/PostgresModule.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using Kyoo.Controllers;
using Microsoft.AspNetCore.Hosting;
+using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
@@ -59,9 +60,16 @@ namespace Kyoo.Postgresql
///
public void Configure(IServiceCollection services, ICollection availableTypes)
{
- services.AddScoped(_ => new PostgresContext(
- _configuration.GetDatabaseConnection("postgres"),
- _environment.IsDevelopment()));
+ services.AddDbContext(x =>
+ {
+ x.UseNpgsql(_configuration.GetDatabaseConnection("postgres"));
+ if (_environment.IsDevelopment())
+ x.EnableDetailedErrors().EnableSensitiveDataLogging();
+ });
+ // services.AddScoped(_ => new PostgresContext(
+ // _configuration.GetDatabaseConnection("postgres"),
+ // _environment.IsDevelopment()));
+ // services.AddScoped(x => x.GetRequiredService());
}
}
}
\ No newline at end of file
diff --git a/Kyoo.Tests/Kyoo.Tests.csproj b/Kyoo.Tests/Kyoo.Tests.csproj
index 65e01c1f..b5e3dd82 100644
--- a/Kyoo.Tests/Kyoo.Tests.csproj
+++ b/Kyoo.Tests/Kyoo.Tests.csproj
@@ -14,14 +14,14 @@
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Kyoo/Controllers/PluginManager.cs b/Kyoo/Controllers/PluginManager.cs
index eaf08b97..c17e3230 100644
--- a/Kyoo/Controllers/PluginManager.cs
+++ b/Kyoo/Controllers/PluginManager.cs
@@ -69,6 +69,31 @@ namespace Kyoo.Controllers
return _plugins;
}
+ ///
+ /// Load a single plugin and return all IPlugin implementations contained in the Assembly.
+ ///
+ /// The path of the dll
+ /// The list of dlls in hte assembly
+ private IPlugin[] LoadPlugin(string path)
+ {
+ path = Path.GetFullPath(path);
+ try
+ {
+ PluginDependencyLoader loader = new(path);
+ Assembly assembly = loader.LoadFromAssemblyPath(path);
+ return assembly.GetTypes()
+ .Where(x => typeof(IPlugin).IsAssignableFrom(x))
+ .Where(x => _plugins.All(y => y.GetType() != x))
+ .Select(x => (IPlugin)ActivatorUtilities.CreateInstance(_provider, x))
+ .ToArray();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Could not load the plugin at {Path}", path);
+ return Array.Empty();
+ }
+ }
+
///
public void LoadPlugins(ICollection plugins)
{
@@ -78,27 +103,12 @@ namespace Kyoo.Controllers
_logger.LogTrace("Loading new plugins...");
string[] pluginsPaths = Directory.GetFiles(pluginFolder, "*.dll", SearchOption.AllDirectories);
- plugins = pluginsPaths.SelectMany(path =>
- {
- path = Path.GetFullPath(path);
- try
- {
- PluginDependencyLoader loader = new(path);
- Assembly assembly = loader.LoadFromAssemblyPath(path);
- return assembly.GetTypes()
- .Where(x => typeof(IPlugin).IsAssignableFrom(x))
- .Where(x => _plugins.All(y => y.GetType() != x))
- .Select(x => (IPlugin)ActivatorUtilities.CreateInstance(_provider, x))
- .ToArray();
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Could not load the plugin at {Path}", path);
- return Array.Empty();
- }
- }).Concat(plugins).ToList();
+ plugins = plugins.Concat(pluginsPaths.SelectMany(LoadPlugin))
+ .GroupBy(x => x.Name)
+ .Select(x => x.First())
+ .ToList();
- ICollection available = GetProvidedTypes();
+ ICollection available = GetProvidedTypes(plugins);
_plugins.AddRange(plugins.Where(plugin =>
{
Type missing = plugin.Requires.FirstOrDefault(x => available.All(y => !y.IsAssignableTo(x)));
@@ -119,7 +129,7 @@ namespace Kyoo.Controllers
///
public void ConfigureServices(IServiceCollection services)
{
- ICollection available = GetProvidedTypes();
+ ICollection available = GetProvidedTypes(_plugins);
foreach (IPlugin plugin in _plugins)
plugin.Configure(services, available);
}
@@ -134,11 +144,12 @@ namespace Kyoo.Controllers
///
/// Get the list of types provided by the currently loaded plugins.
///
+ /// The list of plugins that will be used as a plugin pool to get provided types.
/// The list of types available.
- private ICollection GetProvidedTypes()
+ private ICollection GetProvidedTypes(ICollection plugins)
{
- List available = _plugins.SelectMany(x => x.Provides).ToList();
- List conditionals =_plugins
+ List available = plugins.SelectMany(x => x.Provides).ToList();
+ List conditionals = plugins
.SelectMany(x => x.ConditionalProvides)
.Where(x => x.Condition.Condition())
.ToList();
@@ -199,6 +210,14 @@ namespace Kyoo.Controllers
///
protected override Assembly Load(AssemblyName assemblyName)
{
+ Assembly existing = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(x =>
+ {
+ AssemblyName name = x.GetName();
+ return name.Name == assemblyName.Name && name.Version == assemblyName.Version;
+ });
+ if (existing != null)
+ return existing;
string assemblyPath = _resolver.ResolveAssemblyToPath(assemblyName);
if (assemblyPath != null)
return LoadFromAssemblyPath(assemblyPath);
diff --git a/Kyoo/Kyoo.csproj b/Kyoo/Kyoo.csproj
index ca011593..d4e376b4 100644
--- a/Kyoo/Kyoo.csproj
+++ b/Kyoo/Kyoo.csproj
@@ -36,17 +36,11 @@
-
-
-
-
-
-
- runtime; build; native; contentfiles; analyzers; buildtransitive
- all
-
-
-
+
+
+
+
+
diff --git a/Kyoo/Startup.cs b/Kyoo/Startup.cs
index 730d4b37..c267bd00 100644
--- a/Kyoo/Startup.cs
+++ b/Kyoo/Startup.cs
@@ -2,6 +2,7 @@ using System;
using System.IO;
using Kyoo.Controllers;
using Kyoo.Models;
+using Kyoo.Postgresql;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.AngularCli;
@@ -39,12 +40,12 @@ namespace Kyoo
///
/// The configuration context
/// A logger factory used to create a logger for the plugin manager.
- public Startup(IServiceProvider hostProvider, IConfiguration configuration, ILoggerFactory loggerFactory)
+ public Startup(IServiceProvider hostProvider, IConfiguration configuration, ILoggerFactory loggerFactory, IWebHostEnvironment host)
{
_configuration = configuration;
_plugins = new PluginManager(hostProvider, _configuration, loggerFactory.CreateLogger());
- _plugins.LoadPlugins(new [] {new CoreModule()});
+ _plugins.LoadPlugins(new IPlugin[] {new CoreModule(), new PostgresModule(configuration, host)});
}
///
@@ -132,13 +133,13 @@ namespace Kyoo
});
app.UseResponseCompression();
- app.UseSpa(spa =>
- {
- spa.Options.SourcePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Kyoo.WebApp");
-
- if (env.IsDevelopment())
- spa.UseAngularCliServer("start");
- });
+ // app.UseSpa(spa =>
+ // {
+ // spa.Options.SourcePath = Path.Join(AppDomain.CurrentDomain.BaseDirectory, "Kyoo.WebApp");
+ //
+ // if (env.IsDevelopment())
+ // spa.UseAngularCliServer("start");
+ // });
_plugins.ConfigureAspnet(app);