feat: Applied the feature service on the backend

This commit is contained in:
tidusjar 2022-02-14 20:58:44 +00:00
parent 669ac65d66
commit da2c306a31
9 changed files with 126 additions and 36 deletions

View file

@ -9,6 +9,7 @@ using Ombi.Api.TheMovieDb;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Core.Services;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models;
@ -43,8 +44,9 @@ namespace Ombi.Core.Tests.Engine.V2
var ombiSettings = new Mock<ISettingsService<OmbiSettings>>(); var ombiSettings = new Mock<ISettingsService<OmbiSettings>>();
var requestSubs = new Mock<IRepository<RequestSubscription>>(); var requestSubs = new Mock<IRepository<RequestSubscription>>();
var mediaCache = new Mock<IMediaCacheService>(); var mediaCache = new Mock<IMediaCacheService>();
var featureService = new Mock<IFeatureService>();
_engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object, _engine = new MovieRequestEngine(movieApi.Object, requestService.Object, user.Object, notificationHelper.Object, rules.Object, movieSender.Object,
logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object); logger.Object, userManager.Object, requestLogRepo.Object, cache.Object, ombiSettings.Object, requestSubs.Object, mediaCache.Object, featureService.Object);
} }
[Test] [Test]

View file

@ -10,6 +10,7 @@ using Ombi.Test.Common;
using System.Collections.Generic; using System.Collections.Generic;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System; using System;
using Ombi.Core.Services;
namespace Ombi.Core.Tests.Rule.Request namespace Ombi.Core.Tests.Rule.Request
{ {
@ -28,15 +29,17 @@ namespace Ombi.Core.Tests.Rule.Request
PrincipalMock = new Mock<IPrincipal>(); PrincipalMock = new Mock<IPrincipal>();
PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); PrincipalMock.Setup(x => x.Identity.Name).Returns("abc");
FeatureService = new Mock<IFeatureService>();
UserManager = MockHelper.MockUserManager(_users); UserManager = MockHelper.MockUserManager(_users);
Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object); Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object, FeatureService.Object);
} }
private AutoApproveRule Rule { get; set; } private AutoApproveRule Rule { get; set; }
private Mock<IPrincipal> PrincipalMock { get; set; } private Mock<IPrincipal> PrincipalMock { get; set; }
private Mock<OmbiUserManager> UserManager { get; set; } private Mock<OmbiUserManager> UserManager { get; set; }
private Mock<IFeatureService> FeatureService { get; set; }
[Test] [Test]
public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie() public async Task Should_ReturnSuccess_WhenAdminAndRequestMovie()
@ -137,5 +140,17 @@ namespace Ombi.Core.Tests.Rule.Request
Assert.True(result.Success); Assert.True(result.Success);
Assert.False(request.Approved); Assert.False(request.Approved);
} }
[Test]
public async Task Should_ReturnFail_When4kRequestAndFeatureNotEnabled()
{
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), It.IsAny<string>())).ReturnsAsync(false);
var request = new MovieRequests() { RequestType = Store.Entities.RequestType.Movie, Is4kRequest = true };
var result = await Rule.Execute(request);
Assert.True(result.Success);
Assert.False(request.Approved);
Assert.False(request.Approved4K);
}
} }
} }

View file

