using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using ZB.MOM.WW.ScadaBridge.ManagementService; using ZB.MOM.WW.ScadaBridge.Security; using ZB.MOM.WW.ScadaBridge.Security.Auth; namespace ZB.MOM.WW.ScadaBridge.ManagementService.Tests; /// /// Tests for the dev/test DisableLogin bypass on the management/CLI auth surface /// (). The bypass lets the HTTP-Basic CLI surfaces /// authenticate without LDAP when login is disabled — mirroring the interactive cookie /// handler — so a login-disabled deployment is not locked out of the CLI. /// public class ManagementAuthenticatorTests { private static HttpContext ContextWith(AuthDisableLoginOptions options) { var services = new ServiceCollection(); services.AddSingleton>(Options.Create(options)); return new DefaultHttpContext { RequestServices = services.BuildServiceProvider() }; } [Fact] public void TryDisableLoginUser_WhenDisabled_ReturnsNull() { var context = ContextWith(new AuthDisableLoginOptions { DisableLogin = false }); Assert.Null(ManagementAuthenticator.TryDisableLoginUser(context)); } [Fact] public void TryDisableLoginUser_WhenNoOptionsRegistered_ReturnsNull() { var context = new DefaultHttpContext { RequestServices = new ServiceCollection().BuildServiceProvider(), }; Assert.Null(ManagementAuthenticator.TryDisableLoginUser(context)); } [Fact] public void TryDisableLoginUser_WhenEnabled_ReturnsDevUserWithAllRolesSystemWide() { var context = ContextWith(new AuthDisableLoginOptions { DisableLogin = true, User = "ci-bot" }); var user = ManagementAuthenticator.TryDisableLoginUser(context); Assert.NotNull(user); Assert.Equal("ci-bot", user!.Username); Assert.Equal("ci-bot", user.DisplayName); Assert.Equal(Roles.All, user.Roles); Assert.Empty(user.PermittedSiteIds); // empty == system-wide, mirrors AutoLoginAuthenticationHandler } [Fact] public void TryDisableLoginUser_WhenEnabledWithBlankUser_FallsBackToMultiRole() { var context = ContextWith(new AuthDisableLoginOptions { DisableLogin = true, User = " " }); var user = ManagementAuthenticator.TryDisableLoginUser(context); Assert.NotNull(user); Assert.Equal("multi-role", user!.Username); } [Fact] public async Task AuthenticateAsync_WhenDisabled_BypassesBasicAuthAndReturnsDevUser() { // No Authorization header and no ILdapAuthService registered: the bypass must short-circuit // before either is consulted. var context = ContextWith(new AuthDisableLoginOptions { DisableLogin = true }); var outcome = await ManagementAuthenticator.AuthenticateAsync(context); Assert.Null(outcome.Failure); Assert.NotNull(outcome.User); Assert.Equal("multi-role", outcome.User!.Username); Assert.Equal(Roles.All, outcome.User.Roles); } [Fact] public async Task AuthenticateAsync_WhenEnabledWithNoHeader_ReturnsUnauthorized() { // Login NOT disabled and no Basic header: the real auth path rejects with a 401 result // before any LDAP lookup. var context = ContextWith(new AuthDisableLoginOptions { DisableLogin = false }); var outcome = await ManagementAuthenticator.AuthenticateAsync(context); Assert.Null(outcome.User); Assert.NotNull(outcome.Failure); } }