Added the watchlist import for movies

This commit is contained in:
tidusjar 2022-04-07 11:20:33 +01:00
parent df59b46a78
commit f41eea89a0
55 changed files with 1824 additions and 136 deletions

View file

@ -10,6 +10,7 @@ using Ombi.Core.Authentication;
using Ombi.Core.Engine.V2; using Ombi.Core.Engine.V2;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository.Requests; using Ombi.Store.Repository.Requests;
using Ombi.Core.Helpers;
namespace Ombi.Core.Tests.Engine namespace Ombi.Core.Tests.Engine
{ {
@ -25,7 +26,7 @@ namespace Ombi.Core.Tests.Engine
{ {
MovieRepo = new Mock<IMovieRequestRepository>(); MovieRepo = new Mock<IMovieRequestRepository>();
TvRepo = new Mock<ITvRequestRepository>(); TvRepo = new Mock<ITvRequestRepository>();
var principle = new Mock<IPrincipal>(); var principle = new Mock<ICurrentUser>();
var identity = new Mock<IIdentity>(); var identity = new Mock<IIdentity>();
identity.Setup(x => x.Name).Returns("UnitTest"); identity.Setup(x => x.Name).Returns("UnitTest");
principle.Setup(x => x.Identity).Returns(identity.Object); principle.Setup(x => x.Identity).Returns(identity.Object);

View file

@ -4,6 +4,7 @@ using Moq.AutoMock;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
@ -35,12 +36,17 @@ namespace Ombi.Core.Tests.Engine
var identity = new Mock<IIdentity>(); var identity = new Mock<IIdentity>();
identity.Setup(x => x.Name).Returns("Test"); identity.Setup(x => x.Name).Returns("Test");
principle.Setup(x => x.Identity).Returns(identity.Object); principle.Setup(x => x.Identity).Returns(identity.Object);
var currentUser = new Mock<ICurrentUser>();
currentUser.Setup(x => x.Identity).Returns(identity.Object);
currentUser.Setup(x => x.Username).Returns("Test");
currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { NormalizedUserName = "TEST", Id = "a" });
_repoMock = new Mock<IMovieRequestRepository>(); _repoMock = new Mock<IMovieRequestRepository>();
var requestServiceMock = new Mock<IRequestServiceMain>(); var requestServiceMock = new Mock<IRequestServiceMain>();
requestServiceMock.Setup(x => x.MovieRequestService).Returns(_repoMock.Object); requestServiceMock.Setup(x => x.MovieRequestService).Returns(_repoMock.Object);
_mocker.Use(principle.Object); _mocker.Use(principle.Object);
_mocker.Use(currentUser.Object);
_mocker.Use(userManager.Object); _mocker.Use(userManager.Object);
_mocker.Use(requestServiceMock); _mocker.Use(requestServiceMock);

View file

@ -4,6 +4,7 @@ using Moq.AutoMock;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Helpers; using Ombi.Helpers;
@ -36,6 +37,13 @@ namespace Ombi.Core.Tests.Engine
var identityMock = new Mock<IIdentity>(); var identityMock = new Mock<IIdentity>();
identityMock.SetupGet(x => x.Name).Returns("Test"); identityMock.SetupGet(x => x.Name).Returns("Test");
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
var currentUser = new Mock<ICurrentUser>();
currentUser.Setup(x => x.Identity).Returns(identityMock.Object);
currentUser.Setup(x => x.Username).Returns("Test");
currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" });
_mocker.Use(currentUser.Object);
_mocker.Use(principleMock.Object); _mocker.Use(principleMock.Object);
_subject = _mocker.CreateInstance<RequestLimitService>(); _subject = _mocker.CreateInstance<RequestLimitService>();

View file

@ -4,6 +4,7 @@ using Moq.AutoMock;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Helpers; using Ombi.Helpers;
@ -36,7 +37,12 @@ namespace Ombi.Core.Tests.Engine
var identityMock = new Mock<IIdentity>(); var identityMock = new Mock<IIdentity>();
identityMock.SetupGet(x => x.Name).Returns("Test"); identityMock.SetupGet(x => x.Name).Returns("Test");
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
var currentUser = new Mock<ICurrentUser>();
currentUser.Setup(x => x.Identity).Returns(identityMock.Object);
currentUser.Setup(x => x.Username).Returns("Test");
currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" });
_mocker.Use(principleMock.Object); _mocker.Use(principleMock.Object);
_mocker.Use(currentUser.Object);
_subject = _mocker.CreateInstance<RequestLimitService>(); _subject = _mocker.CreateInstance<RequestLimitService>();
} }

View file

@ -4,6 +4,7 @@ using Moq.AutoMock;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Helpers; using Ombi.Helpers;
@ -33,7 +34,12 @@ namespace Ombi.Core.Tests.Engine
var identityMock = new Mock<IIdentity>(); var identityMock = new Mock<IIdentity>();
identityMock.SetupGet(x => x.Name).Returns("Test"); identityMock.SetupGet(x => x.Name).Returns("Test");
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object); principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
var currentUser = new Mock<ICurrentUser>();
currentUser.Setup(x => x.Identity).Returns(identityMock.Object);
currentUser.Setup(x => x.Username).Returns("Test");
currentUser.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "Test", NormalizedUserName = "TEST", Id = "a" });
_mocker.Use(principleMock.Object); _mocker.Use(principleMock.Object);
_mocker.Use(currentUser.Object);
_subject = _mocker.CreateInstance<RequestLimitService>(); _subject = _mocker.CreateInstance<RequestLimitService>();
} }

View file

@ -7,6 +7,7 @@ using Moq;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Helpers;
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.Services;
@ -33,7 +34,7 @@ namespace Ombi.Core.Tests.Engine.V2
var requestService = new Mock<IRequestServiceMain>(); var requestService = new Mock<IRequestServiceMain>();
_movieRequestRepository = new Mock<IMovieRequestRepository>(); _movieRequestRepository = new Mock<IMovieRequestRepository>();
requestService.Setup(x => x.MovieRequestService).Returns(_movieRequestRepository.Object); requestService.Setup(x => x.MovieRequestService).Returns(_movieRequestRepository.Object);
var user = new Mock<IPrincipal>(); var user = new Mock<ICurrentUser>();
var notificationHelper = new Mock<INotificationHelper>(); var notificationHelper = new Mock<INotificationHelper>();
var rules = new Mock<IRuleEvaluator>(); var rules = new Mock<IRuleEvaluator>();
var movieSender = new Mock<IMovieSender>(); var movieSender = new Mock<IMovieSender>();

View file