@ -9,7 +9,9 @@ using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules;
using Ombi.Core.Rule.Rules.Request; using Ombi.Core.Rule.Rules.Request;
using Ombi.Core.Services;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
@ -24,12 +26,14 @@ namespace Ombi.Core.Tests.Rule.Request
public void Setup() public void Setup()
{ {
ContextMock = new Mock<IMovieRequestRepository>(); ContextMock = new Mock<IMovieRequestRepository>();
Rule = new ExistingMovieRequestRule(ContextMock.Object); FeatureService = new Mock<IFeatureService>();
Rule = new ExistingMovieRequestRule(ContextMock.Object, FeatureService.Object);
} }
private ExistingMovieRequestRule Rule { get; set; } private ExistingMovieRequestRule Rule { get; set; }
private Mock<IMovieRequestRepository> ContextMock { get; set; } private Mock<IMovieRequestRepository> ContextMock { get; set; }
private Mock<IFeatureService> FeatureService { get; set; }
[Test] [Test]
public async Task ExistingRequestRule_Movie_Has_Been_Requested_With_TheMovieDBId() public async Task ExistingRequestRule_Movie_Has_Been_Requested_With_TheMovieDBId()
@ -125,6 +129,7 @@ namespace Ombi.Core.Tests.Rule.Request
[Test] [Test]
public async Task ExistingRequestRule_Movie_4K_Request() public async Task ExistingRequestRule_Movie_4K_Request()
{ {
FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(true);
ContextMock.Setup(x => x.GetAll()).Returns(new List<MovieRequests> ContextMock.Setup(x => x.GetAll()).Returns(new List<MovieRequests>
{ {
new MovieRequests new MovieRequests
@ -146,5 +151,31 @@ namespace Ombi.Core.Tests.Rule.Request
Assert.That(result.Success, Is.True); Assert.That(result.Success, Is.True);
Assert.That(result.Message, Is.Null.Or.Empty); Assert.That(result.Message, Is.Null.Or.Empty);
} }
[Test]
public async Task ExistingRequestRule_Movie_4K_Request_FeatureNotEnabled()
{
FeatureService.Setup(x => x.FeatureEnabled(FeatureNames.Movie4KRequests)).ReturnsAsync(false);
ContextMock.Setup(x => x.GetAll()).Returns(new List<MovieRequests>
{
new MovieRequests
{
TheMovieDbId = 2,
ImdbId = "2",
RequestType = RequestType.Movie,
Is4kRequest = false
}
}.AsQueryable().BuildMock().Object);
var o = new MovieRequests
{
TheMovieDbId = 2,
ImdbId = "1",
Is4kRequest = true
};
var result = await Rule.Execute(o);
Assert.That(result.Success, Is.False);
Assert.That(result.Message, Is.Not.Null);
}
} }
} }

View file

