// Kyoo - A portable and vast media library solution. // Copyright (c) Kyoo. // // See AUTHORS.md and LICENSE file in the project root for full license information. // // Kyoo is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // any later version. // // Kyoo is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Kyoo. If not, see . using System; using System.Collections.Generic; using System.Data.Common; using System.Text.RegularExpressions; using Dapper; using Kyoo.Abstractions.Controllers; using Kyoo.Abstractions.Models; using Kyoo.Postgresql.Utils; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Npgsql; namespace Kyoo.Postgresql { /// /// A module to add postgresql capacity to the app. /// public class PostgresModule : IPlugin { /// public string Name => "Postgresql"; /// /// The configuration to use. The database connection string is pulled from it. /// private readonly IConfiguration _configuration; /// /// The host environment to check if the app is in debug mode. /// private readonly IWebHostEnvironment _environment; /// /// Create a new postgres module instance and use the given configuration and environment. /// /// The configuration to use /// The environment that will be used (if the env is in development mode, more information will be displayed on errors. public PostgresModule(IConfiguration configuration, IWebHostEnvironment env) { _configuration = configuration; _environment = env; } /// /// Migrate the database. /// /// The service list to retrieve the database context public static void Initialize(IServiceProvider provider) { DatabaseContext context = provider.GetRequiredService(); context.Database.Migrate(); using NpgsqlConnection conn = (NpgsqlConnection)context.Database.GetDbConnection(); conn.Open(); conn.ReloadTypes(); SqlMapper.TypeMapProvider = (type) => { return new CustomPropertyTypeMap(type, (type, name) => { string newName = Regex.Replace(name, "(^|_)([a-z])", (match) => match.Groups[2].Value.ToUpperInvariant()); // TODO: Add images handling here (name: poster_source, newName: PosterSource) should set Poster.Source return type.GetProperty(newName)!; }); }; SqlMapper.AddTypeHandler(typeof(Dictionary), new JsonTypeHandler>()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); SqlMapper.AddTypeHandler(typeof(List), new ListTypeHandler()); } /// public void Configure(IServiceCollection services) { DbConnectionStringBuilder builder = new() { ["USER ID"] = _configuration.GetValue("POSTGRES_USER", "KyooUser"), ["PASSWORD"] = _configuration.GetValue("POSTGRES_PASSWORD", "KyooPassword"), ["SERVER"] = _configuration.GetValue("POSTGRES_SERVER", "db"), ["PORT"] = _configuration.GetValue("POSTGRES_PORT", "5432"), ["DATABASE"] = _configuration.GetValue("POSTGRES_DB", "kyooDB"), ["POOLING"] = "true", ["MAXPOOLSIZE"] = "95", ["TIMEOUT"] = "30" }; services.AddDbContext(x => { x.UseNpgsql(builder.ConnectionString) .UseProjectables(); if (_environment.IsDevelopment()) x.EnableDetailedErrors().EnableSensitiveDataLogging(); }, ServiceLifetime.Transient); services.AddTransient((_) => new NpgsqlConnection(builder.ConnectionString)); services.AddHealthChecks().AddDbContextCheck(); } } }