using System.Collections.Generic; using Shouldly; using Xunit; using ZB.MOM.WW.LmxOpcUa.Host.Configuration; using ZB.MOM.WW.LmxOpcUa.Host.Domain; namespace ZB.MOM.WW.LmxOpcUa.Tests.Authentication { public class UserAuthenticationTests { [Fact] public void ValidCredentials_ReturnsTrue() { var provider = new ConfigUserAuthenticationProvider(new List { new UserCredential { Username = "operator", Password = "op123" } }); provider.ValidateCredentials("operator", "op123").ShouldBeTrue(); } [Fact] public void WrongPassword_ReturnsFalse() { var provider = new ConfigUserAuthenticationProvider(new List { new UserCredential { Username = "operator", Password = "op123" } }); provider.ValidateCredentials("operator", "wrong").ShouldBeFalse(); } [Fact] public void UnknownUsername_ReturnsFalse() { var provider = new ConfigUserAuthenticationProvider(new List { new UserCredential { Username = "operator", Password = "op123" } }); provider.ValidateCredentials("unknown", "op123").ShouldBeFalse(); } [Fact] public void Username_IsCaseInsensitive() { var provider = new ConfigUserAuthenticationProvider(new List { new UserCredential { Username = "Operator", Password = "op123" } }); provider.ValidateCredentials("operator", "op123").ShouldBeTrue(); provider.ValidateCredentials("OPERATOR", "op123").ShouldBeTrue(); } [Fact] public void EmptyUserList_RejectsAll() { var provider = new ConfigUserAuthenticationProvider(new List()); provider.ValidateCredentials("anyone", "anything").ShouldBeFalse(); } [Fact] public void AuthenticationConfiguration_Defaults() { var config = new AuthenticationConfiguration(); config.AllowAnonymous.ShouldBeTrue(); config.AnonymousCanWrite.ShouldBeTrue(); config.Users.ShouldBeEmpty(); } [Fact] public void AuthenticationConfiguration_LdapDefaults() { var config = new AuthenticationConfiguration(); config.Ldap.ShouldNotBeNull(); config.Ldap.Enabled.ShouldBeFalse(); config.Ldap.Host.ShouldBe("localhost"); config.Ldap.Port.ShouldBe(3893); config.Ldap.BaseDN.ShouldBe("dc=lmxopcua,dc=local"); config.Ldap.ReadOnlyGroup.ShouldBe("ReadOnly"); config.Ldap.ReadWriteGroup.ShouldBe("ReadWrite"); config.Ldap.AlarmAckGroup.ShouldBe("AlarmAck"); config.Ldap.TimeoutSeconds.ShouldBe(5); } [Fact] public void LdapConfiguration_BindDnTemplate_Default() { var config = new LdapConfiguration(); config.BindDnTemplate.ShouldBe("cn={username},dc=lmxopcua,dc=local"); } [Fact] public void LdapAuthenticationProvider_ValidBind_ReturnsTrue() { // This test requires GLAuth running on localhost:3893 // Skip if not available var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("readonly", "readonly123").ShouldBeTrue(); } catch (System.Exception) { // GLAuth not running - skip gracefully return; } } [Fact] public void LdapAuthenticationProvider_InvalidPassword_ReturnsFalse() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("readonly", "wrongpassword").ShouldBeFalse(); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_UnknownUser_ReturnsFalse() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("nonexistent", "anything").ShouldBeFalse(); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_ReadOnlyUser_HasReadOnlyRole() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("readonly", "readonly123").ShouldBeTrue(); var roles = provider.GetUserRoles("readonly"); roles.ShouldContain("ReadOnly"); roles.ShouldNotContain("ReadWrite"); roles.ShouldNotContain("AlarmAck"); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_ReadWriteUser_HasReadWriteRole() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("readwrite", "readwrite123").ShouldBeTrue(); var roles = provider.GetUserRoles("readwrite"); roles.ShouldContain("ReadWrite"); roles.ShouldNotContain("AlarmAck"); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_AlarmAckUser_HasAlarmAckRole() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("alarmack", "alarmack123").ShouldBeTrue(); var roles = provider.GetUserRoles("alarmack"); roles.ShouldContain("AlarmAck"); roles.ShouldNotContain("ReadWrite"); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_AdminUser_HasAllRoles() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); try { provider.ValidateCredentials("admin", "admin123").ShouldBeTrue(); var roles = provider.GetUserRoles("admin"); roles.ShouldContain("ReadOnly"); roles.ShouldContain("ReadWrite"); roles.ShouldContain("AlarmAck"); } catch (System.Exception) { return; // GLAuth not running } } [Fact] public void LdapAuthenticationProvider_ImplementsIRoleProvider() { var ldapConfig = CreateGlAuthConfig(); var provider = new LdapAuthenticationProvider(ldapConfig); (provider is IRoleProvider).ShouldBeTrue(); } [Fact] public void ConfigUserAuthenticationProvider_DoesNotImplementIRoleProvider() { var provider = new ConfigUserAuthenticationProvider(new List()); (provider is IRoleProvider).ShouldBeFalse(); } [Fact] public void LdapAuthenticationProvider_ConnectionFailure_ReturnsFalse() { var ldapConfig = new LdapConfiguration { Enabled = true, Host = "localhost", Port = 19999, // no server here TimeoutSeconds = 1 }; var provider = new LdapAuthenticationProvider(ldapConfig); provider.ValidateCredentials("anyone", "anything").ShouldBeFalse(); } [Fact] public void LdapAuthenticationProvider_ConnectionFailure_GetUserRoles_FallsBackToReadOnly() { var ldapConfig = new LdapConfiguration { Enabled = true, Host = "localhost", Port = 19999, // no server here TimeoutSeconds = 1, ServiceAccountDn = "cn=svc,dc=test", ServiceAccountPassword = "test" }; var provider = new LdapAuthenticationProvider(ldapConfig); var roles = provider.GetUserRoles("anyone"); roles.ShouldContain("ReadOnly"); } private static LdapConfiguration CreateGlAuthConfig() { return new LdapConfiguration { Enabled = true, Host = "localhost", Port = 3893, BaseDN = "dc=lmxopcua,dc=local", BindDnTemplate = "cn={username},dc=lmxopcua,dc=local", ServiceAccountDn = "cn=serviceaccount,dc=lmxopcua,dc=local", ServiceAccountPassword = "serviceaccount123", TimeoutSeconds = 5, ReadOnlyGroup = "ReadOnly", ReadWriteGroup = "ReadWrite", AlarmAckGroup = "AlarmAck" }; } } }