@ -30,7 +30,7 @@ namespace Ombi.Core.Tests.Rule.Search
[Test] [Test]
public async Task ShouldBe_Requested_WhenExisitngMovie() public async Task ShouldBe_Requested_WhenExistingMovie()
{ {
var list = new MovieRequests var list = new MovieRequests
{ {

View file

@ -22,6 +22,7 @@ using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Core.Models; using Ombi.Core.Models;
using System.Threading; using System.Threading;
using Ombi.Core.Services;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -30,7 +31,8 @@ namespace Ombi.Core.Engine
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user,
INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log, INotificationHelper helper, IRuleEvaluator r, IMovieSender sender, ILogger<MovieRequestEngine> log,
OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache, OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache,
ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService) ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService,
IFeatureService featureService)
: base(user, requestService, r, manager, cache, ombiSettings, sub) : base(user, requestService, r, manager, cache, ombiSettings, sub)
{ {
MovieApi = movieApi; MovieApi = movieApi;
@ -39,6 +41,7 @@ namespace Ombi.Core.Engine
Logger = log; Logger = log;
_requestLog = rl; _requestLog = rl;
_mediaCacheService = mediaCacheService; _mediaCacheService = mediaCacheService;
_featureService = featureService;
} }
private IMovieDbApi MovieApi { get; } private IMovieDbApi MovieApi { get; }
@ -47,6 +50,7 @@ namespace Ombi.Core.Engine
private ILogger<MovieRequestEngine> Logger { get; } private ILogger<MovieRequestEngine> Logger { get; }
private readonly IRepository<RequestLog> _requestLog; private readonly IRepository<RequestLog> _requestLog;
private readonly IMediaCacheService _mediaCacheService; private readonly IMediaCacheService _mediaCacheService;
private readonly IFeatureService _featureService;
/// <summary> /// <summary>
/// Requests the movie. /// Requests the movie.
@ -94,11 +98,14 @@ namespace Ombi.Core.Engine
}; };
} }
var is4kFeatureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
var is4kRequest = is4kFeatureEnabled && model.Is4kRequest;
MovieRequests requestModel; MovieRequests requestModel;
bool isExisting = false; bool isExisting = false;
// Do we already have a request? 4k or non 4k // Do we already have a request? 4k or non 4k
var existingRequest = await MovieRepository.GetRequestAsync(movieInfo.Id); var existingRequest = await MovieRepository.GetRequestAsync(movieInfo.Id);
if (existingRequest != null) if (existingRequest != null && is4kFeatureEnabled)
{ {
if (model.Is4kRequest) if (model.Is4kRequest)
{ {
@ -156,7 +163,7 @@ namespace Ombi.Core.Engine
if (requestModel.Approved) // The rules have auto approved this if (requestModel.Approved) // The rules have auto approved this
{ {
var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, model.Is4kRequest); var requestEngineResult = await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest);
if (requestEngineResult.Result) if (requestEngineResult.Result)
{ {
var result = await ApproveMovie(requestModel, model.Is4kRequest); var result = await ApproveMovie(requestModel, model.Is4kRequest);
@ -177,7 +184,7 @@ namespace Ombi.Core.Engine
// If there are no providers then it's successful but movie has not been sent // If there are no providers then it's successful but movie has not been sent
} }
return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, model.Is4kRequest); return await AddMovieRequest(requestModel, fullMovieName, model.RequestOnBehalf, isExisting, is4kRequest);
} }

View file

@ -5,7 +5,9 @@ using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Core.Services;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
@ -13,14 +15,16 @@ namespace Ombi.Core.Rule.Rules.Request
{ {
public class AutoApproveRule : BaseRequestRule, IRules<BaseRequest> public class AutoApproveRule : BaseRequestRule, IRules<BaseRequest>
{ {
public AutoApproveRule(IPrincipal principal, OmbiUserManager um) public AutoApproveRule(IPrincipal principal, OmbiUserManager um, IFeatureService featureService)
{ {
User = principal; User = principal;
_manager = um; _manager = um;
_featureService = featureService;
} }
private IPrincipal User { get; } private IPrincipal User { get; }
private readonly OmbiUserManager _manager; private readonly OmbiUserManager _manager;
private readonly IFeatureService _featureService;
public async Task<RuleResult> Execute(BaseRequest obj) public async Task<RuleResult> Execute(BaseRequest obj)
{ {
@ -28,17 +32,9 @@ namespace Ombi.Core.Rule.Rules.Request
var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); var user = await _manager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser) if (await _manager.IsInRoleAsync(user, OmbiRoles.Admin) || user.IsSystemUser)
{ {
if (obj.RequestType == RequestType.Movie) if (obj is MovieRequests movie)
{ {
var movie = (MovieRequests)obj; await Check4K(movie);
if (movie.Is4kRequest)
{
movie.Approved4K = true;
}
else
{
obj.Approved = true;
}
} }
else else
{ {
@ -50,14 +46,7 @@ namespace Ombi.Core.Rule.Rules.Request
if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie)) if (obj.RequestType == RequestType.Movie && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveMovie))
{ {
var movie = (MovieRequests)obj; var movie = (MovieRequests)obj;
if (movie.Is4kRequest) await Check4K(movie);
{
movie.Approved4K = true;
}
else
{
obj.Approved = true;
}
} }
if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv)) if (obj.RequestType == RequestType.TvShow && await _manager.IsInRoleAsync(user, OmbiRoles.AutoApproveTv))
obj.Approved = true; obj.Approved = true;
@ -65,5 +54,18 @@ namespace Ombi.Core.Rule.Rules.Request
obj.Approved = true; obj.Approved = true;
return Success(); // We don't really care, we just don't set the obj to approve return Success(); // We don't really care, we just don't set the obj to approve
} }
private async Task Check4K(MovieRequests movie)
{
var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
if (movie.Is4kRequest && featureEnabled)
{
movie.Approved4K = true;
}
else
{
movie.Approved = true;
}
}
} }
} }

