diff --git a/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs new file mode 100644 index 000000000..56524522b --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/Search/CouchPotatoCacheRuleTests.cs @@ -0,0 +1,64 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Rules.Search; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Core.Tests.Rule.Search +{ + public class CouchPotatoCacheRuleTests + { + [SetUp] + public void Setup() + { + ContextMock = new Mock>(); + Rule = new CouchPotatoCacheRule(ContextMock.Object); + + } + + private CouchPotatoCacheRule Rule { get; set; } + private Mock> ContextMock { get; set; } + + [Test] + public async Task Should_ReturnApproved_WhenMovieIsInCouchPotato() + { + var list = new CouchPotatoCache + { + TheMovieDbId = 123 + }; + + ContextMock.Setup(x => x.FirstOrDefaultAsync(It.IsAny>>())).ReturnsAsync(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result =await Rule.Execute(request); + + Assert.True(result.Success); + Assert.True(request.Approved); + } + + + [Test] + public async Task Should_ReturnNotApproved_WhenMovieIsNotCouchPotato() + { + var list = DbHelper.GetQueryableMockDbSet(new CouchPotatoCache + { + TheMovieDbId = 000012 + }); + + ContextMock.Setup(x => x.GetAll()).Returns(list); + + var request = new SearchMovieViewModel { Id = 123 }; + var result = await Rule.Execute(request); + + Assert.True(result.Success); + Assert.False(request.Approved); + } + } +} diff --git a/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs new file mode 100644 index 000000000..a7f20ac40 --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/Search/EmbyAvailabilityRuleTests.cs @@ -0,0 +1,50 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using Ombi.Core.Models.Search; +using Ombi.Core.Rule.Rules.Search; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Ombi.Store.Repository.Requests; + +namespace Ombi.Core.Tests.Rule.Search +{ + public class EmbyAvailabilityRuleTests + { + [SetUp] + public void Setup() + { + ContextMock = new Mock(); + Rule = new EmbyAvailabilityRule(ContextMock.Object); + } + + private EmbyAvailabilityRule Rule { get; set; } + private Mock ContextMock { get; set; } + + [Test] + public async Task Movie_ShouldBe_Available_WhenFoundInEmby() + { + ContextMock.Setup(x => x.Get(It.IsAny())).ReturnsAsync(new EmbyContent + { + ProviderId = "123" + }); + var search = new SearchMovieViewModel(); + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.True(search.Available); + } + + [Test] + public async Task Movie_ShouldBe_NotAvailable_WhenNotFoundInEmby() + { + ContextMock.Setup(x => x.Get(It.IsAny())).Returns(Task.FromResult(default(EmbyContent))); + var search = new SearchMovieViewModel(); + var result = await Rule.Execute(search); + + Assert.True(result.Success); + Assert.False(search.Available); + } + } +} \ No newline at end of file diff --git a/src/Ombi.Core/Rule/Rules/Search/CouchPotatoCacheRule.cs b/src/Ombi.Core/Rule/Rules/Search/CouchPotatoCacheRule.cs index fc58f1d79..a6deb95d2 100644 --- a/src/Ombi.Core/Rule/Rules/Search/CouchPotatoCacheRule.cs +++ b/src/Ombi.Core/Rule/Rules/Search/CouchPotatoCacheRule.cs @@ -5,24 +5,25 @@ using Ombi.Core.Models.Search; using Ombi.Core.Rule.Interfaces; using Ombi.Store.Context; using Ombi.Store.Entities; +using Ombi.Store.Repository; namespace Ombi.Core.Rule.Rules.Search { public class CouchPotatoCacheRule : BaseSearchRule, IRules { - public CouchPotatoCacheRule(IOmbiContext ctx) + public CouchPotatoCacheRule(IRepository ctx) { _ctx = ctx; } - private readonly IOmbiContext _ctx; + private readonly IRepository _ctx; public async Task Execute(SearchViewModel obj) { if (obj.Type == RequestType.Movie) { // Check if it's in Radarr - var result = await _ctx.CouchPotatoCache.FirstOrDefaultAsync(x => x.TheMovieDbId == obj.Id); + var result = await _ctx.FirstOrDefaultAsync(x => x.TheMovieDbId == obj.Id); if (result != null) { obj.Approved = diff --git a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs index 756aa1b5e..47ab155a1 100644 --- a/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs +++ b/src/Ombi.Schedule.Tests/PlexAvailabilityCheckerTests.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; +using System.Linq.Expressions; using System.Threading.Tasks; using Castle.Components.DictionaryAdapter; using Hangfire; @@ -103,6 +105,7 @@ namespace Ombi.Schedule.Tests SeasonNumber = 2 } }.AsQueryable); + _repo.Setup(x => x.Include(It.IsAny>(),It.IsAny>>())); await Checker.Start(); diff --git a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs index 26e312af8..472697d28 100644 --- a/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs +++ b/src/Ombi.Schedule/Jobs/Plex/PlexAvailabilityChecker.cs @@ -103,7 +103,7 @@ namespace Ombi.Schedule.Jobs.Plex NotificationType = NotificationType.RequestAvailable, RequestId = movie.Id, RequestType = RequestType.Movie, - Recipient = movie.RequestedUser.Email + Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty })); } } diff --git a/src/Ombi.Tests/IdentityControllerTests.cs b/src/Ombi.Tests/IdentityControllerTests.cs new file mode 100644 index 000000000..fb0314362 --- /dev/null +++ b/src/Ombi.Tests/IdentityControllerTests.cs @@ -0,0 +1,132 @@ + +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using NUnit.Framework; +using Ombi.Api.Emby; +using Ombi.Api.Plex; +using Ombi.Config; +using Ombi.Controllers; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Models; +using Ombi.Notifications; +using Ombi.Schedule.Jobs.Ombi; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Context; +using Ombi.Store.Entities; + +namespace Ombi.Tests +{ + [TestFixture] + [Ignore("Need to sort out the DB, looks like it's using the real one...")] + public class IdentityControllerTests + { + [SetUp] + public void Setup() + { + _plexApi = new Mock(); + _embyApi = new Mock(); + _mapper = new Mock(); + _emailProvider = new Mock(); + _emailSettings = new Mock>(); + _customizationSettings = new Mock>(); + _welcomeEmail = new Mock(); + _embySettings = new Mock>(); + _plexSettings = new Mock>(); + + var services = new ServiceCollection(); + services.AddEntityFrameworkInMemoryDatabase() + .AddDbContext(); + services.AddIdentity() + .AddEntityFrameworkStores().AddUserManager(); + + services.AddTransient(x => _plexApi.Object); + services.AddTransient(x => _embyApi.Object); + services.AddTransient(x => _customizationSettings.Object); + services.AddTransient(x => _welcomeEmail.Object); + services.AddTransient(x => _emailSettings.Object); + services.AddTransient(x => _emailProvider.Object); + services.AddTransient(x => _mapper.Object); + services.AddTransient(x => _embySettings.Object); + services.AddTransient(x => _plexSettings.Object); + + services.Configure(options => + { + options.Password.RequireDigit = false; + options.Password.RequiredLength = 1; + options.Password.RequireLowercase = false; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequireUppercase = false; + options.User.AllowedUserNameCharacters = string.Empty; + }); + + // Taken from https://github.com/aspnet/MusicStore/blob/dev/test/MusicStore.Test/ManageControllerTest.cs (and modified) + var context = new DefaultHttpContext(); + context.Features.Set(new HttpAuthenticationFeature()); + services.AddSingleton(h => new HttpContextAccessor { HttpContext = context }); + _serviceProvider = services.BuildServiceProvider(); + _userManager = _serviceProvider.GetRequiredService(); + + Controller = new IdentityController(_userManager, _mapper.Object, _serviceProvider.GetService>(), _emailProvider.Object, + _emailSettings.Object, _customizationSettings.Object,_welcomeEmail.Object); + } + + private OmbiUserManager _userManager; + private Mock _emailProvider; + private Mock> _emailSettings; + private Mock> _customizationSettings; + private Mock> _embySettings; + private Mock> _plexSettings; + private Mock _welcomeEmail; + private Mock _mapper; + private Mock _plexApi; + private Mock _embyApi; + private ServiceProvider _serviceProvider; + + private IdentityController Controller { get; set; } + + [Test] + public async Task CreateWizardUser_Should_CreateUser_WhenThereAreNoOtherUsers() + { + var model = new UserAuthModel + { + Password = "a", + Username = "b" + }; + + var result = await Controller.CreateWizardUser(model); + + Assert.That(result, Is.True); + } + + [Test] + public async Task CreateWizardUser_ShouldNot_CreateUser_WhenThereAreOtherUsers() + { + var um = _serviceProvider.GetService(); + var r = await um.CreateAsync(new OmbiUser { UserName = "aaaa",UserType = UserType.LocalUser}, "bbb"); + var model = new UserAuthModel + { + Password = "a", + Username = "b" + }; + + var result = await Controller.CreateWizardUser(model); + + Assert.That(result, Is.False); + } + } +} diff --git a/src/Ombi.Tests/Ombi.Tests.csproj b/src/Ombi.Tests/Ombi.Tests.csproj new file mode 100644 index 000000000..d9fdb8e91 --- /dev/null +++ b/src/Ombi.Tests/Ombi.Tests.csproj @@ -0,0 +1,23 @@ + + + + netcoreapp2.0 + + false + + + + + + + + + + + + + + + + + diff --git a/src/Ombi.Tests/TestStartup.cs b/src/Ombi.Tests/TestStartup.cs new file mode 100644 index 000000000..fad346df0 --- /dev/null +++ b/src/Ombi.Tests/TestStartup.cs @@ -0,0 +1,71 @@ +using System; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using Ombi.Api.Emby; +using Ombi.Api.Plex; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Models.Identity; +using Ombi.Store.Context; +using Ombi.Store.Entities; +using Ombi.Store.Repository; + +namespace Ombi.Tests +{ + public class TestStartup + { + public IServiceProvider ConfigureServices(IServiceCollection services) + { + var _plexApi = new Mock(); + var _embyApi = new Mock(); + var _tokenSettings = new Mock>(); + var _embySettings = new Mock>(); + var _plexSettings = new Mock>(); + var audit = new Mock(); + var tokenRepo = new Mock(); + + services.AddEntityFrameworkInMemoryDatabase() + .AddDbContext(); + services.AddIdentity() + .AddEntityFrameworkStores().AddUserManager(); + + services.AddTransient(x => _plexApi.Object); + services.AddTransient(x => _embyApi.Object); + services.AddTransient(x => _tokenSettings.Object); + services.AddTransient(x => _embySettings.Object); + services.AddTransient(x => _plexSettings.Object); + services.AddTransient(x => audit.Object); + services.AddTransient(x => tokenRepo.Object); + // Taken from https://github.com/aspnet/MusicStore/blob/dev/test/MusicStore.Test/ManageControllerTest.cs (and modified) + var context = new DefaultHttpContext(); + context.Features.Set(new HttpAuthenticationFeature()); + services.AddSingleton(h => new HttpContextAccessor { HttpContext = context }); + + + services.Configure(options => + { + options.Password.RequireDigit = false; + options.Password.RequiredLength = 1; + options.Password.RequireLowercase = false; + options.Password.RequireNonAlphanumeric = false; + options.Password.RequireUppercase = false; + options.User.AllowedUserNameCharacters = string.Empty; + }); + + return services.BuildServiceProvider(); + + } + + public void Configure(IApplicationBuilder app, IHostingEnvironment env) + { + + } + } +} \ No newline at end of file diff --git a/src/Ombi.Tests/TokenControllerTests.cs b/src/Ombi.Tests/TokenControllerTests.cs new file mode 100644 index 000000000..ec0e616ac --- /dev/null +++ b/src/Ombi.Tests/TokenControllerTests.cs @@ -0,0 +1,60 @@ +using System.Net.Http; +using System.Threading.Tasks; +using AutoMapper; +using Microsoft.AspNetCore.Hosting; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Features.Authentication; +using Microsoft.AspNetCore.Identity; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Moq; +using NUnit.Framework; +using Ombi.Api.Emby; +using Ombi.Api.Plex; +using Ombi.Controllers; +using Ombi.Core.Authentication; +using Ombi.Core.Settings; +using Ombi.Core.Settings.Models.External; +using Ombi.Models.Identity; +using Ombi.Notifications; +using Ombi.Schedule.Jobs.Ombi; +using Ombi.Settings.Settings.Models; +using Ombi.Settings.Settings.Models.Notifications; +using Ombi.Store.Context; +using Ombi.Store.Entities; +using Ombi.Store.Repository; +using Microsoft.AspNetCore.Hosting.Server; +using Microsoft.AspNetCore.TestHost; +using Newtonsoft.Json; +using Ombi.Models; + +namespace Ombi.Tests +{ + [TestFixture] + [Ignore("TODO")] + public class TokenControllerTests + { + [SetUp] + public void Setup() + { + _testServer = new TestServer(new WebHostBuilder() + .UseStartup()); + _client = _testServer.CreateClient(); + } + + private TestServer _testServer; + private HttpClient _client; + + + [Test] + public async Task GetToken_FromValid_LocalUser() + { + var model = new UserAuthModel + { + Password = "a", + Username = "a" + }; + HttpResponseMessage response = await _client.PostAsync("/api/v1/token", new StringContent(JsonConvert.SerializeObject(model)) ); + } + } +} \ No newline at end of file diff --git a/src/Ombi.sln b/src/Ombi.sln index 984494cea..5f7af3ead 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -82,7 +82,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Schedule.Tests", "Ombi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.CouchPotato", "Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj", "{87D7897D-7C73-4856-A0AA-FF5948F4EA86}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.DogNzb", "Ombi.Api.DogNzb\Ombi.Api.DogNzb.csproj", "{4F3BF03A-6AAC-4960-A2CD-1EAD7273115E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.DogNzb", "Ombi.Api.DogNzb\Ombi.Api.DogNzb.csproj", "{4F3BF03A-6AAC-4960-A2CD-1EAD7273115E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Tests", "Ombi.Tests\Ombi.Tests.csproj", "{C12F5276-352A-43CF-8E33-400E768E9757}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -214,6 +216,10 @@ Global {4F3BF03A-6AAC-4960-A2CD-1EAD7273115E}.Debug|Any CPU.Build.0 = Debug|Any CPU {4F3BF03A-6AAC-4960-A2CD-1EAD7273115E}.Release|Any CPU.ActiveCfg = Release|Any CPU {4F3BF03A-6AAC-4960-A2CD-1EAD7273115E}.Release|Any CPU.Build.0 = Release|Any CPU + {C12F5276-352A-43CF-8E33-400E768E9757}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C12F5276-352A-43CF-8E33-400E768E9757}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C12F5276-352A-43CF-8E33-400E768E9757}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C12F5276-352A-43CF-8E33-400E768E9757}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -244,6 +250,7 @@ Global {BDD8B924-016E-4CDA-9FFA-50B0A34BCD3C} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {87D7897D-7C73-4856-A0AA-FF5948F4EA86} = {9293CA11-360A-4C20-A674-B9E794431BF5} {4F3BF03A-6AAC-4960-A2CD-1EAD7273115E} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {C12F5276-352A-43CF-8E33-400E768E9757} = {6F42AB98-9196-44C4-B888-D5E409F415A1} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869} diff --git a/src/Ombi/Controllers/IdentityController.cs b/src/Ombi/Controllers/IdentityController.cs index 3e966fbcf..88fa6f06f 100644 --- a/src/Ombi/Controllers/IdentityController.cs +++ b/src/Ombi/Controllers/IdentityController.cs @@ -41,7 +41,6 @@ namespace Ombi.Controllers public IdentityController(OmbiUserManager user, IMapper mapper, RoleManager rm, IEmailProvider prov, ISettingsService s, ISettingsService c, - IOptions userSettings, IWelcomeEmail welcome) { UserManager = user; @@ -50,7 +49,6 @@ namespace Ombi.Controllers EmailProvider = prov; EmailSettings = s; CustomizationSettings = c; - UserSettings = userSettings; WelcomeEmail = welcome; } @@ -60,7 +58,6 @@ namespace Ombi.Controllers private IEmailProvider EmailProvider { get; } private ISettingsService EmailSettings { get; } private ISettingsService CustomizationSettings { get; } - private IOptions UserSettings { get; } private IWelcomeEmail WelcomeEmail { get; } /// @@ -97,7 +94,7 @@ namespace Ombi.Controllers await UserManager.AddToRoleAsync(userToCreate, OmbiRoles.Admin); } - return true; + return result.Succeeded; } private async Task CreateRoles() diff --git a/src/Ombi/Controllers/TokenController.cs b/src/Ombi/Controllers/TokenController.cs index 3e5ff9f07..d408e1081 100644 --- a/src/Ombi/Controllers/TokenController.cs +++ b/src/Ombi/Controllers/TokenController.cs @@ -22,18 +22,15 @@ namespace Ombi.Controllers [Produces("application/json")] public class TokenController { - public TokenController(OmbiUserManager um, IOptions ta, - IApplicationConfigRepository config, IAuditRepository audit, ITokenRepository token) + public TokenController(OmbiUserManager um, IOptions ta, IAuditRepository audit, ITokenRepository token) { _userManager = um; _tokenAuthenticationOptions = ta.Value; - _config = config; _audit = audit; _token = token; } private readonly TokenAuthentication _tokenAuthenticationOptions; - private IApplicationConfigRepository _config; private readonly IAuditRepository _audit; private readonly ITokenRepository _token; private readonly OmbiUserManager _userManager;