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);
}
}