using ZB.MOM.WW.Auth.Abstractions.Ldap;
using LibLdapOptions = ZB.MOM.WW.Auth.Abstractions.Ldap.LdapOptions;
namespace ZB.MOM.WW.OtOpcUa.Security.Ldap;
///
/// LDAP + role-mapping configuration for the Admin UI. Bound from appsettings.json
/// Security:Ldap section. Defaults point at the local GLAuth dev instance (see
/// C:\publish\glauth\auth.md).
///
///
/// Carries both the wire fields the shared ZB.MOM.WW.Auth.Ldap directory client needs
/// (///…) AND the app-only concerns
/// the shared library has no notion of ( master switch,
/// dev bypass, appsettings role baseline).
/// The app wrapper (OtOpcUaLdapAuthService) projects this onto the library's
/// at construction; see .
///
public sealed class LdapOptions
{
public const string SectionName = "Security:Ldap";
/// Gets or sets a value indicating whether LDAP authentication is enabled.
public bool Enabled { get; set; } = true;
/// Gets or sets the LDAP server hostname.
public string Server { get; set; } = "localhost";
/// Gets or sets the LDAP server port.
public int Port { get; set; } = 3893;
///
/// Transport security for the LDAP connection — (implicit
/// TLS), (upgrade), or
/// (plaintext, dev/test only — requires ). Replaces the former
/// UseTls bool (Task 1.4): true→,
/// false→.
///
public LdapTransport Transport { get; set; } = LdapTransport.None;
/// Dev-only escape hatch — must be false in production. Maps to the shared
/// library's (renamed from AllowInsecureLdap).
public bool AllowInsecure { get; set; }
///
/// Dev-only stub: when true, bypasses the real LDAP
/// bind and accepts any non-empty username/password, returning a single Administrator role
/// so the operator can navigate the full Admin UI. MUST be false in production.
///
public bool DevStubMode { get; set; }
/// Gets or sets the LDAP search base DN.
public string SearchBase { get; set; } = "dc=zb,dc=local";
///
/// Service-account DN used for search-then-bind. When empty, a direct-bind with
/// cn={user},{SearchBase} is attempted.
///
public string ServiceAccountDn { get; set; } = string.Empty;
/// Gets or sets the service account password for LDAP authentication.
public string ServiceAccountPassword { get; set; } = string.Empty;
/// Gets or sets the LDAP attribute name for user display name.
public string DisplayNameAttribute { get; set; } = "cn";
/// Gets or sets the LDAP attribute name for group membership.
public string GroupAttribute { get; set; } = "memberOf";
///
/// Attribute the service-account search matches the login name against to resolve the
/// user's DN. cn for GLAuth (the dev default); set sAMAccountName for
/// Active Directory.
///
public string UserNameAttribute { get; set; } = "cn";
///
/// Maps LDAP group name → Admin role. Group match is case-insensitive. A user gets every
/// role whose source group is in their membership list. Values are the canonical control-plane
/// roles (Task 1.7). Example dev mapping:
/// "ReadOnly":"Viewer","ReadWrite":"Designer","AlarmAck":"Administrator"
///
public Dictionary GroupToRole { get; set; } = new(StringComparer.OrdinalIgnoreCase);
///
/// Projects the wire fields onto the shared ZB.MOM.WW.Auth.Ldap
/// the directory client consumes. App-only concerns
/// (, ) have no library counterpart and are
/// handled by the app wrapper around the library service; is carried
/// through so the library's own feature gate stays consistent with the app master switch.
///
public LibLdapOptions ToLibraryOptions() => new()
{
Enabled = Enabled,
Server = Server,
Port = Port,
Transport = Transport,
AllowInsecure = AllowInsecure,
SearchBase = SearchBase,
ServiceAccountDn = ServiceAccountDn,
ServiceAccountPassword = ServiceAccountPassword,
UserNameAttribute = UserNameAttribute,
DisplayNameAttribute = DisplayNameAttribute,
GroupAttribute = GroupAttribute,
};
}