View file

@ -1,21 +1,24 @@
using System; using System.Threading.Tasks;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
using Ombi.Core.Services;
using Ombi.Settings.Settings.Models;
namespace Ombi.Core.Rule.Rules.Request namespace Ombi.Core.Rule.Rules.Request
{ {
public class ExistingMovieRequestRule : BaseRequestRule, IRules<BaseRequest> public class ExistingMovieRequestRule : BaseRequestRule, IRules<BaseRequest>
{ {
public ExistingMovieRequestRule(IMovieRequestRepository movie) private readonly IFeatureService _featureService;
public ExistingMovieRequestRule(IMovieRequestRepository movie, IFeatureService featureService)
{ {
Movie = movie; Movie = movie;
_featureService = featureService;
} }
private IMovieRequestRepository Movie { get; } private IMovieRequestRepository Movie { get; }
@ -35,7 +38,7 @@ namespace Ombi.Core.Rule.Rules.Request
var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == movie.TheMovieDbId); var existing = await movieRequests.FirstOrDefaultAsync(x => x.TheMovieDbId == movie.TheMovieDbId);
if (existing != null) // Do we already have a request for this? if (existing != null) // Do we already have a request for this?
{ {
found = Check4KRequests(movie, existing); found = await Check4KRequests(movie, existing);
} }
if (!found && movie.ImdbId.HasValue()) if (!found && movie.ImdbId.HasValue())
@ -45,7 +48,7 @@ namespace Ombi.Core.Rule.Rules.Request
x.ImdbId == movie.ImdbId); x.ImdbId == movie.ImdbId);
if (existing != null) if (existing != null)
{ {
found = Check4KRequests(movie, existing); found = await Check4KRequests(movie, existing);
} }
} }
if (found) if (found)
@ -56,13 +59,14 @@ namespace Ombi.Core.Rule.Rules.Request
return Success(); return Success();
} }
private static bool Check4KRequests(MovieRequests movie,MovieRequests existing) private async Task<bool> Check4KRequests(MovieRequests movie, MovieRequests existing)
{ {
if (movie.Is4kRequest && existing.Has4KRequest) var featureEnabled = await _featureService.FeatureEnabled(FeatureNames.Movie4KRequests);
if (movie.Is4kRequest && existing.Has4KRequest && featureEnabled)
{ {
return true; return true;
} }
if (!movie.Is4kRequest && !existing.Has4KRequest) if (!movie.Is4kRequest && !existing.Has4KRequest || !featureEnabled)
{ {
return true; return true;
} }

View file

@ -0,0 +1,28 @@
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models;
using System.Linq;
using System.Threading.Tasks;
namespace Ombi.Core.Services
{
public interface IFeatureService
{
Task<bool> FeatureEnabled(string featureName);
}
public class FeatureService : IFeatureService
{
private readonly ISettingsService<FeatureSettings> _featureSettings;
public FeatureService(ISettingsService<FeatureSettings> featureSettings)
{
_featureSettings = featureSettings;
}
public async Task<bool> FeatureEnabled(string featureName)
{
var settings = await _featureSettings.GetSettingsAsync();
return settings.Features?.Where(x => x.Name.Equals(featureName, System.StringComparison.InvariantCultureIgnoreCase)).Select(x => x.Enabled)?.FirstOrDefault() ?? false;
}
}
}

View file

@ -224,6 +224,7 @@ namespace Ombi.DependencyInjection
services.AddTransient<ITelegramNotification, TelegramNotification>(); services.AddTransient<ITelegramNotification, TelegramNotification>();
services.AddTransient<ILegacyMobileNotification, LegacyMobileNotification>(); services.AddTransient<ILegacyMobileNotification, LegacyMobileNotification>();
services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>(); services.AddTransient<IChangeLogProcessor, ChangeLogProcessor>();
services.AddScoped<IFeatureService, FeatureService>();
} }
public static void RegisterJobs(this IServiceCollection services) public static void RegisterJobs(this IServiceCollection services)