docs: backfill XML documentation across 756 files
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
v2-ci / build (push) Failing after 1m43s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>, <param>, <typeparam>, and <inheritdoc/> tags to public members surfaced by commentchecker — resolves 5,847 of 5,869 issues (99.6%) across three /fixdocs passes.
This commit is contained in:
@@ -2,5 +2,10 @@ namespace ZB.MOM.WW.OtOpcUa.Security.Ldap;
|
||||
|
||||
public interface ILdapAuthService
|
||||
{
|
||||
/// <summary>Authenticates a user against the LDAP service.</summary>
|
||||
/// <param name="username">The username to authenticate.</param>
|
||||
/// <param name="password">The password to verify.</param>
|
||||
/// <param name="ct">A cancellation token.</param>
|
||||
/// <returns>A task that returns the authentication result.</returns>
|
||||
Task<LdapAuthResult> AuthenticateAsync(string username, string password, CancellationToken ct = default);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,10 @@ public sealed class LdapAuthService(IOptions<LdapOptions> options, ILogger<LdapA
|
||||
{
|
||||
private readonly LdapOptions _options = options.Value;
|
||||
|
||||
/// <summary>Authenticates a user via LDAP bind and retrieves their group memberships and roles.</summary>
|
||||
/// <param name="username">The username to authenticate.</param>
|
||||
/// <param name="password">The password to validate against the LDAP directory.</param>
|
||||
/// <param name="ct">A cancellation token to observe while waiting for the operation to complete.</param>
|
||||
public async Task<LdapAuthResult> AuthenticateAsync(string username, string password, CancellationToken ct = default)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
@@ -130,6 +134,9 @@ public sealed class LdapAuthService(IOptions<LdapOptions> options, ILogger<LdapA
|
||||
: $"cn={username},{_options.SearchBase}";
|
||||
}
|
||||
|
||||
/// <summary>Escapes special characters in an LDAP filter string according to RFC 4515.</summary>
|
||||
/// <param name="input">The unescaped string to escape.</param>
|
||||
/// <returns>The escaped LDAP filter string.</returns>
|
||||
internal static string EscapeLdapFilter(string input) =>
|
||||
input.Replace("\\", "\\5c")
|
||||
.Replace("*", "\\2a")
|
||||
@@ -142,6 +149,8 @@ public sealed class LdapAuthService(IOptions<LdapOptions> options, ILogger<LdapA
|
||||
/// group as an <c>ou=</c> RDN immediately above the user's <c>cn=</c>, so this recovers
|
||||
/// the group name when <see cref="LdapOptions.GroupAttribute"/> is absent from the entry.
|
||||
/// </summary>
|
||||
/// <param name="dn">The distinguished name to extract the OU from.</param>
|
||||
/// <returns>The extracted OU value, or null if no OU segment is found.</returns>
|
||||
internal static string? ExtractOuSegment(string dn)
|
||||
{
|
||||
var segments = dn.Split(',');
|
||||
@@ -154,6 +163,9 @@ public sealed class LdapAuthService(IOptions<LdapOptions> options, ILogger<LdapA
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>Extracts the value portion of the first RDN (relative distinguished name) from a DN.</summary>
|
||||
/// <param name="dn">The distinguished name to extract from.</param>
|
||||
/// <returns>The value of the first RDN.</returns>
|
||||
internal static string ExtractFirstRdnValue(string dn)
|
||||
{
|
||||
var equalsIdx = dn.IndexOf('=');
|
||||
|
||||
@@ -9,9 +9,16 @@ public sealed class LdapOptions
|
||||
{
|
||||
public const string SectionName = "Authentication:Ldap";
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether LDAP authentication is enabled.</summary>
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
/// <summary>Gets or sets the LDAP server hostname.</summary>
|
||||
public string Server { get; set; } = "localhost";
|
||||
|
||||
/// <summary>Gets or sets the LDAP server port.</summary>
|
||||
public int Port { get; set; } = 3893;
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether to use TLS for LDAP connection.</summary>
|
||||
public bool UseTls { get; set; }
|
||||
|
||||
/// <summary>Dev-only escape hatch — must be <c>false</c> in production.</summary>
|
||||
@@ -24,6 +31,7 @@ public sealed class LdapOptions
|
||||
/// </summary>
|
||||
public bool DevStubMode { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the LDAP search base DN.</summary>
|
||||
public string SearchBase { get; set; } = "dc=lmxopcua,dc=local";
|
||||
|
||||
/// <summary>
|
||||
@@ -31,9 +39,14 @@ public sealed class LdapOptions
|
||||
/// <c>cn={user},{SearchBase}</c> is attempted.
|
||||
/// </summary>
|
||||
public string ServiceAccountDn { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the service account password for LDAP authentication.</summary>
|
||||
public string ServiceAccountPassword { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the LDAP attribute name for user display name.</summary>
|
||||
public string DisplayNameAttribute { get; set; } = "cn";
|
||||
|
||||
/// <summary>Gets or sets the LDAP attribute name for group membership.</summary>
|
||||
public string GroupAttribute { get; set; } = "memberOf";
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -6,6 +6,10 @@ namespace ZB.MOM.WW.OtOpcUa.Security.Ldap;
|
||||
/// </summary>
|
||||
public static class RoleMapper
|
||||
{
|
||||
/// <summary>Maps LDAP groups to roles using the provided group-to-role mapping dictionary.</summary>
|
||||
/// <param name="ldapGroups">The LDAP groups to map.</param>
|
||||
/// <param name="groupToRole">The mapping dictionary from LDAP groups to roles.</param>
|
||||
/// <returns>The list of roles corresponding to the LDAP groups.</returns>
|
||||
public static IReadOnlyList<string> Map(
|
||||
IReadOnlyCollection<string> ldapGroups,
|
||||
IReadOnlyDictionary<string, string> groupToRole)
|
||||
|
||||
Reference in New Issue
Block a user