Remove static Users auth, use shared QualityMapper for historian, simplify LDAP permission checks

- Remove ConfigUserAuthenticationProvider and Users property — LDAP is the only auth mechanism
- Fix historian quality mapping to use existing QualityMapper (OPC DA quality bytes, not custom mapping)
- Add AppRoles constants, unify HasWritePermission/HasAlarmAckPermission into shared HasRole helper
- Hoist write permission check out of per-item loop, eliminate redundant _ldapRolesEnabled field
- Update docs (Configuration.md, Security.md, OpcUaServer.md, HistoricalDataAccess.md)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-03-28 19:23:20 -04:00
parent 74107ea95e
commit d9463d6998
19 changed files with 93 additions and 273 deletions

View File

@@ -1,4 +1,3 @@
using System.Collections.Generic;
using Shouldly;
using Xunit;
using ZB.MOM.WW.LmxOpcUa.Host.Configuration;
@@ -8,59 +7,6 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Authentication
{
public class UserAuthenticationTests
{
[Fact]
public void ValidCredentials_ReturnsTrue()
{
var provider = new ConfigUserAuthenticationProvider(new List<UserCredential>
{
new UserCredential { Username = "operator", Password = "op123" }
});
provider.ValidateCredentials("operator", "op123").ShouldBeTrue();
}
[Fact]
public void WrongPassword_ReturnsFalse()
{
var provider = new ConfigUserAuthenticationProvider(new List<UserCredential>
{
new UserCredential { Username = "operator", Password = "op123" }
});
provider.ValidateCredentials("operator", "wrong").ShouldBeFalse();
}
[Fact]
public void UnknownUsername_ReturnsFalse()
{
var provider = new ConfigUserAuthenticationProvider(new List<UserCredential>
{
new UserCredential { Username = "operator", Password = "op123" }
});
provider.ValidateCredentials("unknown", "op123").ShouldBeFalse();
}
[Fact]
public void Username_IsCaseInsensitive()
{
var provider = new ConfigUserAuthenticationProvider(new List<UserCredential>
{
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<UserCredential>());
provider.ValidateCredentials("anyone", "anything").ShouldBeFalse();
}
[Fact]
public void AuthenticationConfiguration_Defaults()
{
@@ -68,7 +14,6 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Authentication
config.AllowAnonymous.ShouldBeTrue();
config.AnonymousCanWrite.ShouldBeTrue();
config.Users.ShouldBeEmpty();
}
[Fact]
@@ -232,13 +177,6 @@ namespace ZB.MOM.WW.LmxOpcUa.Tests.Authentication
(provider is IRoleProvider).ShouldBeTrue();
}
[Fact]
public void ConfigUserAuthenticationProvider_DoesNotImplementIRoleProvider()
{
var provider = new ConfigUserAuthenticationProvider(new List<UserCredential>());
(provider is IRoleProvider).ShouldBeFalse();
}
[Fact]
public void LdapAuthenticationProvider_ConnectionFailure_ReturnsFalse()
{