using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; using ZB.MOM.WW.Auth.Abstractions.Ldap; using ZB.MOM.WW.Auth.Ldap; namespace ZB.MOM.WW.Auth.AspNetCore; /// /// Dependency-injection helpers that wire up the ZB.MOM.WW LDAP authentication provider /// from configuration. Composes the concrete implementation living in the /// ZB.MOM.WW.Auth.Ldap package so consuming apps register a provider with a single call. /// /// /// API-key DI wiring lives in ZB.MOM.WW.Auth.ApiKeys /// (ZB.MOM.WW.Auth.ApiKeys.DependencyInjection.ApiKeyServiceCollectionExtensions.AddZbApiKeyAuth) /// so that an LDAP-only consumer can reference this package without pulling in SQLite. /// public static class ServiceCollectionExtensions { /// /// Registers LDAP authentication: binds and validates from the /// configuration section at , and registers /// . /// /// The service collection to add to. /// The application configuration. /// Path of the configuration section holding the LDAP options. /// The same instance, for chaining. public static IServiceCollection AddZbLdapAuth( this IServiceCollection services, IConfiguration config, string sectionPath) { ArgumentNullException.ThrowIfNull(services); ArgumentNullException.ThrowIfNull(config); ArgumentException.ThrowIfNullOrWhiteSpace(sectionPath); // Bind via the options builder and opt into start-time validation. An IValidateOptions // otherwise only runs when the options are first materialized (IOptions.Value) — which // here is the first login (ILdapAuthService factory below), not boot. ValidateOnStart hooks // the host's start-time options validation so a misconfigured directory (e.g. insecure // transport without AllowInsecure) fails fast at startup rather than on first login. services.AddOptions() .Bind(config.GetSection(sectionPath)) .ValidateOnStart(); // Fail fast at startup on a misconfigured directory rather than on first login. services.AddSingleton, LdapOptionsValidator>(); // LdapAuthService is stateless: it holds only a snapshot of LdapOptions and a stateless // connection factory, and opens/disposes a connection per call. It is not IDisposable. // Singleton is correct; TryAdd mirrors the pattern in AddZbApiKeyAuth (idempotency). services.TryAddSingleton(sp => new LdapAuthService(sp.GetRequiredService>().Value)); return services; } }