Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 75 additions & 6 deletions src/Ombi.Tests/Middlewear/ApiKeyMiddlewearTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
using NUnit.Framework;
using NUnit.Framework.Constraints;
using Ombi.Core.Authentication;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models;
using Ombi.Test.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -44,7 +47,7 @@ public async Task ValidateUserAccessToken()
{
var context = GetContext();
context.Request.Path = "/api";
context.Request.Headers.Add("UserAccessToken", new Microsoft.Extensions.Primitives.StringValues("test"));
context.Request.Headers["UserAccessToken"] = "test";
var user = new Store.Entities.OmbiUser
{
UserAccessToken = "test",
Expand All @@ -55,8 +58,10 @@ public async Task ValidateUserAccessToken()
user
});
umMock.Setup(x => x.GetRolesAsync(user)).ReturnsAsync(new List<string> { "Admin" });
#nullable enable
_mocker.Setup<IServiceProvider, object?>(x => x.GetService(typeof(OmbiUserManager)))
.Returns(umMock.Object);
#nullable disable


await _subject.Invoke(context);
Expand All @@ -70,27 +75,91 @@ public async Task ValidateUserAccessToken_Token_Invalid()
{
var context = GetContext();
context.Request.Path = "/api";
context.Request.Headers.Add("UserAccessToken", new Microsoft.Extensions.Primitives.StringValues("invalid"));
context.Request.Headers["UserAccessToken"] ="invalid";
var user = new Store.Entities.OmbiUser
{
UserAccessToken = "test",
UserName = "unit test"
};
var umMock = MockHelper.MockUserManager(new List<Store.Entities.OmbiUser>
{
var umMock = MockHelper.MockUserManager(
[
user
});
]);
umMock.Setup(x => x.GetRolesAsync(user)).ReturnsAsync(new List<string> { "Admin" });
#nullable enable
_mocker.Setup<IServiceProvider, object?>(x => x.GetService(typeof(OmbiUserManager)))
.Returns(umMock.Object);

#nullable disable

await _subject.Invoke(context);

Assert.That(context.Response.StatusCode, Is.EqualTo(401));
umMock.Verify(x => x.UpdateAsync(user), Times.Never);
}

[Test]
public async Task ValidateApiKey_InvalidUser()
{
var context = GetContext();
context.Request.Path = "/api";
context.Request.Headers["ApiKey"] = "validkey";
context.Request.Headers["UserName"] = "nonexistent";

using (var bodyStream = new MemoryStream()) {
context.Response.Body = bodyStream;

var settingsMock = new Mock<ISettingsService<OmbiSettings>>();
settingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new OmbiSettings { ApiKey = "validkey" });
#nullable enable
_mocker.Setup<IServiceProvider, object?>(x => x.GetService(typeof(ISettingsService<OmbiSettings>))).Returns(settingsMock.Object);
#nullable disable

var umMock = MockHelper.MockUserManager(new List<Store.Entities.OmbiUser>());
#nullable enable
_mocker.Setup<IServiceProvider, object?>(x => x.GetService(typeof(OmbiUserManager))).Returns(umMock.Object);
#nullable disable

var nextMock = new Mock<RequestDelegate>();
nextMock.Setup(n => n.Invoke(It.IsAny<HttpContext>())).Returns(Task.CompletedTask);
var subject = new ApiKeyMiddlewear(nextMock.Object);

await subject.Invoke(context);

Assert.That(context.Response.StatusCode, Is.EqualTo(401));
bodyStream.Position = 0;
using (var reader = new StreamReader(bodyStream))
{
var body = await reader.ReadToEndAsync();
Assert.That(body, Is.EqualTo("Invalid User"));
nextMock.Verify(x => x.Invoke(It.IsAny<HttpContext>()), Times.Never);
}
}
}

[Test]
public async Task ValidateApiKey_NoUserNameHeader()
{
var context = GetContext();
context.Request.Path = "/api";
context.Request.Headers["ApiKey"] = "validkey";

var settingsMock = new Mock<ISettingsService<OmbiSettings>>();
settingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new OmbiSettings { ApiKey = "validkey" });
#nullable enable
_mocker.Setup<IServiceProvider, object?>(x => x.GetService(typeof(ISettingsService<OmbiSettings>))).Returns(settingsMock.Object);
#nullable disable

var nextMock = new Mock<RequestDelegate>();
nextMock.Setup(n => n.Invoke(It.IsAny<HttpContext>())).Returns(Task.CompletedTask);
var subject = new ApiKeyMiddlewear(nextMock.Object);

await subject.Invoke(context);

Assert.That(context.Response.StatusCode, Is.EqualTo(200)); // Default status
Assert.That(context.User.Identity.Name, Is.EqualTo("API"));
nextMock.Verify(x => x.Invoke(It.IsAny<HttpContext>()), Times.Once);
}

private HttpContext GetContext()
{
var context = new DefaultHttpContext();
Expand Down
28 changes: 14 additions & 14 deletions src/Ombi/Middleware/ApiKeyMiddlewear.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,22 @@ private async Task ValidateApiKey(HttpContext context, RequestDelegate next, str
else
{
username = username.ToUpper();
}

var um = context.RequestServices.GetService<OmbiUserManager>();

var user = await um.Users.FirstOrDefaultAsync(x =>
x.NormalizedUserName == username);
if (user == null)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await context.Response.WriteAsync("Invalid User");
await next.Invoke(context);
var um = context.RequestServices.GetService<OmbiUserManager>();

var user = await um.Users.FirstOrDefaultAsync(x =>
x.NormalizedUserName == username);
if (user == null)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await context.Response.WriteAsync("Invalid User");
return;
}
var roles = await um.GetRolesAsync(user);
var identity = new GenericIdentity(user.UserName);
var principal = new GenericPrincipal(identity, roles.ToArray());
context.User = principal;
}
var roles = await um.GetRolesAsync(user);
var identity = new GenericIdentity(user.UserName);
var principal = new GenericPrincipal(identity, roles.ToArray());
context.User = principal;
}
else
{
Expand Down
Loading