@ -23,6 +23,7 @@ using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Test.Common; using Ombi.Test.Common;
using Artist = Hqub.MusicBrainz.API.Entities.Artist; using Artist = Hqub.MusicBrainz.API.Entities.Artist;
using Ombi.Core.Helpers;
namespace Ombi.Core.Tests.Engine.V2 namespace Ombi.Core.Tests.Engine.V2
{ {
@ -45,7 +46,7 @@ namespace Ombi.Core.Tests.Engine.V2
.ForEach(b => F.Behaviors.Remove(b)); .ForEach(b => F.Behaviors.Remove(b));
F.Behaviors.Add(new OmitOnRecursionBehavior()); F.Behaviors.Add(new OmitOnRecursionBehavior());
var principle = new Mock<IPrincipal>(); var principle = new Mock<ICurrentUser>();
var requestService = new Mock<IRequestServiceMain>(); var requestService = new Mock<IRequestServiceMain>();
var ruleEval = new Mock<IRuleEvaluator>(); var ruleEval = new Mock<IRuleEvaluator>();
var um = MockHelper.MockUserManager(new List<OmbiUser>()); var um = MockHelper.MockUserManager(new List<OmbiUser>());

View file

@ -9,6 +9,7 @@ using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Core.Settings; using Ombi.Core.Settings;
@ -32,8 +33,9 @@ namespace Ombi.Core.Tests.Engine
TvRequestEngine = new Mock<ITvRequestEngine>(); TvRequestEngine = new Mock<ITvRequestEngine>();
MovieRequestEngine = new Mock<IMovieRequestEngine>(); MovieRequestEngine = new Mock<IMovieRequestEngine>();
MovieRequestEngine = new Mock<IMovieRequestEngine>(); MovieRequestEngine = new Mock<IMovieRequestEngine>();
User = new Mock<IPrincipal>(); User = new Mock<ICurrentUser>();
User.Setup(x => x.Identity.Name).Returns("abc"); User.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "abc" });
UserManager = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); UserManager = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", UserName = "abc", NormalizedUserName = "ABC" } });
Rule = new Mock<IRuleEvaluator>(); Rule = new Mock<IRuleEvaluator>();
Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object, Engine = new VoteEngine(VoteRepository.Object, User.Object, UserManager.Object, Rule.Object, VoteSettings.Object, MusicRequestEngine.Object,
@ -48,7 +50,7 @@ namespace Ombi.Core.Tests.Engine
public Fixture F { get; set; } public Fixture F { get; set; }
public VoteEngine Engine { get; set; } public VoteEngine Engine { get; set; }
public Mock<IPrincipal> User { get; set; } public Mock<ICurrentUser> User { get; set; }
public Mock<OmbiUserManager> UserManager { get; set; } public Mock<OmbiUserManager> UserManager { get; set; }
public Mock<IRuleEvaluator> Rule { get; set; } public Mock<IRuleEvaluator> Rule { get; set; }
public Mock<IRepository<Votes>> VoteRepository { get; set; } public Mock<IRepository<Votes>> VoteRepository { get; set; }

View file

@ -11,6 +11,7 @@ using System.Collections.Generic;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using System; using System;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Core.Helpers;
namespace Ombi.Core.Tests.Rule.Request namespace Ombi.Core.Tests.Rule.Request
{ {
@ -27,17 +28,18 @@ namespace Ombi.Core.Tests.Rule.Request
public void Setup() public void Setup()
{ {
PrincipalMock = new Mock<IPrincipal>();
PrincipalMock.Setup(x => x.Identity.Name).Returns("abc");
FeatureService = new Mock<IFeatureService>(); FeatureService = new Mock<IFeatureService>();
PrincipalMock = new Mock<ICurrentUser>();
PrincipalMock.Setup(x => x.Username).Returns("abc");
PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" });
UserManager = MockHelper.MockUserManager(_users); UserManager = MockHelper.MockUserManager(_users);
Rule = new AutoApproveRule(PrincipalMock.Object, UserManager.Object, FeatureService.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<ICurrentUser> PrincipalMock { get; set; }
private Mock<OmbiUserManager> UserManager { get; set; } private Mock<OmbiUserManager> UserManager { get; set; }
private Mock<IFeatureService> FeatureService { get; set; } private Mock<IFeatureService> FeatureService { get; set; }
@ -99,7 +101,8 @@ namespace Ombi.Core.Tests.Rule.Request
[Test] [Test]
public async Task Should_ReturnSuccess_WhenSystemUserAndRequestTV() public async Task Should_ReturnSuccess_WhenSystemUserAndRequestTV()
{ {
PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" });
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveTv)).ReturnsAsync(false); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.AutoApproveTv)).ReturnsAsync(false);
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow }; var request = new BaseRequest() { RequestType = Store.Entities.RequestType.TvShow };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);

View file

@ -5,6 +5,7 @@ using System.Threading.Tasks;
using Moq; using Moq;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Rule.Rules; using Ombi.Core.Rule.Rules;
using Ombi.Core.Rule.Rules.Request; using Ombi.Core.Rule.Rules.Request;
using Ombi.Helpers; using Ombi.Helpers;
@ -26,8 +27,9 @@ namespace Ombi.Core.Tests.Rule.Request
public void Setup() public void Setup()
{ {
PrincipalMock = new Mock<IPrincipal>(); PrincipalMock = new Mock<ICurrentUser>();
PrincipalMock.Setup(x => x.Identity.Name).Returns("abc"); PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "abc", NormalizedUserName = "ABC", Id = "a" });
UserManager = MockHelper.MockUserManager(_users); UserManager = MockHelper.MockUserManager(_users);
Rule = new CanRequestRule(PrincipalMock.Object, UserManager.Object); Rule = new CanRequestRule(PrincipalMock.Object, UserManager.Object);
@ -35,7 +37,7 @@ namespace Ombi.Core.Tests.Rule.Request
private CanRequestRule Rule { get; set; } private CanRequestRule Rule { get; set; }
private Mock<IPrincipal> PrincipalMock { get; set; } private Mock<ICurrentUser> PrincipalMock { get; set; }
private Mock<OmbiUserManager> UserManager { get; set; } private Mock<OmbiUserManager> UserManager { get; set; }
[Test] [Test]
@ -107,7 +109,8 @@ namespace Ombi.Core.Tests.Rule.Request
[Test] [Test]
public async Task Should_ReturnSuccess_WhenRequestingMovieWithSystemRole() public async Task Should_ReturnSuccess_WhenRequestingMovieWithSystemRole()
{ {
PrincipalMock.Setup(x => x.Identity.Name).Returns("sys"); PrincipalMock.Setup(x => x.GetUser()).ReturnsAsync(new OmbiUser { UserName = "sys", NormalizedUserName = "SYS", Id = "a" });
UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Admin)).ReturnsAsync(false); UserManager.Setup(x => x.IsInRoleAsync(It.IsAny<OmbiUser>(), OmbiRoles.Admin)).ReturnsAsync(false);
var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie }; var request = new BaseRequest() { RequestType = Store.Entities.RequestType.Movie };
var result = await Rule.Execute(request); var result = await Rule.Execute(request);

View file

@ -116,16 +116,25 @@ namespace Ombi.Core.Authentication
public async Task<OmbiUser> GetOmbiUserFromPlexToken(string plexToken) public async Task<OmbiUser> GetOmbiUserFromPlexToken(string plexToken)
{ {
var plexAccount = await _plexApi.GetAccount(plexToken); var plexAccount = await _plexApi.GetAccount(plexToken);
// Check for a ombi user // Check for a ombi user
if (plexAccount?.user != null) if (plexAccount?.user == null)
{ {
var potentialOmbiUser = await Users.FirstOrDefaultAsync(x => return null;
x.ProviderUserId == plexAccount.user.id);
return potentialOmbiUser;
} }
return null; var potentialOmbiUser = await Users.FirstOrDefaultAsync(x =>
x.ProviderUserId == plexAccount.user.id);
// Update ombi user with the token
if (potentialOmbiUser != null)
{
potentialOmbiUser.MediaServerToken = plexAccount.user.authentication_token;
await UpdateAsync(potentialOmbiUser);
}
return potentialOmbiUser;
} }
@ -142,6 +151,10 @@ namespace Ombi.Core.Authentication
var result = await _plexApi.SignIn(new UserRequest { password = password, login = login }); var result = await _plexApi.SignIn(new UserRequest { password = password, login = login });
if (result.user?.authentication_token != null) if (result.user?.authentication_token != null)
{ {
// Update ombi user with the token
user.MediaServerToken = result.user?.authentication_token;
await UpdateAsync(user);
return true; return true;
} }
return false; return false;

View file

@ -26,7 +26,7 @@ namespace Ombi.Core.Engine
private Dictionary<int, MovieRequests> _dbMovies; private Dictionary<int, MovieRequests> _dbMovies;
private Dictionary<int, TvRequests> _dbTv; private Dictionary<int, TvRequests> _dbTv;
protected BaseMediaEngine(IPrincipal identity, IRequestServiceMain requestService, protected BaseMediaEngine(ICurrentUser identity, IRequestServiceMain requestService,
IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub) : base(identity, um, rules) IRuleEvaluator rules, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub) : base(identity, um, rules)
{ {
RequestService = requestService; RequestService = requestService;

View file

@ -11,6 +11,7 @@ using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Config; using Ombi.Config;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo
{ {
public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine public class DemoMovieSearchEngine : MovieSearchEngine, IDemoMovieSearchEngine
{ {
public DemoMovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, public DemoMovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s,
IRepository<RequestSubscription> sub, IOptions<DemoLists> lists) IRepository<RequestSubscription> sub, IOptions<DemoLists> lists)
: base(identity, service, movApi, mapper, logger, r, um, mem, s, sub) : base(identity, service, movApi, mapper, logger, r, um, mem, s, sub)

View file

@ -4,6 +4,7 @@ using Ombi.Api.Trakt;
using Ombi.Api.TvMaze; using Ombi.Api.TvMaze;
using Ombi.Config; using Ombi.Config;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -24,7 +25,7 @@ namespace Ombi.Core.Engine.Demo
public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine public class DemoTvSearchEngine : TvSearchEngine, IDemoTvSearchEngine
{ {
public DemoTvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, public DemoTvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper,
ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache,
ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, IOptions<DemoLists> lists, IImageService imageService, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, IOptions<DemoLists> lists, IImageService imageService,
ISettingsService<CustomizationSettings> custom) ISettingsService<CustomizationSettings> custom)

View file

@ -1,42 +1,35 @@
using System; using System;
using Ombi.Core.Rule; using Ombi.Core.Rule;
using System.Collections.Generic; using System.Collections.Generic;
using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Helpers; using Ombi.Core.Helpers;
namespace Ombi.Core.Engine.Interfaces namespace Ombi.Core.Engine.Interfaces
{ {
public abstract class BaseEngine public abstract class BaseEngine
{ {
protected BaseEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules) protected BaseEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules)
{ {
UserPrinciple = user; CurrentUser = user;
Rules = rules; Rules = rules;
UserManager = um; UserManager = um;
} }
protected IPrincipal UserPrinciple { get; } protected ICurrentUser CurrentUser { get; }
protected IRuleEvaluator Rules { get; } protected IRuleEvaluator Rules { get; }
protected OmbiUserManager UserManager { get; } protected OmbiUserManager UserManager { get; }
protected string Username => UserPrinciple.Identity.Name; protected string Username => CurrentUser.Username;
protected Task<OmbiUser> GetUser() => CurrentUser.GetUser();
private OmbiUser _user; /// <summary>
protected async Task<OmbiUser> GetUser() /// Only used for background tasks
{ /// </summary>
if(!Username.HasValue()) public void SetUser(OmbiUser user) => CurrentUser.SetUser(user);
{
return null;
}
var username = Username.ToUpper();
return _user ??= await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
}
protected async Task<string> UserAlias() protected async Task<string> UserAlias()
{ {
@ -52,7 +45,7 @@ namespace Ombi.Core.Engine.Interfaces
var user = await GetUser(); var user = await GetUser();
return await UserManager.IsInRoleAsync(user, roleName); return await UserManager.IsInRoleAsync(user, roleName);
} }
public async Task<IEnumerable<RuleResult>> RunRequestRules(BaseRequest model) public async Task<IEnumerable<RuleResult>> RunRequestRules(BaseRequest model)
{ {
var ruleResults = await Rules.StartRequestRules(model); var ruleResults = await Rules.StartRequestRules(model);

View file

@ -25,5 +25,6 @@ namespace Ombi.Core.Engine.Interfaces
Task UnSubscribeRequest(int requestId, RequestType type); Task UnSubscribeRequest(int requestId, RequestType type);
Task SubscribeToRequest(int requestId, RequestType type); Task SubscribeToRequest(int requestId, RequestType type);
Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken); Task<RequestEngineResult> ReProcessRequest(int requestId, bool is4K, CancellationToken cancellationToken);
void SetUser(OmbiUser user);
} }
} }

View file

@ -23,12 +23,13 @@ using Ombi.Store.Repository;
using Ombi.Core.Models; using Ombi.Core.Models;
using System.Threading; using System.Threading;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Core.Helpers;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine public class MovieRequestEngine : BaseMediaEngine, IMovieRequestEngine
{ {
public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, IPrincipal user, public MovieRequestEngine(IMovieDbApi movieApi, IRequestServiceMain requestService, ICurrentUser 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,

View file

@ -4,6 +4,7 @@ using Microsoft.Extensions.Logging;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -22,7 +23,7 @@ namespace Ombi.Core.Engine
{ {
public class MovieSearchEngine : BaseMediaEngine, IMovieEngine public class MovieSearchEngine : BaseMediaEngine, IMovieEngine
{ {
public MovieSearchEngine(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, public MovieSearchEngine(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub) ILogger<MovieSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub)
: base(identity, service, r, um, mem, s, sub) : base(identity, service, r, um, mem, s, sub)
{ {

View file

@ -24,12 +24,13 @@ using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using System.ComponentModel; using System.ComponentModel;
using Ombi.Core.Helpers;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
public class MusicRequestEngine : BaseMediaEngine, IMusicRequestEngine public class MusicRequestEngine : BaseMediaEngine, IMusicRequestEngine
{ {
public MusicRequestEngine(IRequestServiceMain requestService, IPrincipal user, public MusicRequestEngine(IRequestServiceMain requestService, ICurrentUser user,
INotificationHelper helper, IRuleEvaluator r, ILogger<MusicRequestEngine> log, INotificationHelper helper, IRuleEvaluator r, ILogger<MusicRequestEngine> log,
OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache, OmbiUserManager manager, IRepository<RequestLog> rl, ICacheService cache,
ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, ILidarrApi lidarr, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, ILidarrApi lidarr,

View file

@ -27,7 +27,7 @@ namespace Ombi.Core.Engine
{ {
public class MusicSearchEngine : BaseMediaEngine, IMusicSearchEngine public class MusicSearchEngine : BaseMediaEngine, IMusicSearchEngine
{ {
public MusicSearchEngine(IPrincipal identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper, public MusicSearchEngine(ICurrentUser identity, IRequestServiceMain service, ILidarrApi lidarrApi, IMapper mapper,
ILogger<MusicSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, ILogger<MusicSearchEngine> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub,
ISettingsService<LidarrSettings> lidarrSettings) ISettingsService<LidarrSettings> lidarrSettings)
: base(identity, service, r, um, mem, s, sub) : base(identity, service, r, um, mem, s, sub)

View file

@ -32,7 +32,7 @@ namespace Ombi.Core.Engine
{ {
public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine public class TvRequestEngine : BaseMediaEngine, ITvRequestEngine
{ {
public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, IPrincipal user, public TvRequestEngine(ITvMazeApi tvApi, IMovieDbApi movApi, IRequestServiceMain requestService, ICurrentUser user,
INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger<TvRequestEngine> logger, INotificationHelper helper, IRuleEvaluator rule, OmbiUserManager manager, ILogger<TvRequestEngine> logger,
ITvSender sender, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache, ITvSender sender, IRepository<RequestLog> rl, ISettingsService<OmbiSettings> settings, ICacheService cache,
IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub) IRepository<RequestSubscription> sub, IMediaCacheService mediaCacheService) : base(user, requestService, rule, manager, cache, settings, sub)

View file

@ -23,6 +23,7 @@ using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using System.Threading; using System.Threading;
using TraktSharp.Entities; using TraktSharp.Entities;
using Ombi.Core.Helpers;
namespace Ombi.Core.Engine namespace Ombi.Core.Engine
{ {
@ -32,7 +33,7 @@ namespace Ombi.Core.Engine
private readonly IImageService _imageService; private readonly IImageService _imageService;
private readonly IMovieDbApi _theMovieDbApi; private readonly IMovieDbApi _theMovieDbApi;
public TvSearchEngine(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, public TvSearchEngine(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper,
ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService<CustomizationSettings> customizationSettings, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ISettingsService<CustomizationSettings> customizationSettings,
ICacheService memCache, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, IImageService imageService, ICacheService memCache, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, IImageService imageService,
IMovieDbApi theMovieDbApi) IMovieDbApi theMovieDbApi)

View file

@ -5,6 +5,7 @@ using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Search.V2; using Ombi.Core.Models.Search.V2;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Store.Entities; using Ombi.Store.Entities;
@ -17,7 +18,7 @@ namespace Ombi.Core.Engine.V2
{ {
public DateTime DaysAgo => DateTime.Now.AddDays(-90); public DateTime DaysAgo => DateTime.Now.AddDays(-90);
public DateTime DaysAhead => DateTime.Now.AddDays(90); public DateTime DaysAhead => DateTime.Now.AddDays(90);
public CalendarEngine(IPrincipal user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo, public CalendarEngine(ICurrentUser user, OmbiUserManager um, IRuleEvaluator rules, IMovieRequestRepository movieRepo,
ITvRequestRepository tvRequestRepo) : base(user, um, rules) ITvRequestRepository tvRequestRepo) : base(user, um, rules)
{ {
_movieRepo = movieRepo; _movieRepo = movieRepo;

View file

@ -5,6 +5,7 @@ using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search; using Ombi.Core.Models.Search;
using Ombi.Core.Models.Search.V2; using Ombi.Core.Models.Search.V2;
@ -28,7 +29,7 @@ namespace Ombi.Core.Engine.V2
{ {
public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2 public class MovieSearchEngineV2 : BaseMediaEngine, IMovieEngineV2
{ {
public MovieSearchEngineV2(IPrincipal identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper, public MovieSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, IMovieDbApi movApi, IMapper mapper,
ILogger<MovieSearchEngineV2> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub, ILogger<MovieSearchEngineV2> logger, IRuleEvaluator r, OmbiUserManager um, ICacheService mem, ISettingsService<OmbiSettings> s, IRepository<RequestSubscription> sub,
ISettingsService<CustomizationSettings> customizationSettings, IMovieRequestEngine movieRequestEngine, IHttpClientFactory httpClientFactory) ISettingsService<CustomizationSettings> customizationSettings, IMovieRequestEngine movieRequestEngine, IHttpClientFactory httpClientFactory)
: base(identity, service, r, um, mem, s, sub) : base(identity, service, r, um, mem, s, sub)

View file

@ -7,6 +7,7 @@ using Ombi.Api.MusicBrainz;
using Ombi.Api.TheMovieDb; using Ombi.Api.TheMovieDb;
using Ombi.Api.TheMovieDb.Models; using Ombi.Api.TheMovieDb.Models;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search.V2; using Ombi.Core.Models.Search.V2;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -25,7 +26,7 @@ namespace Ombi.Core.Engine.V2
{ {
public class MultiSearchEngine : BaseMediaEngine, IMultiSearchEngine public class MultiSearchEngine : BaseMediaEngine, IMultiSearchEngine
{ {
public MultiSearchEngine(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, public MultiSearchEngine(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules,
OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, IRepository<RequestSubscription> sub,
IMovieDbApi movieDbApi, ISettingsService<LidarrSettings> lidarrSettings, IMusicBrainzApi musicApi) IMovieDbApi movieDbApi, ISettingsService<LidarrSettings> lidarrSettings, IMusicBrainzApi musicApi)
: base(identity, requestService, rules, um, cache, ombiSettings, sub) : base(identity, requestService, rules, um, cache, ombiSettings, sub)

View file

@ -11,6 +11,7 @@ using Ombi.Api.Lidarr.Models;
using Ombi.Api.MusicBrainz; using Ombi.Api.MusicBrainz;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
using Ombi.Core.Models.Requests; using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search.V2.Music; using Ombi.Core.Models.Search.V2.Music;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -31,7 +32,7 @@ namespace Ombi.Core.Engine.V2
private readonly ISettingsService<LidarrSettings> _lidarrSettings; private readonly ISettingsService<LidarrSettings> _lidarrSettings;
private readonly ILidarrApi _lidarrApi; private readonly ILidarrApi _lidarrApi;
public MusicSearchEngineV2(IPrincipal identity, IRequestServiceMain requestService, IRuleEvaluator rules, public MusicSearchEngineV2(ICurrentUser identity, IRequestServiceMain requestService, IRuleEvaluator rules,
OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings, OmbiUserManager um, ICacheService cache, ISettingsService<OmbiSettings> ombiSettings,
IRepository<RequestSubscription> sub, IMusicBrainzApi musicBrainzApi, ISettingsService<LidarrSettings> lidarrSettings, IRepository<RequestSubscription> sub, IMusicBrainzApi musicBrainzApi, ISettingsService<LidarrSettings> lidarrSettings,
ILidarrApi lidarrApi) ILidarrApi lidarrApi)

View file

@ -25,6 +25,7 @@ using Ombi.Api.TheMovieDb.Models;
using System.Diagnostics; using System.Diagnostics;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.UI; using Ombi.Core.Models.UI;
using Ombi.Core.Helpers;
namespace Ombi.Core.Engine.V2 namespace Ombi.Core.Engine.V2
{ {
@ -37,7 +38,7 @@ namespace Ombi.Core.Engine.V2
private readonly ISettingsService<CustomizationSettings> _customization; private readonly ISettingsService<CustomizationSettings> _customization;
private readonly ITvRequestEngine _requestEngine; private readonly ITvRequestEngine _requestEngine;
public TvSearchEngineV2(IPrincipal identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper, public TvSearchEngineV2(ICurrentUser identity, IRequestServiceMain service, ITvMazeApi tvMaze, IMapper mapper,
ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService<OmbiSettings> s, ITraktApi trakt, IRuleEvaluator r, OmbiUserManager um, ICacheService memCache, ISettingsService<OmbiSettings> s,
IRepository<RequestSubscription> sub, IMovieDbApi movieApi, ISettingsService<CustomizationSettings> customization, ITvRequestEngine requestEngine) IRepository<RequestSubscription> sub, IMovieDbApi movieApi, ISettingsService<CustomizationSettings> customization, ITvRequestEngine requestEngine)
: base(identity, service, r, um, memCache, s, sub) : base(identity, service, r, um, memCache, s, sub)

View file

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Core.Models.UI; using Ombi.Core.Models.UI;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
@ -20,7 +21,7 @@ namespace Ombi.Core.Engine
{ {
public class VoteEngine : BaseEngine, IVoteEngine public class VoteEngine : BaseEngine, IVoteEngine
{ {
public VoteEngine(IRepository<Votes> votes, IPrincipal user, OmbiUserManager um, IRuleEvaluator r, ISettingsService<VoteSettings> voteSettings, public VoteEngine(IRepository<Votes> votes, ICurrentUser user, OmbiUserManager um, IRuleEvaluator r, ISettingsService<VoteSettings> voteSettings,
IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r) IMusicRequestEngine musicRequestEngine, ITvRequestEngine tvRequestEngine, IMovieRequestEngine movieRequestEngine) : base(user, um, r)
{ {
_voteRepository = votes; _voteRepository = votes;

View file

@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication;
using Ombi.Helpers;
using Ombi.Store.Entities;
using System.Security.Principal;
using System.Threading.Tasks;
namespace Ombi.Core.Helpers
{
public class CurrentUser : ICurrentUser
{
private readonly IPrincipal _principle;
private readonly OmbiUserManager _userManager;
private OmbiUser _user;
public IIdentity Identity { get; set; }
public CurrentUser(IPrincipal principle, OmbiUserManager userManager)
{
_principle = principle;
_userManager = userManager;
Identity = _principle?.Identity;
}
public void SetUser(OmbiUser user)
{
_user = user;
}
public string Username => Identity.Name;
public async Task<OmbiUser> GetUser()
{
if (!Username.HasValue() && _user == null)
{
return null;
}
if (_user != null)
{
return _user;
}
var username = Username.ToUpper();
return _user ??= await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
}
}
}

View file

@ -0,0 +1,15 @@
using Ombi.Store.Entities;
using System.Security.Principal;
using System.Threading.Tasks;
namespace Ombi.Core.Helpers
{
public interface ICurrentUser
{
string Username { get; }
Task<OmbiUser> GetUser();
void SetUser(OmbiUser user);
IIdentity Identity { get; set; }
}
}

View file

@ -1,31 +1,5 @@
#region Copyright using Newtonsoft.Json;
// /************************************************************************ using Ombi.Store.Entities.Requests;
// Copyright (c) 2018 Jamie Rees
// File: MovieRequestViewModel.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using Newtonsoft.Json;
namespace Ombi.Core.Models.Requests namespace Ombi.Core.Models.Requests
{ {
@ -41,5 +15,11 @@ namespace Ombi.Core.Models.Requests
/// </summary> /// </summary>
[JsonIgnore] [JsonIgnore]
public string RequestedByAlias { get; set; } public string RequestedByAlias { get; set; }
/// <summary>
/// Only set via list imports
/// </summary>
[JsonIgnore]
public RequestSource Source { get; set; } = RequestSource.Ombi;
} }
} }

View file

@ -3,6 +3,7 @@ using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
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.Services;
@ -15,20 +16,21 @@ namespace Ombi.Core.Rule.Rules.Request
{ {
public class AutoApproveRule : BaseRequestRule, IRules<BaseRequest> public class AutoApproveRule : BaseRequestRule, IRules<BaseRequest>
{ {
public AutoApproveRule(IPrincipal principal, OmbiUserManager um, IFeatureService featureService) public AutoApproveRule(ICurrentUser principal, OmbiUserManager um, IFeatureService featureService)
{ {
User = principal; User = principal;
_manager = um; _manager = um;
_featureService = featureService; _featureService = featureService;
} }
private IPrincipal User { get; } private ICurrentUser User { get; }
private readonly OmbiUserManager _manager; private readonly OmbiUserManager _manager;
private readonly IFeatureService _featureService; private readonly IFeatureService _featureService;
public async Task<RuleResult> Execute(BaseRequest obj) public async Task<RuleResult> Execute(BaseRequest obj)
{ {
var username = User.Identity.Name.ToUpper(); var currentUser = await User.GetUser();
var username = currentUser.UserName.ToUpper();
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)
{ {

View file

@ -10,23 +10,25 @@ using Ombi.Core.Engine;
using Ombi.Core.Rule.Interfaces; using Ombi.Core.Rule.Interfaces;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Store.Entities.Requests; using Ombi.Store.Entities.Requests;
using Ombi.Core.Helpers;
namespace Ombi.Core.Rule.Rules.Request namespace Ombi.Core.Rule.Rules.Request
{ {
public class CanRequestRule : BaseRequestRule, IRules<BaseRequest> public class CanRequestRule : BaseRequestRule, IRules<BaseRequest>
{ {
public CanRequestRule(IPrincipal principal, OmbiUserManager manager) public CanRequestRule(ICurrentUser principal, OmbiUserManager manager)
{ {
User = principal; User = principal;
_manager = manager; _manager = manager;
} }
private IPrincipal User { get; } private ICurrentUser User { get; }
private readonly OmbiUserManager _manager; private readonly OmbiUserManager _manager;
public async Task<RuleResult> Execute(BaseRequest obj) public async Task<RuleResult> Execute(BaseRequest obj)
{ {
var username = User.Identity.Name.ToUpper(); var currentUser = await User.GetUser();
var username = currentUser.UserName.ToUpper();
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)
return Success(); return Success();

View file

@ -1,5 +1,6 @@
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Helpers;
using Ombi.Core.Models; using Ombi.Core.Models;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Store.Entities; using Ombi.Store.Entities;
@ -20,11 +21,11 @@ namespace Ombi.Core.Services
} }
public class RequestLimitService : IRequestLimitService public class RequestLimitService : IRequestLimitService
{ {
private readonly IPrincipal _user; private readonly ICurrentUser _user;
private readonly OmbiUserManager _userManager; private readonly OmbiUserManager _userManager;
private readonly IRepository<RequestLog> _requestLog; private readonly IRepository<RequestLog> _requestLog;
public RequestLimitService(IPrincipal user, OmbiUserManager userManager, IRepository<RequestLog> rl) public RequestLimitService(ICurrentUser user, OmbiUserManager userManager, IRepository<RequestLog> rl)
{ {
_user = user; _user = user;
_userManager = userManager; _userManager = userManager;
@ -141,7 +142,8 @@ namespace Ombi.Core.Services
private async Task<OmbiUser> GetUser() private async Task<OmbiUser> GetUser()
{ {
var username = _user.Identity.Name.ToUpper(); var currentUser = await _user.GetUser();
var username = currentUser.UserName.ToUpper();
return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username); return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
} }

View file

@ -70,6 +70,7 @@ using Ombi.Api.RottenTomatoes;
using System.Net.Http; using System.Net.Http;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Ombi.Core.Services; using Ombi.Core.Services;
using Ombi.Core.Helpers;
namespace Ombi.DependencyInjection namespace Ombi.DependencyInjection
{ {
@ -124,6 +125,8 @@ namespace Ombi.DependencyInjection
var runtimeVersion = AssemblyHelper.GetRuntimeVersion(); var runtimeVersion = AssemblyHelper.GetRuntimeVersion();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User); services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
// HttpContext User is null for background jobs
services.AddScoped<ICurrentUser, CurrentUser>(sp => new CurrentUser(sp.GetService<IHttpContextAccessor>()?.HttpContext?.User ?? null, sp.GetService<OmbiUserManager>()));
services.AddHttpClient("OmbiClient", client => services.AddHttpClient("OmbiClient", client =>
{ {
client.DefaultRequestHeaders.Add("User-Agent", $"Ombi/{runtimeVersion} (https://ombi.io/)"); client.DefaultRequestHeaders.Add("User-Agent", $"Ombi/{runtimeVersion} (https://ombi.io/)");

View file

@ -3,18 +3,16 @@ using Moq.AutoMock;
using NUnit.Framework; using NUnit.Framework;
using Ombi.Api.Plex; using Ombi.Api.Plex;
using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models;
using Ombi.Core.Authentication; using Ombi.Core.Engine;
using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Models.Requests;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Schedule.Jobs.Plex; using Ombi.Schedule.Jobs.Plex;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Test.Common; using Ombi.Test.Common;
using Quartz; using Quartz;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -27,11 +25,11 @@ namespace Ombi.Schedule.Tests
private PlexWatchlistImport _subject; private PlexWatchlistImport _subject;
private AutoMocker _mocker; private AutoMocker _mocker;
private Mock<IJobExecutionContext> _context; private Mock<IJobExecutionContext> _context;
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
_mocker = new AutoMocker(); _mocker = new AutoMocker();
var um = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" } }); var um = MockHelper.MockUserManager(new List<OmbiUser> { new OmbiUser { Id = "abc", UserType = UserType.PlexUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" } });
_mocker.Use(um); _mocker.Use(um);
_context = _mocker.GetMock<IJobExecutionContext>(); _context = _mocker.GetMock<IJobExecutionContext>();
@ -42,16 +40,194 @@ namespace Ombi.Schedule.Tests
[Test] [Test]
public async Task TerminatesWhenPlexIsNotEnabled() public async Task TerminatesWhenPlexIsNotEnabled()
{ {
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false }); _mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = false, EnableWatchlistImport = true });
await _subject.Execute(null); await _subject.Execute(null);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
_mocker.Verify<IPlexApi>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
} }
[Test]
public async Task TerminatesWhenWatchlistIsNotEnabled()
{
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = false });
await _subject.Execute(null);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
_mocker.Verify<IPlexApi>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
}
[Test] [Test]
public async Task EmptyWatchList() public async Task EmptyWatchList()
{ {
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true }); _mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
_mocker.Setup<IPlexApi, Task<PlexWatchlist>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlist()); _mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer());
await _subject.Execute(_context.Object); await _subject.Execute(_context.Object);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
_mocker.Verify<IPlexApi>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
}
[Test]
public async Task NoPlexUsersWithToken()
{
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
var um = MockHelper.MockUserManager(new List<OmbiUser>
{
new OmbiUser { Id = "abc", UserType = UserType.EmbyUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" },
new OmbiUser { Id = "abc", UserType = UserType.LocalUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" },
new OmbiUser { Id = "abc", UserType = UserType.SystemUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" },
new OmbiUser { Id = "abc", UserType = UserType.JellyfinUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" },
new OmbiUser { Id = "abc", UserType = UserType.EmbyConnectUser, MediaServerToken = "abc", UserName = "abc", NormalizedUserName = "ABC" },
new OmbiUser { Id = "abc", UserType = UserType.PlexUser, UserName = "abc", NormalizedUserName = "ABC" },
});
_mocker.Use(um);
_subject = _mocker.CreateInstance<PlexWatchlistImport>();
await _subject.Execute(_context.Object);
_mocker.Verify<IPlexApi>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Never);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
}
[Test]
public async Task MovieRequestFromWatchList_NoGuid()
{
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer
{
MediaContainer = new PlexWatchlist
{
Metadata = new List<Metadata>
{
new Metadata
{
type = "movie",
ratingKey = "abc"
}
}
}
});
_mocker.Setup<IPlexApi, Task<PlexWatchlistMetadataContainer>>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new PlexWatchlistMetadataContainer
{
MediaContainer = new PlexWatchlistMetadata
{
Metadata = new WatchlistMetadata[]
{
new WatchlistMetadata
{
Guid = new List<PlexGuids>
{
new PlexGuids
{
Id = "tmdb://123"
}
}
}
}
}
});
_mocker.Setup<IMovieRequestEngine, Task<RequestEngineResult>>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()))
.ReturnsAsync(new RequestEngineResult { RequestId = 1 });
await _subject.Execute(_context.Object);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.Is<MovieRequestViewModel>(x => x.TheMovieDbId == 123)), Times.Once);
_mocker.Verify<IPlexApi>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_mocker.Verify<IMovieRequestEngine>(x => x.SetUser(It.Is<OmbiUser>(x => x.Id == "abc")), Times.Once);
}
[Test]
public async Task MovieRequestFromWatchList_AlreadyRequested()
{
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer
{
MediaContainer = new PlexWatchlist
{
Metadata = new List<Metadata>
{
new Metadata
{
type = "movie",
ratingKey = "abc"
}
}
}
});
_mocker.Setup<IPlexApi, Task<PlexWatchlistMetadataContainer>>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new PlexWatchlistMetadataContainer
{
MediaContainer = new PlexWatchlistMetadata
{
Metadata = new WatchlistMetadata[]
{
new WatchlistMetadata
{
Guid = new List<PlexGuids>
{
new PlexGuids
{
Id = "tmdb://123"
}
}
}
}
}
});
_mocker.Setup<IMovieRequestEngine, Task<RequestEngineResult>>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()))
.ReturnsAsync(new RequestEngineResult { ErrorCode = ErrorCode.AlreadyRequested, ErrorMessage = "Requested" });
await _subject.Execute(_context.Object);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.Is<MovieRequestViewModel>(x => x.TheMovieDbId == 123)), Times.Once);
_mocker.Verify<IPlexApi>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_mocker.Verify<IMovieRequestEngine>(x => x.SetUser(It.Is<OmbiUser>(x => x.Id == "abc")), Times.Once);
}
[Test]
public async Task MovieRequestFromWatchList_NoTmdbGuid()
{
_mocker.Setup<ISettingsService<PlexSettings>, Task<PlexSettings>>(x => x.GetSettingsAsync()).ReturnsAsync(new PlexSettings { Enable = true, EnableWatchlistImport = true });
_mocker.Setup<IPlexApi, Task<PlexWatchlistContainer>>(x => x.GetWatchlist(It.IsAny<string>(), It.IsAny<CancellationToken>())).ReturnsAsync(new PlexWatchlistContainer
{
MediaContainer = new PlexWatchlist
{
Metadata = new List<Metadata>
{
new Metadata
{
type = "movie",
ratingKey = "abc"
}
}
}
});
_mocker.Setup<IPlexApi, Task<PlexWatchlistMetadataContainer>>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new PlexWatchlistMetadataContainer
{
MediaContainer = new PlexWatchlistMetadata
{
Metadata = new WatchlistMetadata[]
{
new WatchlistMetadata
{
Guid = new List<PlexGuids>
{
new PlexGuids
{
Id = "imdb://123"
}
}
}
}
}
});
_mocker.Setup<IMovieRequestEngine, Task<RequestEngineResult>>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()))
.ReturnsAsync(new RequestEngineResult { RequestId = 1 });
await _subject.Execute(_context.Object);
_mocker.Verify<IMovieRequestEngine>(x => x.RequestMovie(It.IsAny<MovieRequestViewModel>()), Times.Never);
_mocker.Verify<IPlexApi>(x => x.GetWatchlistMetadata("abc", It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);
_mocker.Verify<IMovieRequestEngine>(x => x.SetUser(It.Is<OmbiUser>(x => x.Id == "abc")), Times.Never);
} }
} }
} }

View file

@ -1,17 +1,17 @@
using Ombi.Api.Plex; using Microsoft.Extensions.Logging;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models; using Ombi.Api.Plex.Models;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Core.Engine;
using Ombi.Core.Engine.Interfaces; using Ombi.Core.Engine.Interfaces;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository.Requests; using Ombi.Store.Entities.Requests;
using Quartz; using Quartz;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -22,34 +22,32 @@ namespace Ombi.Schedule.Jobs.Plex
private readonly IPlexApi _plexApi; private readonly IPlexApi _plexApi;
private readonly ISettingsService<PlexSettings> _settings; private readonly ISettingsService<PlexSettings> _settings;
private readonly OmbiUserManager _ombiUserManager; private readonly OmbiUserManager _ombiUserManager;
private readonly IMovieRequestRepository _movieRequestRepository;
private readonly ITvRequestRepository _tvRequestRepository;
private readonly IMovieRequestEngine _movieRequestEngine; private readonly IMovieRequestEngine _movieRequestEngine;
private readonly ILogger _logger;
public PlexWatchlistImport(IPlexApi plexApi, ISettingsService<PlexSettings> settings, OmbiUserManager ombiUserManager, public PlexWatchlistImport(IPlexApi plexApi, ISettingsService<PlexSettings> settings, OmbiUserManager ombiUserManager,
IMovieRequestRepository movieRequestRepository, ITvRequestRepository tvRequestRepository, IMovieRequestEngine movieRequestEngine) IMovieRequestEngine movieRequestEngine,
ILogger<PlexWatchlistImport> logger)
{ {
_plexApi = plexApi; _plexApi = plexApi;
_settings = settings; _settings = settings;
_ombiUserManager = ombiUserManager; _ombiUserManager = ombiUserManager;
_movieRequestRepository = movieRequestRepository;
_tvRequestRepository = tvRequestRepository;
_movieRequestEngine = movieRequestEngine; _movieRequestEngine = movieRequestEngine;
_logger = logger;
} }
public async Task Execute(IJobExecutionContext context) public async Task Execute(IJobExecutionContext context)
{ {
var settings = await _settings.GetSettingsAsync(); var settings = await _settings.GetSettingsAsync();
if (!settings.Enable) if (!settings.Enable || !settings.EnableWatchlistImport)
{ {
return; return;
} }
var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList(); var plexUsersWithTokens = _ombiUserManager.Users.Where(x => x.UserType == UserType.PlexUser && x.MediaServerToken != null).ToList();
//foreach (var user in plexUsersWithTokens) foreach (var user in plexUsersWithTokens)
//{ {
var watchlist = await _plexApi.GetWatchlist(token, context?.CancellationToken ?? CancellationToken.None); var watchlist = await _plexApi.GetWatchlist(user.MediaServerToken, context?.CancellationToken ?? CancellationToken.None);
if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false)) if (watchlist == null || !(watchlist.MediaContainer?.Metadata?.Any() ?? false))
{ {
return; return;
@ -64,27 +62,38 @@ namespace Ombi.Schedule.Jobs.Plex
await ProcessShow(item); await ProcessShow(item);
break; break;
case "movie": case "movie":
await ProcessMovie(token, item, null, context?.CancellationToken ?? CancellationToken.None); await ProcessMovie(user.MediaServerToken, item, user, context?.CancellationToken ?? CancellationToken.None);
break; break;
} }
} }
}
//}
} }
private async Task ProcessMovie(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) private async Task ProcessMovie(string authToken, Metadata movie, OmbiUser user, CancellationToken cancellationToken)
{ {
var providerIds = await GetProviderIds(authToken, movie, servers, cancellationToken); var providerIds = await GetProviderIds(authToken, movie, cancellationToken);
if (!providerIds.TheMovieDb.HasValue()) if (!providerIds.TheMovieDb.HasValue())
{ {
// We need a MovieDbId to support this; // We need a MovieDbId to support this;
return; return;
} }
//_movieRequestEngine.RequestMovie(new() { TheMovieDbId = }); _movieRequestEngine.SetUser(user);
var response = await _movieRequestEngine.RequestMovie(new() { TheMovieDbId = int.Parse(providerIds.TheMovieDb), Source = RequestSource.PlexWatchlist});
if (response.IsError)
{
if (response.ErrorCode == ErrorCode.AlreadyRequested)
{
return;
}
_logger.LogInformation($"Error adding title from PlexWatchlist for user '{user.UserName}'. Message: '{response.ErrorMessage}'");
}
else
{
_logger.LogInformation($"Added title from PlexWatchlist for user '{user.UserName}'. {response.Message}");
}
} }
private async Task<ProviderId> GetProviderIds(string authToken, Metadata movie, PlexServers servers, CancellationToken cancellationToken) private async Task<ProviderId> GetProviderIds(string authToken, Metadata movie, CancellationToken cancellationToken)
{ {
var guids = new List<string>(); var guids = new List<string>();
if (!movie.Guid.Any()) if (!movie.Guid.Any())

View file

@ -91,6 +91,7 @@ namespace Ombi.Schedule
await OmbiQuartz.Instance.AddJob<IPlexUserImporter>(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s)); await OmbiQuartz.Instance.AddJob<IPlexUserImporter>(nameof(IPlexUserImporter), "Plex", JobSettingsHelper.UserImporter(s));
await OmbiQuartz.Instance.AddJob<IPlexEpisodeSync>(nameof(IPlexEpisodeSync), "Plex", null); await OmbiQuartz.Instance.AddJob<IPlexEpisodeSync>(nameof(IPlexEpisodeSync), "Plex", null);
await OmbiQuartz.Instance.AddJob<IPlexAvailabilityChecker>(nameof(IPlexAvailabilityChecker), "Plex", null); await OmbiQuartz.Instance.AddJob<IPlexAvailabilityChecker>(nameof(IPlexAvailabilityChecker), "Plex", null);
await OmbiQuartz.Instance.AddJob<IPlexWatchlistImport>(nameof(IPlexWatchlistImport), "Plex", JobSettingsHelper.PlexWatchlistImport(s));
} }
private static async Task AddEmby(JobSettings s) private static async Task AddEmby(JobSettings s)

View file

@ -7,6 +7,7 @@ namespace Ombi.Core.Settings.Models.External
public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings public sealed class PlexSettings : Ombi.Settings.Settings.Models.Settings
{ {
public bool Enable { get; set; } public bool Enable { get; set; }
public bool EnableWatchlistImport { get; set; }
/// <summary> /// <summary>
/// This is the ClientId for OAuth /// This is the ClientId for OAuth
/// </summary> /// </summary>

View file

@ -19,5 +19,6 @@
public string RetryRequests { get; set; } public string RetryRequests { get; set; }
public string MediaDatabaseRefresh { get; set; } public string MediaDatabaseRefresh { get; set; }
public string AutoDeleteRequests { get; set; } public string AutoDeleteRequests { get; set; }
public string PlexWatchlistImport { get; set; }
} }
} }

View file

@ -54,6 +54,11 @@ namespace Ombi.Settings.Settings.Models
{ {
return ValidateCron(Get(s.UserImporter, Cron.Daily())); return ValidateCron(Get(s.UserImporter, Cron.Daily()));
} }
public static string PlexWatchlistImport(JobSettings s)
{
return ValidateCron(Get(s.PlexWatchlistImport, Cron.Daily()));
}
public static string Newsletter(JobSettings s) public static string Newsletter(JobSettings s)
{ {

View file

@ -22,6 +22,8 @@ namespace Ombi.Store.Entities.Requests
[ForeignKey(nameof(RequestedUserId))] [ForeignKey(nameof(RequestedUserId))]
public OmbiUser RequestedUser { get; set; } public OmbiUser RequestedUser { get; set; }
public RequestSource Source { get; set; } = RequestSource.Ombi;
[NotMapped] [NotMapped]
public virtual bool CanApprove => !Approved && !Available; public virtual bool CanApprove => !Approved && !Available;

View file

@ -0,0 +1,8 @@
namespace Ombi.Store.Entities.Requests
{
public enum RequestSource
{
Ombi = 0,
PlexWatchlist = 1
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Ombi.Store.Migrations.OmbiSqlite
{
public partial class RequestSource : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Source",
table: "MovieRequests",
type: "INTEGER",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "Source",
table: "ChildRequests",
type: "INTEGER",
nullable: false,
defaultValue: 0);
migrationBuilder.AddColumn<int>(
name: "Source",
table: "AlbumRequests",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Source",
table: "MovieRequests");
migrationBuilder.DropColumn(
name: "Source",
table: "ChildRequests");
migrationBuilder.DropColumn(
name: "Source",
table: "AlbumRequests");
}
}
}

View file

@ -469,6 +469,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
b.Property<string>("RequestedUserId") b.Property<string>("RequestedUserId")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Source")
.HasColumnType("INTEGER");
b.Property<string>("Title") b.Property<string>("Title")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -527,6 +530,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
b.Property<int>("SeriesType") b.Property<int>("SeriesType")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Source")
.HasColumnType("INTEGER");
b.Property<string>("Title") b.Property<string>("Title")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
@ -729,6 +735,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
b.Property<int>("RootPathOverride") b.Property<int>("RootPathOverride")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<int>("Source")
.HasColumnType("INTEGER");
b.Property<string>("Status") b.Property<string>("Status")
.HasColumnType("TEXT"); .HasColumnType("TEXT");

View file

@ -112,6 +112,7 @@ export interface IPublicInfo {
export interface IPlexSettings extends ISettings { export interface IPlexSettings extends ISettings {
enable: boolean; enable: boolean;
enableWatchlistImport: boolean;
servers: IPlexServer[]; servers: IPlexServer[];
} }
@ -219,6 +220,7 @@ export interface IJobSettings {
mediaDatabaseRefresh: string; mediaDatabaseRefresh: string;
autoDeleteRequests: string; autoDeleteRequests: string;
embyRecentlyAddedSync: string; embyRecentlyAddedSync: string;
plexWatchlistImport: string;
} }
export interface IIssueSettings extends ISettings { export interface IIssueSettings extends ISettings {

View file

@ -27,6 +27,10 @@ export class JobService extends ServiceHelpers {
return this.http.post<boolean>(`${this.url}plexUserImporter/`, {headers: this.headers}); return this.http.post<boolean>(`${this.url}plexUserImporter/`, {headers: this.headers});
} }
public runPlexWatchlistImport(): Observable<boolean> {
return this.http.post<boolean>(`${this.url}plexwatchlist/`, {headers: this.headers});
}
public runEmbyImporter(): Observable<boolean> { public runEmbyImporter(): Observable<boolean> {
return this.http.post<boolean>(`${this.url}embyUserImporter/`, {headers: this.headers}); return this.http.post<boolean>(`${this.url}embyUserImporter/`, {headers: this.headers});
} }

View file

@ -77,6 +77,13 @@
<small *ngIf="form.get('plexRecentlyAddedSync').hasError('required')" class="error-text">The Plex Sync is required</small></mat-form-field> <small *ngIf="form.get('plexRecentlyAddedSync').hasError('required')" class="error-text">The Plex Sync is required</small></mat-form-field>
<button mat-raised-button type="button" class="btn btn-sm btn-primary-outline cronbtn" (click)="testCron(form.get('plexRecentlyAddedSync')?.value)">Test</button> <button mat-raised-button type="button" class="btn btn-sm btn-primary-outline cronbtn" (click)="testCron(form.get('plexRecentlyAddedSync')?.value)">Test</button>
</div> </div>
<div class="form-group cronBox">
<mat-form-field appearance="outline" floatLabel=always>
<mat-label for="plexWatchlistImport" class="control-mat-label">Plex Watchlist Import</mat-label>
<input type="text" matInput [ngClass]="{'form-error': form.get('plexWatchlistImport').hasError('required')}" id="plexWatchlistImport" name="plexWatchlistImport" formControlName="plexWatchlistImport">
<small *ngIf="form.get('plexWatchlistImport').hasError('required')" class="error-text">The Plex Watchlist Import is required</small></mat-form-field>
<button mat-raised-button type="button" class="btn btn-sm btn-primary-outline cronbtn" (click)="testCron(form.get('plexWatchlistImport')?.value)">Test</button>
</div>
<div class="form-group cronBox"> <div class="form-group cronBox">
<mat-form-field appearance="outline" floatLabel=always> <mat-form-field appearance="outline" floatLabel=always>

View file

@ -37,6 +37,7 @@ export class JobsComponent implements OnInit {
mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required], mediaDatabaseRefresh: [x.mediaDatabaseRefresh, Validators.required],
autoDeleteRequests: [x.autoDeleteRequests, Validators.required], autoDeleteRequests: [x.autoDeleteRequests, Validators.required],
embyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required], embyRecentlyAddedSync: [x.embyRecentlyAddedSync, Validators.required],
plexWatchlistImport: [x.plexWatchlistImport, Validators.required],
}); });
}); });
} }

View file

@ -9,6 +9,12 @@
<mat-slide-toggle [(ngModel)]="settings.enable" [checked]="settings.enable">Enable <mat-slide-toggle [(ngModel)]="settings.enable" [checked]="settings.enable">Enable
</mat-slide-toggle> </mat-slide-toggle>
</div> </div>
<div class="md-form-field">
<mat-slide-toggle [(ngModel)]="settings.enableWatchlistImport" [checked]="settings.enableWatchlistImport">Enable User Watchlist Requests
</mat-slide-toggle>
<p>When a Plex User adds something to their watchlist in Plex, it will turn up in Ombi as a Request if enabled. This <b>only</b> applies to users that are logging in with their Plex Account</p>
<p>Request limits if set are all still applied etc.</p>
</div>
<div class="md-form-field"> <div class="md-form-field">
<mat-slide-toggle [(ngModel)]="advanced">Advanced</mat-slide-toggle> <mat-slide-toggle [(ngModel)]="advanced">Advanced</mat-slide-toggle>
</div> </div>
@ -183,6 +189,12 @@
Clear Data And Resync Clear Data And Resync
</button> </button>
</div> </div>
<div class="form-group">
<button mat-raised-button (click)="runWatchlistImport()" type="button" id="watchlistImport"
class="mat-focus-indicator mat-stroked-button mat-button-base">
Run Watchlist Import
</button>
</div>
</div> </div>
</div> </div>
</mat-tab> </mat-tab>

View file

@ -172,6 +172,14 @@ export class PlexComponent implements OnInit, OnDestroy {
}); });
} }
public runWatchlistImport(): void {
this.jobService.runPlexWatchlistImport().subscribe(x => {
if (x) {
this.notificationService.success("Triggered the Watchlist Import");
}
});
}
public ngOnDestroy() { public ngOnDestroy() {
this.subscriptions.next(); this.subscriptions.next();
this.subscriptions.complete(); this.subscriptions.complete();

View file

@ -91,6 +91,17 @@ namespace Ombi.Controllers.V1
return true; return true;
} }
/// <summary>
/// Runs the Plex Watchlist Importer
/// </summary>
/// <returns></returns>
[HttpPost("plexwatchlist")]
public async Task<bool> PlexWatchlistImport()
{
await OmbiQuartz.TriggerJob(nameof(IPlexWatchlistImport), "Plex");
return true;
}
/// <summary> /// <summary>
/// Runs the Emby User importer /// Runs the Emby User importer
/// </summary> /// </summary>

View file

@ -626,6 +626,7 @@ namespace Ombi.Controllers.V1
j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j); j.MediaDatabaseRefresh = j.MediaDatabaseRefresh.HasValue() ? j.MediaDatabaseRefresh : JobSettingsHelper.MediaDatabaseRefresh(j);
j.AutoDeleteRequests = j.AutoDeleteRequests.HasValue() ? j.AutoDeleteRequests : JobSettingsHelper.AutoDeleteRequests(j); j.AutoDeleteRequests = j.AutoDeleteRequests.HasValue() ? j.AutoDeleteRequests : JobSettingsHelper.AutoDeleteRequests(j);
j.EmbyRecentlyAddedSync = j.EmbyRecentlyAddedSync.HasValue() ? j.EmbyRecentlyAddedSync : JobSettingsHelper.EmbyRecentlyAddedSync(j); j.EmbyRecentlyAddedSync = j.EmbyRecentlyAddedSync.HasValue() ? j.EmbyRecentlyAddedSync : JobSettingsHelper.EmbyRecentlyAddedSync(j);
j.PlexWatchlistImport = j.PlexWatchlistImport.HasValue() ? j.PlexWatchlistImport : JobSettingsHelper.PlexWatchlistImport(j);
return j; return j;
} }

View file

@ -6,19 +6,16 @@ using System.Security.Claims;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Ombi.Core.Authentication; using Ombi.Core.Authentication;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Models; using Ombi.Models;
using Ombi.Models.External; using Ombi.Models.External;
using Ombi.Models.Identity;
using Ombi.Store.Entities; using Ombi.Store.Entities;
using Ombi.Store.Repository; using Ombi.Store.Repository;
using Ombi.Core.Settings; using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models; using Ombi.Settings.Settings.Models;
using Ombi.Schedule.Jobs.Plex;
namespace Ombi.Controllers.V1 namespace Ombi.Controllers.V1
{ {
@ -27,26 +24,21 @@ namespace Ombi.Controllers.V1
[ApiController] [ApiController]
public class TokenController : ControllerBase public class TokenController : ControllerBase
{ {
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, ITokenRepository token, public TokenController(OmbiUserManager um, ITokenRepository token,
IPlexOAuthManager oAuthManager, ILogger<TokenController> logger, ISettingsService<AuthenticationSettings> auth, IPlexOAuthManager oAuthManager, ILogger<TokenController> logger, ISettingsService<AuthenticationSettings> auth)
IPlexWatchlistImport import)
{ {
_userManager = um; _userManager = um;
_tokenAuthenticationOptions = ta.Value;
_token = token; _token = token;
_plexOAuthManager = oAuthManager; _plexOAuthManager = oAuthManager;
_log = logger; _log = logger;
_authSettings = auth; _authSettings = auth;
_import = import;
} }
private readonly TokenAuthentication _tokenAuthenticationOptions;
private readonly ITokenRepository _token; private readonly ITokenRepository _token;
private readonly OmbiUserManager _userManager; private readonly OmbiUserManager _userManager;
private readonly IPlexOAuthManager _plexOAuthManager; private readonly IPlexOAuthManager _plexOAuthManager;
private readonly ILogger<TokenController> _log; private readonly ILogger<TokenController> _log;
private readonly ISettingsService<AuthenticationSettings> _authSettings; private readonly ISettingsService<AuthenticationSettings> _authSettings;
private readonly IPlexWatchlistImport _import;
/// <summary> /// <summary>
/// Gets the token. /// Gets the token.
@ -57,7 +49,6 @@ namespace Ombi.Controllers.V1
[ProducesResponseType(401)] [ProducesResponseType(401)]
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model) public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
{ {
await _import.Execute(null);
if (!model.UsePlexOAuth) if (!model.UsePlexOAuth)
{ {
var user = await _userManager.FindByNameAsync(model.Username); var user = await _userManager.FindByNameAsync(model.Username);
@ -122,6 +113,7 @@ namespace Ombi.Controllers.V1
{ {
return Unauthorized(); return Unauthorized();
} }
return await CreateToken(true, user); return await CreateToken(true, user);
} }