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:
@@ -1,20 +0,0 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
|
||||
namespace ZB.MOM.WW.LmxOpcUa.IntegrationTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Placeholder integration test that keeps the integration test project wired into the solution.
|
||||
/// </summary>
|
||||
public class SampleIntegrationTest
|
||||
{
|
||||
/// <summary>
|
||||
/// Confirms that the integration test assembly is executing.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Placeholder_ShouldPass()
|
||||
{
|
||||
true.ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -1,54 +1,44 @@
|
||||
using Opc.Ua;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Historian;
|
||||
using ZB.MOM.WW.LmxOpcUa.Host.Domain;
|
||||
|
||||
namespace ZB.MOM.WW.LmxOpcUa.Tests.Historian
|
||||
{
|
||||
public class HistorianQualityMappingTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verifies that the Historian good-quality sentinel is surfaced to OPC UA clients as a good status code.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Quality0_MapsToGood()
|
||||
{
|
||||
HistorianDataSource.MapQuality(0).ShouldBe(StatusCodes.Good);
|
||||
}
|
||||
private static StatusCode MapHistorianQuality(byte quality)
|
||||
=> QualityMapper.MapToOpcUaStatusCode(QualityMapper.MapFromMxAccessQuality(quality));
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that the Historian bad-quality sentinel is surfaced to OPC UA clients as a bad status code.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void Quality1_MapsToBad()
|
||||
{
|
||||
HistorianDataSource.MapQuality(1).ShouldBe(StatusCodes.Bad);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that Historian uncertainty quality bands are translated into OPC UA uncertain results.
|
||||
/// </summary>
|
||||
/// <param name="quality">A Wonderware Historian quality byte in the uncertain range.</param>
|
||||
[Theory]
|
||||
[InlineData(128)]
|
||||
[InlineData(133)]
|
||||
[InlineData(192)]
|
||||
public void QualityAbove128_MapsToUncertain(byte quality)
|
||||
[InlineData(192)] // Quality.Good
|
||||
[InlineData(216)] // Quality.GoodLocalOverride
|
||||
public void GoodQualityRange_MapsToGood(byte quality)
|
||||
{
|
||||
HistorianDataSource.MapQuality(quality).ShouldBe(StatusCodes.Uncertain);
|
||||
StatusCode.IsGood(MapHistorianQuality(quality)).ShouldBeTrue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that nonzero non-uncertain Historian quality values are treated as bad historical samples.
|
||||
/// </summary>
|
||||
/// <param name="quality">A Wonderware Historian quality byte that should map to an OPC UA bad status.</param>
|
||||
[Theory]
|
||||
[InlineData(2)]
|
||||
[InlineData(50)]
|
||||
[InlineData(127)]
|
||||
public void OtherBadQualities_MapToBad(byte quality)
|
||||
[InlineData(64)] // Quality.Uncertain
|
||||
[InlineData(68)] // Quality.UncertainLastUsable
|
||||
[InlineData(80)] // Quality.UncertainSensorNotAccurate
|
||||
[InlineData(88)] // Quality.UncertainSubNormal
|
||||
[InlineData(128)] // Uncertain range (no exact enum match)
|
||||
public void UncertainQualityRange_MapsToUncertain(byte quality)
|
||||
{
|
||||
HistorianDataSource.MapQuality(quality).ShouldBe(StatusCodes.Bad);
|
||||
StatusCode.IsUncertain(MapHistorianQuality(quality)).ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(0)] // Quality.Bad
|
||||
[InlineData(1)] // Bad range
|
||||
[InlineData(4)] // Quality.BadConfigError
|
||||
[InlineData(8)] // Quality.BadNotConnected
|
||||
[InlineData(20)] // Quality.BadCommFailure
|
||||
[InlineData(50)] // Bad range (no exact enum match)
|
||||
public void BadQualityRange_MapsToBad(byte quality)
|
||||
{
|
||||
StatusCode.IsBad(MapHistorianQuality(quality)).ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user