using DigitalData.Core.Abstractions.Security; using DigitalData.Core.Security.Config; using DigitalData.Core.Security.Cryptographer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System.Security.Claims; namespace DigitalData.Core.Security { public static class DIExtensions { private static (bool Added, object Lock) _mappingProfile = (false, new()); private static IServiceCollection AddMappingProfile(this IServiceCollection services) { if (_mappingProfile.Added) return services; lock (_mappingProfile.Lock) { if (_mappingProfile.Added) return services; _mappingProfile.Added = true; return services .AddAutoMapper(typeof(MappingProfile).Assembly) .AddSingleton(); } } private static IServiceCollection AddParamsConfigureOptions(this IServiceCollection services) where TParams : RSAFactoryParams => services.AddSingleton, ParamsConfigureOptions>(); private static IServiceCollection AddAsymCryptService(this IServiceCollection services, bool setAsDefault = false) where TAsymCryptParams : AsymCryptParams { services.AddParamsConfigureOptions().AddMappingProfile(); return setAsDefault ? services.AddSingleton>() : services.AddSingleton, AsymCryptService>(); } /// /// Registers a custom asym crypt service with specified parameters from the given configuration section. /// /// /// /// /// If true, the factory is registered as the default . Otherwise, it is registered as . /// public static IServiceCollection AddAsymCryptService(this IServiceCollection services, IConfigurationSection section, bool setAsDefault = false) where TAsymCryptParams : AsymCryptParams => services .Configure(section) .AddAsymCryptService(setAsDefault: setAsDefault); /// /// Registers a custom asym crypt service with default parameters from the given configuration section. /// /// /// /// /// public static IServiceCollection AddAsymCryptService(this IServiceCollection services, IConfigurationSection section, bool setAsDefault = false) => services.Configure(section).AddAsymCryptService(setAsDefault: setAsDefault); /// /// Registers an asym crypt service with the specified parameters from the given instance. Optionally, sets it as the default factory. /// /// /// /// /// If true, the factory is registered as the default . Otherwise, it is registered as . /// public static IServiceCollection AddAsymCryptService(this IServiceCollection services, TAsymCryptParams param, bool setAsDefault = false) where TAsymCryptParams : AsymCryptParams => services .AddSingleton(Options.Create(param)) .AddAsymCryptService(setAsDefault: setAsDefault); /// /// Registers default asym crypt service with the specified parameters from the given instance. /// /// /// /// public static IServiceCollection AddAsymCryptService(this IServiceCollection services, AsymCryptParams param) => services .AddAsymCryptService(param: param, setAsDefault: true); /// /// Registers default RSA Factory instance with default params /// /// /// /// The updated with the RSA Factory registered. public static IServiceCollection AddRSAFactory(this IServiceCollection services, RSAFactoryParams? factoryParams = null) => services .AddParamsConfigureOptions() .AddMappingProfile() .AddScoped(_ => new RSAFactory(Options.Create(factoryParams ?? new()))); /// /// Registers a custom RSA Factory with specified parameters from the given configuration section. /// /// /// /// /// If true, the factory is registered as the default . Otherwise, it is registered as . /// The updated with the RSA Factory registered. public static IServiceCollection AddRSAFactory(this IServiceCollection services, IConfigurationSection section, bool setAsDefault = false) where TRSAFactoryParams : RSAFactoryParams { services.AddMappingProfile().AddParamsConfigureOptions().Configure(section); return setAsDefault ? services.AddSingleton>() : services.AddSingleton, RSAFactory>(); } /// /// Registers an RSA Factory with the specified parameters from the given instance. Optionally, sets it as the default factory. /// /// The type of the RSA factory parameters. /// /// /// If true, the factory is registered as the default . Otherwise, it is registered as . /// The updated with the RSA Factory registered. public static IServiceCollection AddRSAFactory(this IServiceCollection services, TRSAFactoryParams rsaParams, bool setAsDefault = false) where TRSAFactoryParams : RSAFactoryParams { services.AddMappingProfile().AddSingleton(Options.Create(rsaParams)); return setAsDefault ? services.AddParamsConfigureOptions().AddSingleton>() : services.AddParamsConfigureOptions().AddSingleton, RSAFactory>(); } private static IServiceCollection AddClaimDescriptor(this IServiceCollection services, Func>? claimsMapper = null, Func? subjectMapper = null) { var descriptor = new ClaimDescriptor { CreateClaims = claimsMapper, CreateSubject = subjectMapper }; return services.AddSingleton(sp => Options.Create(descriptor)); } } }