namespace ZB.MOM.WW.OtOpcUa.Server.Security;
///
/// LDAP settings for the OPC UA server's UserName token validator. Bound from
/// appsettings.json OpcUaServer:Ldap. Defaults target the GLAuth dev instance
/// (localhost:3893, dc=lmxopcua,dc=local) for the stock inner-loop setup. Production
/// deployments are expected to point at Active Directory; see
/// and the per-field xml-docs for the AD-specific overrides.
///
///
/// Active Directory cheat-sheet:
///
/// - : one of the domain controllers, or the domain FQDN (will round-robin DCs).
/// - : 389 (LDAP) or 636 (LDAPS); use 636 + in production.
/// - : true. AD increasingly rejects plain-LDAP bind under LDAP-signing enforcement.
/// - : false. Dev escape hatch only.
/// - : DC=corp,DC=example,DC=com — your domain's base DN.
/// - : a dedicated service principal with read access to user + group entries
/// (e.g. CN=OpcUaSvc,OU=Service Accounts,DC=corp,DC=example,DC=com). Never a privileged admin.
/// - : sAMAccountName (classic login name) or userPrincipalName
/// (user@domain form). Default is uid which AD does not populate, so this override is required.
/// - : displayName gives the human name; cn works too but is less rich.
/// - : memberOf — matches AD's default. Values are full DNs
/// (CN=<Group>,OU=...,DC=...); the authenticator strips the leading CN= RDN value and uses
/// that as the lookup key in .
/// - : maps your AD group common-names to OPC UA roles — e.g.
/// {"OPCUA-Operators" : "WriteOperate", "OPCUA-Engineers" : "WriteConfigure"}.
///
///
/// Nested groups are not expanded — AD's tokenGroups / LDAP_MATCHING_RULE_IN_CHAIN
/// membership-chain filter isn't used. Assign users directly to the role-mapped groups, or pre-flatten
/// membership in your directory. If nested expansion becomes a requirement, it's an authenticator
/// enhancement (not a config change).
///
///
public sealed class LdapOptions
{
public bool Enabled { get; init; } = false;
public string Server { get; init; } = "localhost";
public int Port { get; init; } = 3893;
public bool UseTls { get; init; } = false;
/// Dev-only escape hatch — must be false in production.
public bool AllowInsecureLdap { get; init; } = true;
public string SearchBase { get; init; } = "dc=lmxopcua,dc=local";
public string ServiceAccountDn { get; init; } = string.Empty;
public string ServiceAccountPassword { get; init; } = string.Empty;
public string DisplayNameAttribute { get; init; } = "cn";
public string GroupAttribute { get; init; } = "memberOf";
///
/// LDAP attribute used to match a login name against user entries in the directory.
/// Defaults to uid (RFC 2307). Common overrides:
///
/// - sAMAccountName — Active Directory, classic NT-style login names (e.g. jdoe).
/// - userPrincipalName — Active Directory, email-style (e.g. jdoe@corp.example.com).
/// - cn — GLAuth + some OpenLDAP deployments where users are keyed by common-name.
///
/// Used only when is non-empty (search-then-bind path) —
/// direct-bind fallback constructs the DN as cn=<name>,<SearchBase>
/// regardless of this setting and is not a production-grade path against AD.
///
public string UserNameAttribute { get; init; } = "uid";
///
/// LDAP group → OPC UA role. Each authenticated user gets every role whose source group
/// is in their membership list. Recognized role names (CLAUDE.md): ReadOnly (browse
/// + read), WriteOperate, WriteTune, WriteConfigure, AlarmAck.
///
public Dictionary GroupToRole { get; init; } = new(StringComparer.OrdinalIgnoreCase);
}