diff --git a/src/Ombi.Tests/Middlewear/ApiKeyMiddlewearTests.cs b/src/Ombi.Tests/Middlewear/ApiKeyMiddlewearTests.cs index 5768994766..402f4480bf 100644 --- a/src/Ombi.Tests/Middlewear/ApiKeyMiddlewearTests.cs +++ b/src/Ombi.Tests/Middlewear/ApiKeyMiddlewearTests.cs @@ -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; @@ -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", @@ -55,8 +58,10 @@ public async Task ValidateUserAccessToken() user }); umMock.Setup(x => x.GetRolesAsync(user)).ReturnsAsync(new List { "Admin" }); +#nullable enable _mocker.Setup(x => x.GetService(typeof(OmbiUserManager))) .Returns(umMock.Object); +#nullable disable await _subject.Invoke(context); @@ -70,20 +75,21 @@ 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 - { + var umMock = MockHelper.MockUserManager( + [ user - }); + ]); umMock.Setup(x => x.GetRolesAsync(user)).ReturnsAsync(new List { "Admin" }); +#nullable enable _mocker.Setup(x => x.GetService(typeof(OmbiUserManager))) .Returns(umMock.Object); - +#nullable disable await _subject.Invoke(context); @@ -91,6 +97,69 @@ public async Task ValidateUserAccessToken_Token_Invalid() 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>(); + settingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new OmbiSettings { ApiKey = "validkey" }); +#nullable enable + _mocker.Setup(x => x.GetService(typeof(ISettingsService))).Returns(settingsMock.Object); +#nullable disable + + var umMock = MockHelper.MockUserManager(new List()); +#nullable enable + _mocker.Setup(x => x.GetService(typeof(OmbiUserManager))).Returns(umMock.Object); +#nullable disable + + var nextMock = new Mock(); + nextMock.Setup(n => n.Invoke(It.IsAny())).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()), Times.Never); + } + } + } + + [Test] + public async Task ValidateApiKey_NoUserNameHeader() + { + var context = GetContext(); + context.Request.Path = "/api"; + context.Request.Headers["ApiKey"] = "validkey"; + + var settingsMock = new Mock>(); + settingsMock.Setup(x => x.GetSettingsAsync()).ReturnsAsync(new OmbiSettings { ApiKey = "validkey" }); +#nullable enable + _mocker.Setup(x => x.GetService(typeof(ISettingsService))).Returns(settingsMock.Object); +#nullable disable + + var nextMock = new Mock(); + nextMock.Setup(n => n.Invoke(It.IsAny())).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()), Times.Once); + } + private HttpContext GetContext() { var context = new DefaultHttpContext(); diff --git a/src/Ombi/Middleware/ApiKeyMiddlewear.cs b/src/Ombi/Middleware/ApiKeyMiddlewear.cs index d5e0115093..7e3ef6d58b 100644 --- a/src/Ombi/Middleware/ApiKeyMiddlewear.cs +++ b/src/Ombi/Middleware/ApiKeyMiddlewear.cs @@ -108,22 +108,22 @@ private async Task ValidateApiKey(HttpContext context, RequestDelegate next, str else { username = username.ToUpper(); - } - - var um = context.RequestServices.GetService(); - 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(); + + 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 {