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;
}
}