a1ea34bc01
Consolidate data and config into separate folders that will be expected to be mapped in the container Reviewed-on: #1 Co-authored-by: Huy Nguyen <ecenshu@gmail.com> Co-committed-by: Huy Nguyen <ecenshu@gmail.com>
117 lines
3.7 KiB
C#
117 lines
3.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.Extensions.Logging;
|
|
using Moq;
|
|
using NUnit.Framework;
|
|
using TinfoilVibeServer.Authentication;
|
|
using TinfoilVibeServer.Middleware;
|
|
|
|
namespace TinfoilVibeServerTest.Tests
|
|
{
|
|
[TestFixture]
|
|
public class BasicAuthMiddlewareTests
|
|
{
|
|
private Mock<ILogger<BasicAuthMiddleware>> _loggerMock;
|
|
private Mock<IAuthStore> _authMock;
|
|
private BasicAuthMiddleware _middleware;
|
|
private RequestDelegate _next;
|
|
|
|
[SetUp]
|
|
public void SetUp()
|
|
{
|
|
_loggerMock = new Mock<ILogger<BasicAuthMiddleware>>();
|
|
_authMock = new Mock<IAuthStore>();
|
|
_next = (HttpContext ctx) => Task.CompletedTask;
|
|
|
|
_middleware = new BasicAuthMiddleware(_next);
|
|
}
|
|
|
|
private HttpContext CreateContext(string authHeader = "", string ip = "127.0.0.1", string uid = "")
|
|
{
|
|
var ctx = new DefaultHttpContext();
|
|
ctx.Connection.RemoteIpAddress = IPAddress.Parse(ip);
|
|
|
|
if (!string.IsNullOrEmpty(authHeader))
|
|
{
|
|
ctx.Request.Headers["Authorization"] = authHeader;
|
|
}
|
|
|
|
if (uid!= null)
|
|
{
|
|
ctx.Request.Headers["UID"] = uid.ToString();
|
|
}
|
|
|
|
return ctx;
|
|
}
|
|
|
|
[Test]
|
|
public async Task InvokeAsync_NoAuthHeader_ShouldReturn401()
|
|
{
|
|
// Arrange
|
|
var ctx = CreateContext();
|
|
ctx.Request.Path = new PathString("/");
|
|
|
|
// Act
|
|
await _middleware.InvokeAsync(ctx, _authMock.Object, _loggerMock.Object);
|
|
|
|
// Assert
|
|
Assert.That(ctx.Response.StatusCode, Is.EqualTo(StatusCodes.Status401Unauthorized));
|
|
_loggerMock.Verify(l => l.Log(
|
|
LogLevel.Warning,
|
|
It.IsAny<EventId>(),
|
|
It.Is<It.IsAnyType>((v, t) => v.ToString().Contains("Missing Authorization header")),
|
|
null,
|
|
It.IsAny<Func<It.IsAnyType, Exception, string>>()), Times.Once);
|
|
}
|
|
|
|
[Test]
|
|
public async Task InvokeAsync_BlacklistedIP_ShouldReturn403()
|
|
{
|
|
// Arrange
|
|
var ctx = CreateContext("Basic dXNlcjpwYXNz");
|
|
ctx.Request.Path = new PathString("/");
|
|
_authMock.Setup(a => a.IsIPBlacklisted("127.0.0.1")).Returns(true);
|
|
|
|
// Act
|
|
|
|
await _middleware.InvokeAsync(ctx, _authMock.Object, _loggerMock.Object);
|
|
|
|
// Assert
|
|
Assert.That(ctx.Response.StatusCode, Is.EqualTo(StatusCodes.Status403Forbidden));
|
|
}
|
|
|
|
[Test]
|
|
public async Task InvokeAsync_ValidCredentials_ShouldCallNext()
|
|
{
|
|
// Arrange
|
|
var user = "alice";
|
|
var pw = "secret";
|
|
var uid = "1234";
|
|
var header = $"Basic {Convert.ToBase64String(Encoding.ASCII.GetBytes($"{user}:{pw}"))}";
|
|
|
|
var ip = "127.0.0.1";
|
|
var ctx = CreateContext(header,ip, uid);
|
|
|
|
string? error;
|
|
_authMock.Setup(a =>
|
|
a.TryValidate(user, pw, uid, ip, out error))
|
|
.Returns(true);
|
|
|
|
bool nextCalled = false;
|
|
_next = (HttpContext _) => { nextCalled = true; return Task.CompletedTask; };
|
|
_middleware = new BasicAuthMiddleware(_next);
|
|
|
|
// Act
|
|
await _middleware.InvokeAsync(ctx, _authMock.Object, _loggerMock.Object);
|
|
|
|
// Assert
|
|
Assert.That(nextCalled, Is.True);
|
|
Assert.That(ctx.Response.StatusCode, Is.EqualTo(StatusCodes.Status200OK));
|
|
}
|
|
}
|
|
} |