diff --git a/appveyor.yml b/appveyor.yml index 93cac22c2..0f341baed 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -14,6 +14,7 @@ before_build: - gulp publish build_script: - dotnet build +- dotnet xunit after_build: - dotnet publish -c Release -r win10-x64 - dotnet publish -c Release -r osx.10.12-x64 diff --git a/src/Ombi.Tests.Core/Ombi.Tests.Core.csproj b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj similarity index 75% rename from src/Ombi.Tests.Core/Ombi.Tests.Core.csproj rename to src/Ombi.Core.Tests/Ombi.Core.Tests.csproj index 245cb749e..204b0d1b0 100644 --- a/src/Ombi.Tests.Core/Ombi.Tests.Core.csproj +++ b/src/Ombi.Core.Tests/Ombi.Core.Tests.csproj @@ -5,16 +5,14 @@ - - + - diff --git a/src/Ombi.Core.Tests/Rule/AutoApproveRuleTests.cs b/src/Ombi.Core.Tests/Rule/AutoApproveRuleTests.cs new file mode 100644 index 000000000..7f7202e3e --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/AutoApproveRuleTests.cs @@ -0,0 +1,87 @@ +using Ombi.Core.Rule.Rules; +using Xunit; +using System.Security.Principal; +using Moq; +using Ombi.Core.Models.Requests; +using Ombi.Core.Claims; + +namespace Ombi.Core.Tests +{ + public class AutoApproveRuleTests + { + public AutoApproveRuleTests() + { + PrincipalMock = new Mock(); + Rule = new AutoApproveRule(PrincipalMock.Object); + } + + private AutoApproveRule Rule { get; } + private Mock PrincipalMock { get; } + + [Fact] + public void Should_ReturnSuccess_WhenAdminAndRequestMovie() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, true); + } + + [Fact] + public void Should_ReturnSuccess_WhenAdminAndRequestTV() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, true); + } + + [Fact] + public void Should_ReturnSuccess_WhenAutoApproveMovieAndRequestMovie() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveMovie)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, true); + } + + [Fact] + public void Should_ReturnSuccess_WhenAutoApproveTVAndRequestTV() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.AutoApproveTv)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, true); + } + + [Fact] + public void Should_ReturnFail_WhenNoClaimsAndRequestMovie() + { + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, false); + } + + [Fact] + public void Should_ReturnFail_WhenNoClaimsAndRequestTV() + { + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + Assert.Equal(request.Approved, false); + } + + + } +} diff --git a/src/Ombi.Core.Tests/Rule/CanRequestRuleTests.cs b/src/Ombi.Core.Tests/Rule/CanRequestRuleTests.cs new file mode 100644 index 000000000..e7e8d11e3 --- /dev/null +++ b/src/Ombi.Core.Tests/Rule/CanRequestRuleTests.cs @@ -0,0 +1,83 @@ +using Ombi.Core.Rule.Rules; +using Xunit; +using System.Security.Principal; +using Moq; +using Ombi.Core.Models.Requests; +using Ombi.Core.Claims; + +namespace Ombi.Core.Tests +{ + public class CanRequestRuleTests + { + public CanRequestRuleTests() + { + PrincipalMock = new Mock(); + Rule = new CanRequestRule(PrincipalMock.Object); + } + + private CanRequestRule Rule { get; } + private Mock PrincipalMock { get; } + + [Fact] + public void Should_ReturnSuccess_WhenRequestingMovieWithMovieRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + } + + [Fact] + public void Should_ReturnFail_WhenRequestingMovieWithoutMovieRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestMovie)).Returns(false); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, false); + Assert.Equal(string.IsNullOrEmpty(result.Message), false); + } + + [Fact] + public void Should_ReturnSuccess_WhenRequestingMovieWithAdminRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.Movie }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + } + + [Fact] + public void Should_ReturnSuccess_WhenRequestingTVWithAdminRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.Admin)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + } + + [Fact] + public void Should_ReturnSuccess_WhenRequestingTVWithTVRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(true); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, true); + } + + [Fact] + public void Should_ReturnFail_WhenRequestingTVWithoutTVRole() + { + PrincipalMock.Setup(x => x.IsInRole(OmbiClaims.RequestTv)).Returns(false); + var request = new BaseRequestModel() { Type = Store.Entities.RequestType.TvShow }; + var result = Rule.Execute(request); + + Assert.Equal(result.Success, false); + Assert.Equal(string.IsNullOrEmpty(result.Message), false); + } + } +} diff --git a/src/Ombi.Core/Rule/RuleEvaluator.cs b/src/Ombi.Core/Rule/RuleEvaluator.cs index 4bc9ab955..010cea33c 100644 --- a/src/Ombi.Core/Rule/RuleEvaluator.cs +++ b/src/Ombi.Core/Rule/RuleEvaluator.cs @@ -2,6 +2,7 @@ using Ombi.Core.Rule; using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; namespace Ombi.Core.Rules @@ -19,8 +20,17 @@ namespace Ombi.Core.Rules { if (ti?.BaseType?.FullName == baseType) { - var type = ti.GetType(); - var item = Activator.CreateInstance(ti.GetType(), provider.GetService(type));// ti.GetType is wrong + var type = ti.AsType(); + var ctors = type.GetConstructors(); + var ctor = ctors.FirstOrDefault(); + + var services = new List(); + foreach (var param in ctor.GetParameters()) + { + services.Add(provider.GetService(param.ParameterType)); + } + + var item = Activator.CreateInstance(type, services.ToArray());// ti.GetType is wrong RequestRules.Add((IRequestRules)item); } } diff --git a/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs b/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs new file mode 100644 index 000000000..e2463a8dc --- /dev/null +++ b/src/Ombi.Core/Rule/Rules/AutoApproveRule.cs @@ -0,0 +1,38 @@ +using Ombi.Core.Claims; +using Ombi.Core.Models.Requests; +using Ombi.Core.Rules; +using System; +using System.Collections.Generic; +using System.Security.Principal; +using System.Text; + +namespace Ombi.Core.Rule.Rules +{ + public class AutoApproveRule : BaseRule, IRequestRules + { + public AutoApproveRule(IPrincipal principal) + { + User = principal; + } + + private IPrincipal User { get; } + public RuleResult Execute(BaseRequestModel obj) + { + if(User.IsInRole(OmbiClaims.Admin)) + { + obj.Approved = true; + return Success(); + } + + if (obj.Type == Store.Entities.RequestType.Movie && User.IsInRole(OmbiClaims.AutoApproveMovie)) + { + obj.Approved = true; + } + if (obj.Type == Store.Entities.RequestType.TvShow && User.IsInRole(OmbiClaims.AutoApproveTv)) + { + obj.Approved = true; + } + return Success(); // We don't really care, we just don't set the obj to approve + } + } +} diff --git a/src/Ombi.Core/Rule/Rules/CanRequestRule.cs b/src/Ombi.Core/Rule/Rules/CanRequestRule.cs index e99908c07..f56a0f868 100644 --- a/src/Ombi.Core/Rule/Rules/CanRequestRule.cs +++ b/src/Ombi.Core/Rule/Rules/CanRequestRule.cs @@ -5,7 +5,7 @@ using System.Security.Principal; namespace Ombi.Core.Rule.Rules { - public class CanRequestRule : BaseRule where T : BaseRequestModel, IRequestRules + public class CanRequestRule : BaseRule, IRequestRules { public CanRequestRule(IPrincipal principal) { @@ -13,8 +13,13 @@ namespace Ombi.Core.Rule.Rules } private IPrincipal User { get; } - public RuleResult Execute(T obj) + public RuleResult Execute(BaseRequestModel obj) { + if(User.IsInRole(OmbiClaims.Admin)) + { + return Success(); + } + if (obj.Type == Store.Entities.RequestType.Movie) { if (User.IsInRole(OmbiClaims.RequestMovie)) diff --git a/src/Ombi.DependencyInjection/IocExtensions.cs b/src/Ombi.DependencyInjection/IocExtensions.cs index e7245b743..08128e8a6 100644 --- a/src/Ombi.DependencyInjection/IocExtensions.cs +++ b/src/Ombi.DependencyInjection/IocExtensions.cs @@ -44,7 +44,7 @@ namespace Ombi.DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddSingleton(); } public static void RegisterApi(this IServiceCollection services) diff --git a/src/Ombi.Notifications.Email/Ombi.Notifications.Email.csproj b/src/Ombi.Notifications.Email/Ombi.Notifications.Email.csproj index 90d57b9cb..6732c9c78 100644 --- a/src/Ombi.Notifications.Email/Ombi.Notifications.Email.csproj +++ b/src/Ombi.Notifications.Email/Ombi.Notifications.Email.csproj @@ -5,7 +5,7 @@ - + diff --git a/src/Ombi.Tests.Core/UserIdentityManagerTests.cs b/src/Ombi.Tests.Core/UserIdentityManagerTests.cs deleted file mode 100644 index a9edae9b5..000000000 --- a/src/Ombi.Tests.Core/UserIdentityManagerTests.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; -using System.Threading.Tasks; -using AutoMapper; -using Moq; -using Ombi.Core.IdentityResolver; -using Ombi.Core.Models; -using Ombi.Store.Entities; -using Ombi.Store.Repository; -using Xunit; - -namespace Ombi.Tests.Core -{ - public class UserIdentityManagerTests - { - public UserIdentityManagerTests() - { - UserRepo = new Mock(); - var mapper = new Mock(); - Manager = new UserIdentityManager(UserRepo.Object, mapper.Object); - } - private Mock UserRepo { get; } - private IUserIdentityManager Manager { get; } - - [Fact] - public async Task CredentialsValid() - { - UserRepo.Setup(x => x.GetUser("ABC")).ReturnsAsync(() => new User{Password = "4tDKIbNCZ0pMxNzSSjVbT6mG88o52x9jOixPEwQS9rg=", Salt = new byte[]{30,80,214,127,185,134,75,86,80,177,0,242,202,161,219,246}}); - - Assert.True(await Manager.CredentialsValid("ABC", "ABC")); - } - } -} diff --git a/src/Ombi.sln b/src/Ombi.sln index e7dceb9e4..5602d63f3 100644 --- a/src/Ombi.sln +++ b/src/Ombi.sln @@ -53,12 +53,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Notifications.Email", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Notifications.Templates", "Ombi.Notifications.Templates\Ombi.Notifications.Templates.csproj", "{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Tests.Core", "Ombi.Tests.Core\Ombi.Tests.Core.csproj", "{627A27A7-8879-4851-8140-38F8F5ADD6CD}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Settings", "Ombi.Settings\Ombi.Settings.csproj", "{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Trakt", "Ombi.Api.Trakt\Ombi.Api.Trakt.csproj", "{3880375C-1A7E-4D75-96EC-63B954C42FEA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Core.Tests", "Ombi.Core.Tests\Ombi.Core.Tests.csproj", "{FC6A8F7C-9722-4AE4-960D-277ACB0E81CB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -129,10 +129,6 @@ Global {6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Debug|Any CPU.Build.0 = Debug|Any CPU {6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Release|Any CPU.ActiveCfg = Release|Any CPU {6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Release|Any CPU.Build.0 = Release|Any CPU - {627A27A7-8879-4851-8140-38F8F5ADD6CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {627A27A7-8879-4851-8140-38F8F5ADD6CD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {627A27A7-8879-4851-8140-38F8F5ADD6CD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {627A27A7-8879-4851-8140-38F8F5ADD6CD}.Release|Any CPU.Build.0 = Release|Any CPU {AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -141,6 +137,10 @@ Global {3880375C-1A7E-4D75-96EC-63B954C42FEA}.Debug|Any CPU.Build.0 = Debug|Any CPU {3880375C-1A7E-4D75-96EC-63B954C42FEA}.Release|Any CPU.ActiveCfg = Release|Any CPU {3880375C-1A7E-4D75-96EC-63B954C42FEA}.Release|Any CPU.Build.0 = Release|Any CPU + {FC6A8F7C-9722-4AE4-960D-277ACB0E81CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC6A8F7C-9722-4AE4-960D-277ACB0E81CB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC6A8F7C-9722-4AE4-960D-277ACB0E81CB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC6A8F7C-9722-4AE4-960D-277ACB0E81CB}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -157,7 +157,7 @@ Global {E6EE2830-E4AC-4F2E-AD93-2C9305605761} = {EA30DD15-6280-4687-B370-2956EC2E54E5} {72DB97D7-2D60-4B96-8C57-6C0E20E892EB} = {EA30DD15-6280-4687-B370-2956EC2E54E5} {6EE01B17-0966-4E11-8BC1-A5318A92AB1D} = {EA30DD15-6280-4687-B370-2956EC2E54E5} - {627A27A7-8879-4851-8140-38F8F5ADD6CD} = {6F42AB98-9196-44C4-B888-D5E409F415A1} {3880375C-1A7E-4D75-96EC-63B954C42FEA} = {9293CA11-360A-4C20-A674-B9E794431BF5} + {FC6A8F7C-9722-4AE4-960D-277ACB0E81CB} = {6F42AB98-9196-44C4-B888-D5E409F415A1} EndGlobalSection EndGlobal