using ZB.MOM.WW.MxGateway.Contracts.Proto; using ZB.MOM.WW.MxGateway.Contracts.Proto.Galaxy; using ZB.MOM.WW.MxGateway.Server.Security.Authorization; namespace ZB.MOM.WW.MxGateway.Tests.Security.Authorization; public sealed class GatewayGrpcScopeResolverTests { /// Verifies that ResolveRequiredScope returns the expected scope for known RPC request types. /// The gRPC request type to test. /// The expected scope for the request. [Theory] [InlineData(typeof(OpenSessionRequest), GatewayScopes.SessionOpen)] [InlineData(typeof(CloseSessionRequest), GatewayScopes.SessionClose)] [InlineData(typeof(StreamEventsRequest), GatewayScopes.EventsRead)] [InlineData(typeof(AcknowledgeAlarmRequest), GatewayScopes.InvokeWrite)] [InlineData(typeof(StreamAlarmsRequest), GatewayScopes.EventsRead)] [InlineData(typeof(TestConnectionRequest), GatewayScopes.MetadataRead)] [InlineData(typeof(GetLastDeployTimeRequest), GatewayScopes.MetadataRead)] [InlineData(typeof(DiscoverHierarchyRequest), GatewayScopes.MetadataRead)] [InlineData(typeof(WatchDeployEventsRequest), GatewayScopes.MetadataRead)] [InlineData(typeof(BrowseChildrenRequest), GatewayScopes.MetadataRead)] public void ResolveRequiredScope_KnownRpcRequest_ReturnsExpectedScope( Type requestType, string expectedScope) { GatewayGrpcScopeResolver resolver = new(); object request = Activator.CreateInstance(requestType)!; string scope = resolver.ResolveRequiredScope(request); Assert.Equal(expectedScope, scope); } /// Verifies that ResolveRequiredScope returns the expected scope for MXAccess invoke commands. /// The MXAccess command kind to test. /// The expected scope for the command. [Theory] [InlineData(MxCommandKind.Register, GatewayScopes.InvokeRead)] [InlineData(MxCommandKind.AddItem, GatewayScopes.InvokeRead)] [InlineData(MxCommandKind.Advise, GatewayScopes.InvokeRead)] [InlineData(MxCommandKind.Write, GatewayScopes.InvokeWrite)] [InlineData(MxCommandKind.Write2, GatewayScopes.InvokeWrite)] [InlineData(MxCommandKind.WriteSecured, GatewayScopes.InvokeSecure)] [InlineData(MxCommandKind.WriteSecured2, GatewayScopes.InvokeSecure)] [InlineData(MxCommandKind.WriteBulk, GatewayScopes.InvokeWrite)] [InlineData(MxCommandKind.Write2Bulk, GatewayScopes.InvokeWrite)] [InlineData(MxCommandKind.WriteSecuredBulk, GatewayScopes.InvokeSecure)] [InlineData(MxCommandKind.WriteSecured2Bulk, GatewayScopes.InvokeSecure)] [InlineData(MxCommandKind.ReadBulk, GatewayScopes.InvokeRead)] [InlineData(MxCommandKind.AuthenticateUser, GatewayScopes.InvokeSecure)] [InlineData(MxCommandKind.ArchestraUserToId, GatewayScopes.MetadataRead)] [InlineData(MxCommandKind.GetSessionState, GatewayScopes.MetadataRead)] [InlineData(MxCommandKind.GetWorkerInfo, GatewayScopes.MetadataRead)] [InlineData(MxCommandKind.DrainEvents, GatewayScopes.EventsRead)] [InlineData(MxCommandKind.ShutdownWorker, GatewayScopes.Admin)] public void ResolveRequiredScope_InvokeCommand_ReturnsExpectedScope( MxCommandKind commandKind, string expectedScope) { GatewayGrpcScopeResolver resolver = new(); string scope = resolver.ResolveRequiredScope(new MxCommandRequest { Command = new MxCommand { Kind = commandKind } }); Assert.Equal(expectedScope, scope); } /// /// Verifies that an unmapped request type fails closed: the resolver returns the /// most-restrictive scope rather than a permissive /// default, so a newly added RPC that is never mapped is denied to ordinary keys. /// [Fact] public void ResolveRequiredScope_UnmappedRequestType_FailsClosedToAdminScope() { GatewayGrpcScopeResolver resolver = new(); string scope = resolver.ResolveRequiredScope(new UnmappedRequest()); Assert.Equal(GatewayScopes.Admin, scope); } /// /// Verifies that an with an unrecognized command kind /// resolves to the read scope rather than silently granting write or admin access. /// [Fact] public void ResolveRequiredScope_UnknownInvokeCommandKind_ReturnsInvokeReadScope() { GatewayGrpcScopeResolver resolver = new(); string scope = resolver.ResolveRequiredScope(new MxCommandRequest { Command = new MxCommand { Kind = (MxCommandKind)9999, }, }); Assert.Equal(GatewayScopes.InvokeRead, scope); } /// Request type intentionally not mapped by the scope resolver. private sealed class UnmappedRequest; }