mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-21 05:43:19 -07:00
Merge pull request #4312 from Ombi-app/feature/request-limits
Feature/request limits
This commit is contained in:
commit
e302cf685f
38 changed files with 7726 additions and 222 deletions
527
src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs
Normal file
527
src/Ombi.Core.Tests/Engine/MovieRequestLimitsTests.cs
Normal file
|
@ -0,0 +1,527 @@
|
||||||
|
using MockQueryable.Moq;
|
||||||
|
using Moq;
|
||||||
|
using Moq.AutoMock;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
using Ombi.Core.Engine;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Ombi.Core.Services;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Tests.Engine
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class MovieRequestLimitsTests
|
||||||
|
{
|
||||||
|
|
||||||
|
private AutoMocker _mocker;
|
||||||
|
private RequestLimitService _subject;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
|
||||||
|
_mocker = new AutoMocker();
|
||||||
|
var principleMock = new Mock<IPrincipal>();
|
||||||
|
var identityMock = new Mock<IIdentity>();
|
||||||
|
identityMock.SetupGet(x => x.Name).Returns("Test");
|
||||||
|
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
|
||||||
|
_mocker.Use(principleMock.Object);
|
||||||
|
|
||||||
|
_subject = _mocker.CreateInstance<RequestLimitService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task User_No_MovieLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_UsernotExist_No_MovieLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_No_MovieLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST"
|
||||||
|
};
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_No_Requests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 1
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(new List<RequestLog>().AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = yesterday, // Yesterday
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(7))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Ignore("Failing on CI")]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_MultipleRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = yesterday.AddDays(-2),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate =yesterday.AddDays(-3), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate =yesterday.AddDays(-4), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate =yesterday.AddDays(-5), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate =yesterday.AddDays(-6), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate =yesterday.AddDays(-7), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = yesterday.AddDays(-8), // Yesterday
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Daily_NoRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Daily_OneRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Daily_AllRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today.AddHours(-2),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Weekly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.FirstDateInWeek().AddDays(-1); // Day before reset
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Weekly_OneRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.UtcNow;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Weekly_AllRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Monthly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.AddMonths(-1).AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Monthly_OneRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MovieLimit_Set_Limit_Monthly_AllRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MovieRequestLimit = 2,
|
||||||
|
MovieRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Movie,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMovieRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
527
src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs
Normal file
527
src/Ombi.Core.Tests/Engine/MusicRequestLimitTests.cs
Normal file
|
@ -0,0 +1,527 @@
|
||||||
|
using MockQueryable.Moq;
|
||||||
|
using Moq;
|
||||||
|
using Moq.AutoMock;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
using Ombi.Core.Engine;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Ombi.Core.Services;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Tests.Engine
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class MusicRequestLimitTests
|
||||||
|
{
|
||||||
|
|
||||||
|
private AutoMocker _mocker;
|
||||||
|
private RequestLimitService _subject;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-GB");
|
||||||
|
_mocker = new AutoMocker();
|
||||||
|
var principleMock = new Mock<IPrincipal>();
|
||||||
|
var identityMock = new Mock<IIdentity>();
|
||||||
|
identityMock.SetupGet(x => x.Name).Returns("Test");
|
||||||
|
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
|
||||||
|
_mocker.Use(principleMock.Object);
|
||||||
|
|
||||||
|
_subject = _mocker.CreateInstance<RequestLimitService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task User_No_MusicLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_UsernotExist_No_MusicLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_No_MusicLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST"
|
||||||
|
};
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_No_Requests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 1
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(new List<RequestLog>().AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = yesterday, // Yesterday
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(7))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Ignore("Failing on CI")]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_MultipleRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = yesterday.AddDays(-2),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate =yesterday.AddDays(-3), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate =yesterday.AddDays(-4), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate =yesterday.AddDays(-5), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate =yesterday.AddDays(-6), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate =yesterday.AddDays(-7), // Yesterday
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = yesterday.AddDays(-8), // Yesterday
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Daily_NoRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Daily_OneRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Daily_AllRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today.AddHours(-2),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Weekly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.FirstDateInWeek().AddDays(-1); // Day before reset
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Weekly_OneRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.UtcNow;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Weekly_AllRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.FirstDateInWeek().AddDays(7).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Monthly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.AddMonths(-1).AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Monthly_OneRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_MusicLimit_Set_Limit_Monthly_AllRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
MusicRequestLimit = 2,
|
||||||
|
MusicRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var firstDayOfMonth = new DateTime(today.Year, today.Month, 1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.Album,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingMusicRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(firstDayOfMonth.AddMonths(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
665
src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs
Normal file
665
src/Ombi.Core.Tests/Engine/TvRequestLimitsTests.cs
Normal file
|
@ -0,0 +1,665 @@
|
||||||
|
using MockQueryable.Moq;
|
||||||
|
using Moq;
|
||||||
|
using Moq.AutoMock;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
using Ombi.Core.Engine;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Ombi.Core.Services;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Tests.Engine
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class TvRequestLimitsTests
|
||||||
|
{
|
||||||
|
|
||||||
|
private AutoMocker _mocker;
|
||||||
|
private RequestLimitService _subject;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_mocker = new AutoMocker();
|
||||||
|
var principleMock = new Mock<IPrincipal>();
|
||||||
|
var identityMock = new Mock<IIdentity>();
|
||||||
|
identityMock.SetupGet(x => x.Name).Returns("Test");
|
||||||
|
principleMock.SetupGet(x => x.Identity).Returns(identityMock.Object);
|
||||||
|
_mocker.Use(principleMock.Object);
|
||||||
|
|
||||||
|
_subject = _mocker.CreateInstance<RequestLimitService>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task User_No_TvLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_UsernotExist_No_TvLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser();
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result, Is.Null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task No_UserPassedIn_No_TvLimit_Set()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST"
|
||||||
|
};
|
||||||
|
|
||||||
|
var um = _mocker.GetMock<OmbiUserManager>();
|
||||||
|
um.SetupGet(x => x.Users).Returns(new List<OmbiUser> { user }.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(null);
|
||||||
|
|
||||||
|
Assert.That(result.HasLimit, Is.False);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_No_Requests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 1
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(new List<RequestLog>().AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = yesterday, // Yesterday
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(7).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Ignore("Failing on CI")]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_MultipleRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = yesterday.AddDays(-2),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate =yesterday.AddDays(-3),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
EpisodeCount = 1,
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate =yesterday.AddDays(-4),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate =yesterday.AddDays(-5),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate =yesterday.AddDays(-6),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate =yesterday.AddDays(-7),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = yesterday.AddDays(-8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(yesterday.AddDays(1).Date)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Daily_NoRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var yesterday = DateTime.Now.AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = yesterday,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Daily_OneRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).AddHours(-1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Daily_AllRequestsToday()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
EpisodeCount = 1,
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = today.AddHours(-2),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).AddHours(-2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Daily_MultipleEpisodeRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 10,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Day,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today.AddHours(-1),
|
||||||
|
EpisodeCount = 5,
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 4,
|
||||||
|
RequestDate = today.AddHours(-2),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(10)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(1).AddHours(-2))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Weekly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.AddDays(-8);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Weekly_OneRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(7))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Weekly_AllRequestsWeek()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(6))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Weekly_MultipleEpisodeRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 10,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Week,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 5,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today,
|
||||||
|
EpisodeCount = 4,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(10)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddDays(6))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Monthly_NoRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var lastWeek = DateTime.Now.AddMonths(-1).AddDays(-1);
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = lastWeek,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(2)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Monthly_OneRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
RequestDate = today,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddMonths(1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Monthly_AllRequests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 2,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 1,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(2)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(0)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddMonths(1).AddDays(-1))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task UserPassedIn_TvLimit_Set_Limit_Monthly_MultipleEpisodeReuests()
|
||||||
|
{
|
||||||
|
var user = new OmbiUser
|
||||||
|
{
|
||||||
|
NormalizedUserName = "TEST",
|
||||||
|
EpisodeRequestLimit = 10,
|
||||||
|
EpisodeRequestLimitType = RequestLimitType.Month,
|
||||||
|
Id = "id1"
|
||||||
|
};
|
||||||
|
var today = DateTime.Now;
|
||||||
|
var log = new List<RequestLog>
|
||||||
|
{
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount =5,
|
||||||
|
RequestDate = today.AddDays(-1),
|
||||||
|
},
|
||||||
|
new RequestLog
|
||||||
|
{
|
||||||
|
UserId = "id1",
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
EpisodeCount = 4,
|
||||||
|
RequestDate = today,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
var repoMock = _mocker.GetMock<IRepository<RequestLog>>();
|
||||||
|
repoMock.Setup(x => x.GetAll()).Returns(log.AsQueryable().BuildMock().Object);
|
||||||
|
|
||||||
|
var result = await _subject.GetRemainingTvRequests(user);
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RequestQuotaCountModel>()
|
||||||
|
.With.Property(nameof(RequestQuotaCountModel.HasLimit)).EqualTo(true)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Limit)).EqualTo(10)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.Remaining)).EqualTo(1)
|
||||||
|
.And.Property(nameof(RequestQuotaCountModel.NextRequest)).EqualTo(today.AddMonths(1).AddDays(-1))
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,8 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoFixture" Version="4.11.0" />
|
<PackageReference Include="AutoFixture" Version="4.11.0" />
|
||||||
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="5.0.0" />
|
||||||
<PackageReference Include="Moq" Version="4.14.1" />
|
<PackageReference Include="Moq" Version="4.15.1" />
|
||||||
|
<PackageReference Include="Moq.AutoMock" Version="3.0.0" />
|
||||||
<PackageReference Include="Nunit" Version="3.12.0" />
|
<PackageReference Include="Nunit" Version="3.12.0" />
|
||||||
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
|
<PackageReference Include="NUnit.ConsoleRunner" Version="3.11.1" />
|
||||||
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
|
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1">
|
||||||
|
|
258
src/Ombi.Core.Tests/Rule/Request/RequestLimitRuleTests.cs
Normal file
258
src/Ombi.Core.Tests/Rule/Request/RequestLimitRuleTests.cs
Normal file
|
@ -0,0 +1,258 @@
|
||||||
|
using Moq;
|
||||||
|
using Moq.AutoMock;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Ombi.Core.Rule;
|
||||||
|
using Ombi.Core.Rule.Rules.Request;
|
||||||
|
using Ombi.Core.Services;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Tests.Rule.Request
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class RequestLimitRuleTests
|
||||||
|
{
|
||||||
|
private AutoMocker _mocker;
|
||||||
|
private RequestLimitRule _subject;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
_mocker = new AutoMocker();
|
||||||
|
_subject = _mocker.CreateInstance<RequestLimitRule>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task MovieRule_No_Limit()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = false
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Movie
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task MovieRule_Limit_NotReached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 2,
|
||||||
|
Remaining = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Movie
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task MovieRule_Limit_Reached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMovieRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 1,
|
||||||
|
Remaining = 0
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Movie
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
|
||||||
|
}
|
||||||
|
[Test]
|
||||||
|
public async Task MusicRule_No_Limit()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = false
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Album
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task MusicRule_Limit_NotReached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 2,
|
||||||
|
Remaining = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Album
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task MusicRule_Limit_Reached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingMusicRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 1,
|
||||||
|
Remaining = 0
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.Album
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TvRule_No_Limit()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = false
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new Store.Entities.Requests.BaseRequest
|
||||||
|
{
|
||||||
|
RequestType = RequestType.TvShow
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TvRule_Limit_NotReached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 2,
|
||||||
|
Remaining = 1
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new ChildRequests
|
||||||
|
{
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
SeasonRequests = new List<SeasonRequests>
|
||||||
|
{
|
||||||
|
new SeasonRequests
|
||||||
|
{
|
||||||
|
Episodes = new List<EpisodeRequests>
|
||||||
|
{
|
||||||
|
new EpisodeRequests()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TvRule_Limit_Reached()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 1,
|
||||||
|
Remaining = 0
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new ChildRequests
|
||||||
|
{
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
SeasonRequests = new List<SeasonRequests>
|
||||||
|
{
|
||||||
|
new SeasonRequests
|
||||||
|
{
|
||||||
|
Episodes = new List<EpisodeRequests>
|
||||||
|
{
|
||||||
|
new EpisodeRequests()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task TvRule_Limit_Reached_ManyEpisodes()
|
||||||
|
{
|
||||||
|
var limitService = _mocker.GetMock<IRequestLimitService>();
|
||||||
|
limitService.Setup(x => x.GetRemainingTvRequests(It.IsAny<OmbiUser>())).ReturnsAsync(new Models.RequestQuotaCountModel
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = 1,
|
||||||
|
Remaining = 5
|
||||||
|
});
|
||||||
|
|
||||||
|
var result = await _subject.Execute(new ChildRequests
|
||||||
|
{
|
||||||
|
RequestType = RequestType.TvShow,
|
||||||
|
SeasonRequests = new List<SeasonRequests>
|
||||||
|
{
|
||||||
|
new SeasonRequests
|
||||||
|
{
|
||||||
|
Episodes = new List<EpisodeRequests>
|
||||||
|
{
|
||||||
|
new EpisodeRequests(),
|
||||||
|
new EpisodeRequests(),
|
||||||
|
new EpisodeRequests(),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new SeasonRequests
|
||||||
|
{
|
||||||
|
Episodes = new List<EpisodeRequests>
|
||||||
|
{
|
||||||
|
new EpisodeRequests(),
|
||||||
|
new EpisodeRequests(),
|
||||||
|
new EpisodeRequests(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.That(result, Is.InstanceOf<RuleResult>().With.Property(nameof(RuleResult.Success)).EqualTo(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,7 +22,6 @@ namespace Ombi.Core.Engine
|
||||||
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
|
Task<RequestEngineResult> RequestAlbum(MusicAlbumRequestViewModel model);
|
||||||
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
|
Task<IEnumerable<AlbumRequest>> SearchAlbumRequest(string search);
|
||||||
Task<bool> UserHasRequest(string userId);
|
Task<bool> UserHasRequest(string userId);
|
||||||
Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null);
|
|
||||||
Task<RequestsViewModel<AlbumRequest>> GetRequestsByStatus(int count, int position, string sort, string sortOrder, RequestStatus available);
|
Task<RequestsViewModel<AlbumRequest>> GetRequestsByStatus(int count, int position, string sort, string sortOrder, RequestStatus available);
|
||||||
Task<RequestsViewModel<AlbumRequest>> GetRequests(int count, int position, string sort, string sortOrder);
|
Task<RequestsViewModel<AlbumRequest>> GetRequests(int count, int position, string sort, string sortOrder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
var username = Username.ToUpper();
|
var username = Username.ToUpper();
|
||||||
return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username));
|
return _user ??= await UserManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<string> UserAlias()
|
protected async Task<string> UserAlias()
|
||||||
|
|
|
@ -24,7 +24,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
Task<int> GetTotal();
|
Task<int> GetTotal();
|
||||||
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<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user = null);
|
|
||||||
Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken);
|
Task<RequestEngineResult> ReProcessRequest(int requestId, CancellationToken cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -566,7 +566,7 @@ namespace Ombi.Core.Engine
|
||||||
{
|
{
|
||||||
var langCode = await DefaultLanguageCode(null);
|
var langCode = await DefaultLanguageCode(null);
|
||||||
var collections = await Cache.GetOrAddAsync($"GetCollection{collectionId}{langCode}",
|
var collections = await Cache.GetOrAddAsync($"GetCollection{collectionId}{langCode}",
|
||||||
() => MovieApi.GetCollection(langCode, collectionId, cancellationToken), DateTimeOffset.Now.AddDays(1));
|
() => MovieApi.GetCollection(langCode, collectionId, cancellationToken), DateTimeOffset.Now.AddDays(1));
|
||||||
|
|
||||||
var results = new List<RequestEngineResult>();
|
var results = new List<RequestEngineResult>();
|
||||||
foreach (var collection in collections.parts)
|
foreach (var collection in collections.parts)
|
||||||
|
@ -583,7 +583,7 @@ namespace Ombi.Core.Engine
|
||||||
new RequestEngineResult { Result = false, ErrorMessage = $"The whole collection {collections.name} Is already monitored or requested!" };
|
new RequestEngineResult { Result = false, ErrorMessage = $"The whole collection {collections.name} Is already monitored or requested!" };
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId};
|
return new RequestEngineResult { Result = true, Message = $"The collection {collections.name} has been successfully added!", RequestId = results.FirstOrDefault().RequestId };
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<RequestEngineResult> ProcessSendingMovie(MovieRequests request)
|
private async Task<RequestEngineResult> ProcessSendingMovie(MovieRequests request)
|
||||||
|
@ -753,49 +753,5 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id };
|
return new RequestEngineResult { Result = true, Message = $"{movieName} has been successfully added!", RequestId = model.Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
user = await GetUser();
|
|
||||||
|
|
||||||
// If user is still null after attempting to get the logged in user, return null.
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int limit = user.MovieRequestLimit ?? 0;
|
|
||||||
|
|
||||||
if (limit <= 0)
|
|
||||||
{
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = false,
|
|
||||||
Limit = 0,
|
|
||||||
Remaining = 0,
|
|
||||||
NextRequest = DateTime.Now,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Movie);
|
|
||||||
|
|
||||||
int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
|
|
||||||
DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
|
|
||||||
.OrderBy(x => x.RequestDate)
|
|
||||||
.Select(x => x.RequestDate)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = true,
|
|
||||||
Limit = limit,
|
|
||||||
Remaining = count,
|
|
||||||
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -435,49 +435,6 @@ namespace Ombi.Core.Engine
|
||||||
Result = true
|
Result = true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
user = await GetUser();
|
|
||||||
|
|
||||||
// If user is still null after attempting to get the logged in user, return null.
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int limit = user.MusicRequestLimit ?? 0;
|
|
||||||
|
|
||||||
if (limit <= 0)
|
|
||||||
{
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = false,
|
|
||||||
Limit = 0,
|
|
||||||
Remaining = 0,
|
|
||||||
NextRequest = DateTime.Now,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Album);
|
|
||||||
|
|
||||||
int count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
|
|
||||||
DateTime oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
|
|
||||||
.OrderBy(x => x.RequestDate)
|
|
||||||
.Select(x => x.RequestDate)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = true,
|
|
||||||
Limit = limit,
|
|
||||||
Remaining = count,
|
|
||||||
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RequestEngineResult> MarkAvailable(int modelId)
|
public async Task<RequestEngineResult> MarkAvailable(int modelId)
|
||||||
{
|
{
|
||||||
|
|
|
@ -955,56 +955,7 @@ namespace Ombi.Core.Engine
|
||||||
return new RequestEngineResult { Result = true, RequestId = model.Id };
|
return new RequestEngineResult { Result = true, RequestId = model.Id };
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingRequests(OmbiUser user)
|
|
||||||
{
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
user = await GetUser();
|
|
||||||
|
|
||||||
// If user is still null after attempting to get the logged in user, return null.
|
|
||||||
if (user == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int limit = user.EpisodeRequestLimit ?? 0;
|
|
||||||
|
|
||||||
if (limit <= 0)
|
|
||||||
{
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = false,
|
|
||||||
Limit = 0,
|
|
||||||
Remaining = 0,
|
|
||||||
NextRequest = DateTime.Now,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
IQueryable<RequestLog> log = _requestLog.GetAll()
|
|
||||||
.Where(x => x.UserId == user.Id
|
|
||||||
&& x.RequestType == RequestType.TvShow
|
|
||||||
&& x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
|
|
||||||
// Needed, due to a bug which would cause all episode counts to be 0
|
|
||||||
int zeroEpisodeCount = await log.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
|
||||||
|
|
||||||
int episodeCount = await log.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
|
||||||
|
|
||||||
int count = limit - (zeroEpisodeCount + episodeCount);
|
|
||||||
|
|
||||||
DateTime oldestRequestedAt = await log.OrderBy(x => x.RequestDate)
|
|
||||||
.Select(x => x.RequestDate)
|
|
||||||
.FirstOrDefaultAsync();
|
|
||||||
|
|
||||||
return new RequestQuotaCountModel()
|
|
||||||
{
|
|
||||||
HasLimit = true,
|
|
||||||
Limit = limit,
|
|
||||||
Remaining = count,
|
|
||||||
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<RequestEngineResult> UpdateAdvancedOptions(MediaAdvancedOptions options)
|
public async Task<RequestEngineResult> UpdateAdvancedOptions(MediaAdvancedOptions options)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,6 +24,9 @@ namespace Ombi.Core.Models.UI
|
||||||
public RequestQuotaCountModel MusicRequestQuota { get; set; }
|
public RequestQuotaCountModel MusicRequestQuota { get; set; }
|
||||||
public int MusicRequestLimit { get; set; }
|
public int MusicRequestLimit { get; set; }
|
||||||
public UserQualityProfiles UserQualityProfiles { get; set; }
|
public UserQualityProfiles UserQualityProfiles { get; set; }
|
||||||
|
public RequestLimitType MovieRequestLimitType { get; set; }
|
||||||
|
public RequestLimitType MusicRequestLimitType { get; set; }
|
||||||
|
public RequestLimitType EpisodeRequestLimitType { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ClaimCheckboxes
|
public class ClaimCheckboxes
|
||||||
|
|
|
@ -31,6 +31,7 @@ using System.Threading.Tasks;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Rule.Interfaces;
|
using Ombi.Core.Rule.Interfaces;
|
||||||
|
using Ombi.Core.Services;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using Ombi.Store.Repository;
|
using Ombi.Store.Repository;
|
||||||
|
@ -39,45 +40,37 @@ namespace Ombi.Core.Rule.Rules.Request
|
||||||
{
|
{
|
||||||
public class RequestLimitRule : BaseRequestRule, IRules<BaseRequest>
|
public class RequestLimitRule : BaseRequestRule, IRules<BaseRequest>
|
||||||
{
|
{
|
||||||
public RequestLimitRule(IRepository<RequestLog> rl, OmbiUserManager um)
|
public RequestLimitRule(IRequestLimitService requestLimitService)
|
||||||
{
|
{
|
||||||
_requestLog = rl;
|
_requestLimitService = requestLimitService;
|
||||||
_userManager = um;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IRepository<RequestLog> _requestLog;
|
private readonly IRequestLimitService _requestLimitService;
|
||||||
private readonly OmbiUserManager _userManager;
|
|
||||||
|
|
||||||
public async Task<RuleResult> Execute(BaseRequest obj)
|
public async Task<RuleResult> Execute(BaseRequest obj)
|
||||||
{
|
{
|
||||||
var user = await _userManager.Users.FirstOrDefaultAsync(x => x.Id == obj.RequestedUserId);
|
|
||||||
|
|
||||||
var movieLimit = user.MovieRequestLimit;
|
|
||||||
var episodeLimit = user.EpisodeRequestLimit;
|
|
||||||
var musicLimit = user.MusicRequestLimit;
|
|
||||||
|
|
||||||
var requestLog = _requestLog.GetAll().Where(x => x.UserId == obj.RequestedUserId);
|
|
||||||
if (obj.RequestType == RequestType.Movie)
|
if (obj.RequestType == RequestType.Movie)
|
||||||
{
|
{
|
||||||
if (movieLimit <= 0)
|
var remainingLimitsModel = await _requestLimitService.GetRemainingMovieRequests();
|
||||||
|
if (!remainingLimitsModel.HasLimit)
|
||||||
|
{
|
||||||
return Success();
|
return Success();
|
||||||
|
}
|
||||||
|
|
||||||
var movieLogs = requestLog.Where(x => x.RequestType == RequestType.Movie);
|
if (remainingLimitsModel.Remaining < 1)
|
||||||
|
|
||||||
// Count how many requests in the past 7 days
|
|
||||||
var count = await movieLogs.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
count += 1; // Since we are including this request
|
|
||||||
if (count > movieLimit)
|
|
||||||
{
|
{
|
||||||
return Fail("You have exceeded your Movie request quota!");
|
return Fail("You have exceeded your Movie request quota!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (obj.RequestType == RequestType.TvShow)
|
if (obj.RequestType == RequestType.TvShow)
|
||||||
{
|
{
|
||||||
if (episodeLimit <= 0)
|
var remainingLimitsModel = await _requestLimitService.GetRemainingTvRequests();
|
||||||
|
if (!remainingLimitsModel.HasLimit)
|
||||||
|
{
|
||||||
return Success();
|
return Success();
|
||||||
|
}
|
||||||
|
|
||||||
var child = (ChildRequests) obj;
|
var child = (ChildRequests)obj;
|
||||||
var requestCount = 0;
|
var requestCount = 0;
|
||||||
// Get the count of requests to be made
|
// Get the count of requests to be made
|
||||||
foreach (var s in child.SeasonRequests)
|
foreach (var s in child.SeasonRequests)
|
||||||
|
@ -85,37 +78,25 @@ namespace Ombi.Core.Rule.Rules.Request
|
||||||
requestCount += s.Episodes.Count;
|
requestCount += s.Episodes.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tvLogs = requestLog.Where(x => x.RequestType == RequestType.TvShow);
|
if ((remainingLimitsModel.Remaining - requestCount) < 0)
|
||||||
|
|
||||||
// Count how many requests in the past 7 days
|
|
||||||
var tv = tvLogs.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
|
|
||||||
// Needed, due to a bug which would cause all episode counts to be 0
|
|
||||||
var zeroEpisodeCount = await tv.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
|
||||||
|
|
||||||
var episodeCount = await tv.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
|
||||||
|
|
||||||
var count = requestCount + episodeCount + zeroEpisodeCount; // Add the amount of requests in
|
|
||||||
if (count > episodeLimit)
|
|
||||||
{
|
{
|
||||||
return Fail("You have exceeded your Episode request quota!");
|
return Fail("You have exceeded your Episode request quota!");
|
||||||
}
|
}
|
||||||
} else if (obj.RequestType == RequestType.Album)
|
}
|
||||||
|
if (obj.RequestType == RequestType.Album)
|
||||||
{
|
{
|
||||||
if (musicLimit <= 0)
|
var remainingLimitsModel = await _requestLimitService.GetRemainingMusicRequests();
|
||||||
|
if (!remainingLimitsModel.HasLimit)
|
||||||
|
{
|
||||||
return Success();
|
return Success();
|
||||||
|
}
|
||||||
|
|
||||||
var albumLogs = requestLog.Where(x => x.RequestType == RequestType.Album);
|
if (remainingLimitsModel.Remaining < 1)
|
||||||
|
|
||||||
// Count how many requests in the past 7 days
|
|
||||||
var count = await albumLogs.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
|
||||||
count += 1; // Since we are including this request
|
|
||||||
if (count > musicLimit)
|
|
||||||
{
|
{
|
||||||
return Fail("You have exceeded your Album request quota!");
|
return Fail("You have exceeded your Album request quota!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Success();
|
return Success();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
303
src/Ombi.Core/Services/RequestLimitService.cs
Normal file
303
src/Ombi.Core/Services/RequestLimitService.cs
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
using Ombi.Core.Engine.Interfaces;
|
||||||
|
using Ombi.Core.Models;
|
||||||
|
using Ombi.Core.Rule.Interfaces;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Services
|
||||||
|
{
|
||||||
|
public interface IRequestLimitService
|
||||||
|
{
|
||||||
|
Task<RequestQuotaCountModel> GetRemainingMovieRequests(OmbiUser user = default);
|
||||||
|
Task<RequestQuotaCountModel> GetRemainingTvRequests(OmbiUser user = default);
|
||||||
|
Task<RequestQuotaCountModel> GetRemainingMusicRequests(OmbiUser user = default);
|
||||||
|
}
|
||||||
|
public class RequestLimitService : IRequestLimitService
|
||||||
|
{
|
||||||
|
private readonly IPrincipal _user;
|
||||||
|
private readonly OmbiUserManager _userManager;
|
||||||
|
private readonly IRepository<RequestLog> _requestLog;
|
||||||
|
|
||||||
|
public RequestLimitService(IPrincipal user, OmbiUserManager userManager, IRepository<RequestLog> rl)
|
||||||
|
{
|
||||||
|
_user = user;
|
||||||
|
_userManager = userManager;
|
||||||
|
_requestLog = rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestQuotaCountModel> GetRemainingMovieRequests(OmbiUser user)
|
||||||
|
{
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = await GetUser();
|
||||||
|
|
||||||
|
// If user is still null after attempting to get the logged in user, return null.
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int limit = user.MovieRequestLimit ?? 0;
|
||||||
|
|
||||||
|
if (limit <= 0)
|
||||||
|
{
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = false,
|
||||||
|
Limit = 0,
|
||||||
|
Remaining = 0,
|
||||||
|
NextRequest = DateTime.Now,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Movie);
|
||||||
|
|
||||||
|
if (!user.MovieRequestLimitType.HasValue)
|
||||||
|
{
|
||||||
|
var count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
||||||
|
|
||||||
|
var oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = limit,
|
||||||
|
Remaining = count < 0 ? 0 : count,
|
||||||
|
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return await CalculateBasicRemaingRequests(user, limit, user.MovieRequestLimitType ?? RequestLimitType.Day, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestQuotaCountModel> GetRemainingMusicRequests(OmbiUser user)
|
||||||
|
{
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = await GetUser();
|
||||||
|
|
||||||
|
// If user is still null after attempting to get the logged in user, return null.
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int limit = user.MusicRequestLimit ?? 0;
|
||||||
|
|
||||||
|
if (limit <= 0)
|
||||||
|
{
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = false,
|
||||||
|
Limit = 0,
|
||||||
|
Remaining = 0,
|
||||||
|
NextRequest = DateTime.Now,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.Album);
|
||||||
|
|
||||||
|
// Hisoric Limits
|
||||||
|
if (!user.MusicRequestLimitType.HasValue)
|
||||||
|
{
|
||||||
|
var oldcount = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
||||||
|
|
||||||
|
var oldestRequestedAtOld = await log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = limit,
|
||||||
|
Remaining = oldcount < 0 ? 0 : oldcount,
|
||||||
|
NextRequest = DateTime.SpecifyKind(oldestRequestedAtOld.AddDays(7), DateTimeKind.Utc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return await CalculateBasicRemaingRequests(user, limit, user.MusicRequestLimitType ?? RequestLimitType.Day, log);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<OmbiUser> GetUser()
|
||||||
|
{
|
||||||
|
var username = _user.Identity.Name.ToUpper();
|
||||||
|
return await _userManager.Users.FirstOrDefaultAsync(x => x.NormalizedUserName == username);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<RequestQuotaCountModel> CalculateBasicRemaingRequests(OmbiUser user, int limit, RequestLimitType type, IQueryable<RequestLog> log)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
DateTime oldestRequestedAt = DateTime.Now;
|
||||||
|
DateTime nextRequest = DateTime.Now;
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case RequestLimitType.Day:
|
||||||
|
count = limit - await log.CountAsync(x => x.RequestDate >= DateTime.UtcNow.Date);
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date)
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = oldestRequestedAt.AddDays(1).Date;
|
||||||
|
break;
|
||||||
|
case RequestLimitType.Week:
|
||||||
|
var fdow = DateTime.UtcNow.FirstDateInWeek();
|
||||||
|
count = limit - await log.CountAsync(x => x.RequestDate >= fdow);
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= fdow)
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = fdow.AddDays(7).Date;
|
||||||
|
break;
|
||||||
|
case RequestLimitType.Month:
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
var firstDayOfMonth = new DateTime(now.Year, now.Month, 1);
|
||||||
|
count = limit - await log.CountAsync(x => x.RequestDate >= firstDayOfMonth);
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= firstDayOfMonth)
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = firstDayOfMonth.AddMonths(1).Date;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = limit,
|
||||||
|
Remaining = count < 0 ? 0 : count,
|
||||||
|
NextRequest = DateTime.SpecifyKind(nextRequest, DateTimeKind.Utc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<RequestQuotaCountModel> GetRemainingTvRequests(OmbiUser user)
|
||||||
|
{
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
user = await GetUser();
|
||||||
|
|
||||||
|
// If user is still null after attempting to get the logged in user, return null.
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int limit = user.EpisodeRequestLimit ?? 0;
|
||||||
|
|
||||||
|
if (limit <= 0)
|
||||||
|
{
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = false,
|
||||||
|
Limit = 0,
|
||||||
|
Remaining = 0,
|
||||||
|
NextRequest = DateTime.Now,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
IQueryable<RequestLog> log = _requestLog.GetAll().Where(x => x.UserId == user.Id && x.RequestType == RequestType.TvShow);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
DateTime oldestRequestedAt = DateTime.Now;
|
||||||
|
DateTime nextRequest = DateTime.Now;
|
||||||
|
|
||||||
|
|
||||||
|
IQueryable<RequestLog> filteredLog;
|
||||||
|
int zeroEpisodeCount;
|
||||||
|
int episodeCount;
|
||||||
|
|
||||||
|
if (!user.EpisodeRequestLimitType.HasValue)
|
||||||
|
{
|
||||||
|
filteredLog = log.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7));
|
||||||
|
// Needed, due to a bug which would cause all episode counts to be 0
|
||||||
|
zeroEpisodeCount = await filteredLog.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
||||||
|
|
||||||
|
episodeCount = await filteredLog.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
||||||
|
|
||||||
|
count = limit - (zeroEpisodeCount + episodeCount);
|
||||||
|
|
||||||
|
oldestRequestedAt = await log
|
||||||
|
.Where(x => x.RequestDate >= DateTime.UtcNow.AddDays(-7))
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = limit,
|
||||||
|
Remaining = count < 0 ? 0 : count,
|
||||||
|
NextRequest = DateTime.SpecifyKind(oldestRequestedAt.AddDays(7), DateTimeKind.Utc).Date,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (user.EpisodeRequestLimitType)
|
||||||
|
{
|
||||||
|
case RequestLimitType.Day:
|
||||||
|
|
||||||
|
filteredLog = log.Where(x => x.RequestDate >= DateTime.UtcNow.Date);
|
||||||
|
// Needed, due to a bug which would cause all episode counts to be 0
|
||||||
|
zeroEpisodeCount = await filteredLog.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
||||||
|
episodeCount = await filteredLog.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
||||||
|
count = limit - (zeroEpisodeCount + episodeCount);
|
||||||
|
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date)
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = oldestRequestedAt.AddDays(1);
|
||||||
|
break;
|
||||||
|
case RequestLimitType.Week:
|
||||||
|
|
||||||
|
filteredLog = log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddDays(-7));
|
||||||
|
// Needed, due to a bug which would cause all episode counts to be 0
|
||||||
|
zeroEpisodeCount = await filteredLog.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
||||||
|
episodeCount = await filteredLog.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
||||||
|
count = limit - (zeroEpisodeCount + episodeCount);
|
||||||
|
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddDays(-7))
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = oldestRequestedAt.AddDays(7);
|
||||||
|
break;
|
||||||
|
case RequestLimitType.Month:
|
||||||
|
filteredLog = log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddMonths(-1));
|
||||||
|
// Needed, due to a bug which would cause all episode counts to be 0
|
||||||
|
zeroEpisodeCount = await filteredLog.Where(x => x.EpisodeCount == 0).Select(x => x.EpisodeCount).CountAsync();
|
||||||
|
episodeCount = await filteredLog.Where(x => x.EpisodeCount != 0).Select(x => x.EpisodeCount).SumAsync();
|
||||||
|
count = limit - (zeroEpisodeCount + episodeCount);
|
||||||
|
|
||||||
|
oldestRequestedAt = await log.Where(x => x.RequestDate >= DateTime.UtcNow.Date.AddMonths(-1))
|
||||||
|
.OrderBy(x => x.RequestDate)
|
||||||
|
.Select(x => x.RequestDate)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
nextRequest = oldestRequestedAt.AddMonths(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new RequestQuotaCountModel()
|
||||||
|
{
|
||||||
|
HasLimit = true,
|
||||||
|
Limit = limit,
|
||||||
|
Remaining = count < 0 ? 0 : count,
|
||||||
|
NextRequest = DateTime.SpecifyKind(nextRequest, DateTimeKind.Utc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -69,6 +69,7 @@ using Ombi.Api.CloudService;
|
||||||
using Ombi.Api.RottenTomatoes;
|
using Ombi.Api.RottenTomatoes;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Core.Services;
|
||||||
|
|
||||||
namespace Ombi.DependencyInjection
|
namespace Ombi.DependencyInjection
|
||||||
{
|
{
|
||||||
|
@ -80,10 +81,10 @@ namespace Ombi.DependencyInjection
|
||||||
services.RegisterEngines();
|
services.RegisterEngines();
|
||||||
services.RegisterEnginesV2();
|
services.RegisterEnginesV2();
|
||||||
services.RegisterApi();
|
services.RegisterApi();
|
||||||
|
services.RegisterHttp();
|
||||||
services.RegisterServices();
|
services.RegisterServices();
|
||||||
services.RegisterStore();
|
services.RegisterStore();
|
||||||
services.RegisterJobs();
|
services.RegisterJobs();
|
||||||
services.RegisterHttp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterEngines(this IServiceCollection services)
|
public static void RegisterEngines(this IServiceCollection services)
|
||||||
|
@ -174,7 +175,8 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IRottenTomatoesApi, RottenTomatoesApi>();
|
services.AddTransient<IRottenTomatoesApi, RottenTomatoesApi>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterStore(this IServiceCollection services) {
|
public static void RegisterStore(this IServiceCollection services)
|
||||||
|
{
|
||||||
//services.AddDbContext<OmbiContext>();
|
//services.AddDbContext<OmbiContext>();
|
||||||
//services.AddDbContext<SettingsContext>();
|
//services.AddDbContext<SettingsContext>();
|
||||||
//services.AddDbContext<ExternalContext>();
|
//services.AddDbContext<ExternalContext>();
|
||||||
|
@ -208,6 +210,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddSingleton<ICacheService, CacheService>();
|
services.AddSingleton<ICacheService, CacheService>();
|
||||||
services.AddSingleton<IMediaCacheService, MediaCacheService>();
|
services.AddSingleton<IMediaCacheService, MediaCacheService>();
|
||||||
services.AddScoped<IImageService, ImageService>();
|
services.AddScoped<IImageService, ImageService>();
|
||||||
|
services.AddScoped<IRequestLimitService, RequestLimitService>();
|
||||||
|
|
||||||
services.AddTransient<IDiscordNotification, DiscordNotification>();
|
services.AddTransient<IDiscordNotification, DiscordNotification>();
|
||||||
services.AddTransient<IEmailNotification, EmailNotification>();
|
services.AddTransient<IEmailNotification, EmailNotification>();
|
||||||
|
|
40
src/Ombi.Helpers.Tests/DateTimeExtensionsTests.cs
Normal file
40
src/Ombi.Helpers.Tests/DateTimeExtensionsTests.cs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NUnit.Framework.Internal;
|
||||||
|
|
||||||
|
namespace Ombi.Helpers.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class DateTimeExtensionsTests
|
||||||
|
{
|
||||||
|
[TestCaseSource(nameof(DayOfWeekData))]
|
||||||
|
public DateTime FirstDateInWeekTests(DateTime input, string culture)
|
||||||
|
{
|
||||||
|
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(culture);
|
||||||
|
return input.FirstDateInWeek();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<TestCaseData> DayOfWeekData
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 20), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Monday, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 21), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Tuesday, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 22), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Wednesday, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 23), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Thursday, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 24), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Friday, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 25), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Sat, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 26), "en-GB").Returns(new DateTime(2021, 09, 20)).SetName("en-GB Sun, FDOW is Monday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 20), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Monday, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 21), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Tuesday, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 22), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Wednesday, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 23), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Thursday, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 24), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Friday, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 25), "en-US").Returns(new DateTime(2021, 09, 19)).SetName("en-US Sat, FDOW is Sunday");
|
||||||
|
yield return new TestCaseData(new DateTime(2021, 09, 26), "en-US").Returns(new DateTime(2021, 09, 26)).SetName("en-US Sun, FDOW is Sunday");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/Ombi.Helpers/DateTimeExtensions.cs
Normal file
18
src/Ombi.Helpers/DateTimeExtensions.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Ombi.Helpers
|
||||||
|
{
|
||||||
|
public static class DateTimeExtensions
|
||||||
|
{
|
||||||
|
public static DateTime FirstDateInWeek(this DateTime dt)
|
||||||
|
{
|
||||||
|
while (dt.DayOfWeek != Thread.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek)
|
||||||
|
{
|
||||||
|
dt = dt.AddDays(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ namespace Ombi.Helpers
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not in the cache, so add this Key into our MediaServiceCache
|
// Not in the cache, so add this Key into our MediaServiceCache
|
||||||
await UpdateLocalCache(cacheKey);
|
UpdateLocalCache(cacheKey);
|
||||||
|
|
||||||
return await _memoryCache.GetOrCreateAsync<T>(cacheKey, entry =>
|
return await _memoryCache.GetOrCreateAsync<T>(cacheKey, entry =>
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,7 @@ namespace Ombi.Helpers
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task UpdateLocalCache(string cacheKey)
|
private void UpdateLocalCache(string cacheKey)
|
||||||
{
|
{
|
||||||
var mediaServiceCache = _memoryCache.Get<List<string>>(CacheKey);
|
var mediaServiceCache = _memoryCache.Get<List<string>>(CacheKey);
|
||||||
if (mediaServiceCache == null)
|
if (mediaServiceCache == null)
|
||||||
|
|
|
@ -31,6 +31,10 @@ namespace Ombi.Store.Entities
|
||||||
public int? EpisodeRequestLimit { get; set; }
|
public int? EpisodeRequestLimit { get; set; }
|
||||||
public int? MusicRequestLimit { get; set; }
|
public int? MusicRequestLimit { get; set; }
|
||||||
|
|
||||||
|
public RequestLimitType? MovieRequestLimitType { get; set; }
|
||||||
|
public RequestLimitType? EpisodeRequestLimitType { get; set; }
|
||||||
|
public RequestLimitType? MusicRequestLimitType { get; set; }
|
||||||
|
|
||||||
public string UserAccessToken { get; set; }
|
public string UserAccessToken { get; set; }
|
||||||
|
|
||||||
public List<NotificationUserId> NotificationUserIds { get; set; }
|
public List<NotificationUserId> NotificationUserIds { get; set; }
|
||||||
|
@ -69,4 +73,11 @@ namespace Ombi.Store.Entities
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum RequestLimitType
|
||||||
|
{
|
||||||
|
Day = 0,
|
||||||
|
Week = 1,
|
||||||
|
Month = 2,
|
||||||
|
}
|
||||||
}
|
}
|
1253
src/Ombi.Store/Migrations/OmbiMySql/20210921200723_UserRequestLimits.Designer.cs
generated
Normal file
1253
src/Ombi.Store/Migrations/OmbiMySql/20210921200723_UserRequestLimits.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,73 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.OmbiMySql
|
||||||
|
{
|
||||||
|
public partial class UserRequestLimits : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1244
src/Ombi.Store/Migrations/OmbiMySql/20210922091445_UserRequestLimits_Pt2.Designer.cs
generated
Normal file
1244
src/Ombi.Store/Migrations/OmbiMySql/20210922091445_UserRequestLimits_Pt2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,43 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.OmbiMySql
|
||||||
|
{
|
||||||
|
public partial class UserRequestLimits_Pt2 : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -266,6 +266,9 @@ namespace Ombi.Store.Migrations.OmbiMySql
|
||||||
b.Property<int?>("EpisodeRequestLimit")
|
b.Property<int?>("EpisodeRequestLimit")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimitType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<string>("Language")
|
b.Property<string>("Language")
|
||||||
.HasColumnType("longtext");
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
@ -281,9 +284,15 @@ namespace Ombi.Store.Migrations.OmbiMySql
|
||||||
b.Property<int?>("MovieRequestLimit")
|
b.Property<int?>("MovieRequestLimit")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimitType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<int?>("MusicRequestLimit")
|
b.Property<int?>("MusicRequestLimit")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("MusicRequestLimitType")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
b.Property<string>("NormalizedEmail")
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("varchar(256)");
|
.HasColumnType("varchar(256)");
|
||||||
|
|
1252
src/Ombi.Store/Migrations/OmbiSqlite/20210921195729_UserRequestLimits.Designer.cs
generated
Normal file
1252
src/Ombi.Store/Migrations/OmbiSqlite/20210921195729_UserRequestLimits.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,73 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.OmbiSqlite
|
||||||
|
{
|
||||||
|
public partial class UserRequestLimits : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitType",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitType",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1243
src/Ombi.Store/Migrations/OmbiSqlite/20210922091550_UserRequestLimits_Pt2.Designer.cs
generated
Normal file
1243
src/Ombi.Store/Migrations/OmbiSqlite/20210922091550_UserRequestLimits_Pt2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,43 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations.OmbiSqlite
|
||||||
|
{
|
||||||
|
public partial class UserRequestLimits_Pt2 : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MovieRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "MusicRequestLimitAmount",
|
||||||
|
table: "AspNetUsers",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -265,6 +265,9 @@ namespace Ombi.Store.Migrations.OmbiSqlite
|
||||||
b.Property<int?>("EpisodeRequestLimit")
|
b.Property<int?>("EpisodeRequestLimit")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimitType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("Language")
|
b.Property<string>("Language")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
@ -280,9 +283,15 @@ namespace Ombi.Store.Migrations.OmbiSqlite
|
||||||
b.Property<int?>("MovieRequestLimit")
|
b.Property<int?>("MovieRequestLimit")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimitType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<int?>("MusicRequestLimit")
|
b.Property<int?>("MusicRequestLimit")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int?>("MusicRequestLimitType")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b.Property<string>("NormalizedEmail")
|
b.Property<string>("NormalizedEmail")
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
3
src/Ombi/.vscode/settings.json
vendored
3
src/Ombi/.vscode/settings.json
vendored
|
@ -12,6 +12,7 @@
|
||||||
],
|
],
|
||||||
"discord.enabled": true,
|
"discord.enabled": true,
|
||||||
"conventionalCommits.scopes": [
|
"conventionalCommits.scopes": [
|
||||||
"discover"
|
"discover",
|
||||||
|
"request-limits"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,12 +20,23 @@ export interface IUser {
|
||||||
userQualityProfiles: IUserQualityProfiles;
|
userQualityProfiles: IUserQualityProfiles;
|
||||||
streamingCountry: string;
|
streamingCountry: string;
|
||||||
|
|
||||||
|
movieRequestLimitType?: RequestLimitType;
|
||||||
|
episodeRequestLimitType?: RequestLimitType;
|
||||||
|
musicRequestLimitType?: RequestLimitType;
|
||||||
|
|
||||||
// FOR UI
|
// FOR UI
|
||||||
episodeRequestQuota: IRemainingRequests | null;
|
episodeRequestQuota: IRemainingRequests | null;
|
||||||
movieRequestQuota: IRemainingRequests | null;
|
movieRequestQuota: IRemainingRequests | null;
|
||||||
musicRequestQuota: IRemainingRequests | null;
|
musicRequestQuota: IRemainingRequests | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RequestLimitType
|
||||||
|
{
|
||||||
|
Day = 0,
|
||||||
|
Week = 1,
|
||||||
|
Month = 2,
|
||||||
|
}
|
||||||
|
|
||||||
export interface IUserDropdown {
|
export interface IUserDropdown {
|
||||||
username: string;
|
username: string;
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { Component, Input, OnInit } from "@angular/core";
|
import { Component, Input, OnInit } from "@angular/core";
|
||||||
import { TranslateService } from "@ngx-translate/core";
|
|
||||||
import { RequestType } from "../../interfaces";
|
|
||||||
import { IRemainingRequests } from "../../interfaces/IRemainingRequests";
|
import { IRemainingRequests } from "../../interfaces/IRemainingRequests";
|
||||||
import { RequestService } from "../../services";
|
import { RequestService } from "../../services";
|
||||||
|
import { RequestType } from "../../interfaces";
|
||||||
|
import { TranslateService } from "@ngx-translate/core";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-remaining-requests",
|
selector: "app-remaining-requests",
|
||||||
templateUrl: "remaining-requests.component.html",
|
templateUrl: "remaining-requests.component.html",
|
||||||
|
@ -43,7 +45,7 @@ export class RemainingRequestsComponent implements OnInit {
|
||||||
|
|
||||||
private start() {
|
private start() {
|
||||||
|
|
||||||
const callback = (remaining => {
|
const callback = ((remaining: IRemainingRequests) => {
|
||||||
this.remaining = remaining;
|
this.remaining = remaining;
|
||||||
if (this.remaining && this.remaining.hasLimit) {
|
if (this.remaining && this.remaining.hasLimit) {
|
||||||
this.calculateTime();
|
this.calculateTime();
|
||||||
|
|
|
@ -42,21 +42,51 @@
|
||||||
|
|
||||||
<div class="col-md-3 col-sm-12">
|
<div class="col-md-3 col-sm-12">
|
||||||
<label class="control-label"><h3>Request Limits</h3></label>
|
<label class="control-label"><h3>Request Limits</h3></label>
|
||||||
<div>
|
<div class="row">
|
||||||
<mat-form-field>
|
<div class="col-6">
|
||||||
<input id="movieRequestLimit" matInput placeholder="Movie Request Limit" [(ngModel)]="user.movieRequestLimit">
|
<mat-form-field>
|
||||||
</mat-form-field>
|
<input id="movieRequestLimit" matInput placeholder="Movie Request Limit" [(ngModel)]="user.movieRequestLimit">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<mat-label>Movie Request Limit Type</mat-label>
|
||||||
|
<mat-select [(value)]="user.movieRequestLimitType">
|
||||||
|
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||||
|
{{RequestLimitType[value]}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="row">
|
||||||
<mat-form-field>
|
<div class="col-6">
|
||||||
<input id="episodeRequestLimit" matInput placeholder="Episode Request Limit" [(ngModel)]="user.episodeRequestLimit">
|
<mat-form-field>
|
||||||
</mat-form-field>
|
<input id="episodeRequestLimit" matInput placeholder="Episode Request Limit" [(ngModel)]="user.episodeRequestLimit">
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<mat-label>Episode Request Limit Type</mat-label>
|
||||||
|
<mat-select [(value)]="user.episodeRequestLimitType">
|
||||||
|
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||||
|
{{RequestLimitType[value]}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="row">
|
||||||
|
<div class="col-6">
|
||||||
<mat-form-field>
|
<mat-form-field>
|
||||||
<input id="musicRequestLimit" matInput placeholder="Music Request Limit" [(ngModel)]="user.musicRequestLimit">
|
<input id="musicRequestLimit" matInput placeholder="Music Request Limit" [(ngModel)]="user.musicRequestLimit">
|
||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<mat-label>Music Request Limit Type</mat-label>
|
||||||
|
<mat-select [(value)]="user.musicRequestLimitType">
|
||||||
|
<mat-option *ngFor="let value of requestLimitTypes" [value]="value">
|
||||||
|
{{RequestLimitType[value]}}
|
||||||
|
</mat-option>
|
||||||
|
</mat-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<label class="control-label"><h3>Quality & Root Path Preferences</h3></label>
|
<label class="control-label"><h3>Quality & Root Path Preferences</h3></label>
|
||||||
<mat-form-field *ngIf="sonarrQualities">
|
<mat-form-field *ngIf="sonarrQualities">
|
||||||
<mat-label>Sonarr Quality Profile</mat-label>
|
<mat-label>Sonarr Quality Profile</mat-label>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
import { ICheckbox, ICustomizationSettings, INotificationAgent, INotificationPreferences, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, IUser, UserType } from "../interfaces";
|
import { ICheckbox, ICustomizationSettings, INotificationAgent, INotificationPreferences, IRadarrProfile, IRadarrRootFolder, ISonarrProfile, ISonarrRootFolder, IUser, RequestLimitType, UserType } from "../interfaces";
|
||||||
import { IdentityService, MessageService, RadarrService, SettingsService, SonarrService } from "../services";
|
import { IdentityService, MessageService, RadarrService, SettingsService, SonarrService } from "../services";
|
||||||
|
|
||||||
import { Clipboard } from '@angular/cdk/clipboard';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
|
@ -27,6 +27,8 @@ export class UserManagementUserComponent implements OnInit {
|
||||||
public edit: boolean;
|
public edit: boolean;
|
||||||
|
|
||||||
public countries: string[];
|
public countries: string[];
|
||||||
|
public requestLimitTypes: RequestLimitType[];
|
||||||
|
public RequestLimitType = RequestLimitType;
|
||||||
|
|
||||||
private customization: ICustomizationSettings;
|
private customization: ICustomizationSettings;
|
||||||
private accessToken: string;
|
private accessToken: string;
|
||||||
|
@ -53,7 +55,7 @@ export class UserManagementUserComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
|
this.requestLimitTypes = [RequestLimitType.Day, RequestLimitType.Week, RequestLimitType.Month];
|
||||||
this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x);
|
this.identityService.getSupportedStreamingCountries().subscribe(x => this.countries = x);
|
||||||
this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x);
|
this.identityService.getAllAvailableClaims().subscribe(x => this.availableClaims = x);
|
||||||
if(this.edit) {
|
if(this.edit) {
|
||||||
|
|
|
@ -61,13 +61,13 @@
|
||||||
<th mat-header-cell *matHeaderCellDef> Next Request Due </th>
|
<th mat-header-cell *matHeaderCellDef> Next Request Due </th>
|
||||||
<td mat-cell *matCellDef="let u">
|
<td mat-cell *matCellDef="let u">
|
||||||
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.remaining != u.movieRequestLimit">
|
<div *ngIf="u.movieRequestQuota != null && u.movieRequestQuota.remaining != u.movieRequestLimit">
|
||||||
{{'UserManagment.MovieDue' | translate: {date: (u.movieRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }}
|
{{'UserManagment.MovieDue' | translate: {date: (u.movieRequestQuota.nextRequest | amLocal | amDateFormat: 'l')} }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.remaining != u.episodeRequestLimit">
|
<div *ngIf="u.episodeRequestQuota != null && u.episodeRequestQuota.remaining != u.episodeRequestLimit">
|
||||||
{{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }}
|
{{'UserManagment.TvDue' | translate: {date: (u.episodeRequestQuota.nextRequest | amLocal | amDateFormat: 'l')} }}
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.remaining != u.musicRequestLimit">
|
<div *ngIf="u.musicRequestQuota != null && u.musicRequestQuota.remaining != u.musicRequestLimit">
|
||||||
{{'UserManagment.MusicDue' | translate: {date: (u.musicRequestQuota.nextRequest | amLocal | amDateFormat: 'l LT')} }}
|
{{'UserManagment.MusicDue' | translate: {date: (u.musicRequestQuota.nextRequest | amLocal | amDateFormat: 'l')} }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -75,7 +75,7 @@
|
||||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Last Logged In </th>
|
<th mat-header-cell *matHeaderCellDef mat-sort-header> Last Logged In </th>
|
||||||
<td mat-cell *matCellDef="let u">
|
<td mat-cell *matCellDef="let u">
|
||||||
<span *ngIf="u.lastLoggedIn">
|
<span *ngIf="u.lastLoggedIn">
|
||||||
{{u.lastLoggedIn | amLocal | amDateFormat: 'l LT'}}
|
{{u.lastLoggedIn | amFromUtc | amLocal | amDateFormat: 'l LT'}}
|
||||||
</span>
|
</span>
|
||||||
<span *ngIf="!u.lastLoggedIn">
|
<span *ngIf="!u.lastLoggedIn">
|
||||||
Not logged in yet!
|
Not logged in yet!
|
||||||
|
|
|
@ -17,6 +17,7 @@ using Ombi.Core.Engine;
|
||||||
using Ombi.Core.Engine.Interfaces;
|
using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Helpers;
|
using Ombi.Core.Helpers;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
|
using Ombi.Core.Services;
|
||||||
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;
|
||||||
|
@ -68,6 +69,7 @@ namespace Ombi.Controllers.V1
|
||||||
ITvRequestEngine tvRequestEngine,
|
ITvRequestEngine tvRequestEngine,
|
||||||
IMusicRequestEngine musicEngine,
|
IMusicRequestEngine musicEngine,
|
||||||
IUserDeletionEngine deletionEngine,
|
IUserDeletionEngine deletionEngine,
|
||||||
|
IRequestLimitService requestLimitService,
|
||||||
ICacheService cacheService)
|
ICacheService cacheService)
|
||||||
{
|
{
|
||||||
UserManager = user;
|
UserManager = user;
|
||||||
|
@ -96,11 +98,13 @@ namespace Ombi.Controllers.V1
|
||||||
_userQualityProfiles = userProfiles;
|
_userQualityProfiles = userProfiles;
|
||||||
MusicRequestEngine = musicEngine;
|
MusicRequestEngine = musicEngine;
|
||||||
_deletionEngine = deletionEngine;
|
_deletionEngine = deletionEngine;
|
||||||
|
_requestLimitService = requestLimitService;
|
||||||
_cacheService = cacheService;
|
_cacheService = cacheService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private OmbiUserManager UserManager { get; }
|
private OmbiUserManager UserManager { get; }
|
||||||
private readonly IUserDeletionEngine _deletionEngine;
|
private readonly IUserDeletionEngine _deletionEngine;
|
||||||
|
private readonly IRequestLimitService _requestLimitService;
|
||||||
private readonly ICacheService _cacheService;
|
private readonly ICacheService _cacheService;
|
||||||
|
|
||||||
private RoleManager<IdentityRole> RoleManager { get; }
|
private RoleManager<IdentityRole> RoleManager { get; }
|
||||||
|
@ -395,6 +399,9 @@ namespace Ombi.Controllers.V1
|
||||||
EpisodeRequestLimit = user.EpisodeRequestLimit ?? 0,
|
EpisodeRequestLimit = user.EpisodeRequestLimit ?? 0,
|
||||||
MovieRequestLimit = user.MovieRequestLimit ?? 0,
|
MovieRequestLimit = user.MovieRequestLimit ?? 0,
|
||||||
MusicRequestLimit = user.MusicRequestLimit ?? 0,
|
MusicRequestLimit = user.MusicRequestLimit ?? 0,
|
||||||
|
MovieRequestLimitType = user.MovieRequestLimitType ?? RequestLimitType.Week,
|
||||||
|
EpisodeRequestLimitType = user.EpisodeRequestLimitType ?? RequestLimitType.Week,
|
||||||
|
MusicRequestLimitType = user.MusicRequestLimitType ?? RequestLimitType.Week,
|
||||||
Language = user.Language,
|
Language = user.Language,
|
||||||
StreamingCountry = user.StreamingCountry
|
StreamingCountry = user.StreamingCountry
|
||||||
};
|
};
|
||||||
|
@ -422,17 +429,17 @@ namespace Ombi.Controllers.V1
|
||||||
|
|
||||||
if (vm.EpisodeRequestLimit > 0)
|
if (vm.EpisodeRequestLimit > 0)
|
||||||
{
|
{
|
||||||
vm.EpisodeRequestQuota = await TvRequestEngine.GetRemainingRequests(user);
|
vm.EpisodeRequestQuota = await _requestLimitService.GetRemainingTvRequests(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.MovieRequestLimit > 0)
|
if (vm.MovieRequestLimit > 0)
|
||||||
{
|
{
|
||||||
vm.MovieRequestQuota = await MovieRequestEngine.GetRemainingRequests(user);
|
vm.MovieRequestQuota = await _requestLimitService.GetRemainingMovieRequests(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm.MusicRequestLimit > 0)
|
if (vm.MusicRequestLimit > 0)
|
||||||
{
|
{
|
||||||
vm.MusicRequestQuota = await MusicRequestEngine.GetRemainingRequests(user);
|
vm.MusicRequestQuota = await _requestLimitService.GetRemainingMusicRequests(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the quality profiles
|
// Get the quality profiles
|
||||||
|
@ -637,6 +644,9 @@ namespace Ombi.Controllers.V1
|
||||||
user.MovieRequestLimit = ui.MovieRequestLimit;
|
user.MovieRequestLimit = ui.MovieRequestLimit;
|
||||||
user.EpisodeRequestLimit = ui.EpisodeRequestLimit;
|
user.EpisodeRequestLimit = ui.EpisodeRequestLimit;
|
||||||
user.MusicRequestLimit = ui.MusicRequestLimit;
|
user.MusicRequestLimit = ui.MusicRequestLimit;
|
||||||
|
user.EpisodeRequestLimitType = ui.EpisodeRequestLimitType;
|
||||||
|
user.MusicRequestLimitType = ui.MusicRequestLimitType;
|
||||||
|
user.MovieRequestLimitType = ui.MovieRequestLimitType;
|
||||||
if (ui.Password.HasValue())
|
if (ui.Password.HasValue())
|
||||||
{
|
{
|
||||||
user.PasswordHash = UserManager.PasswordHasher.HashPassword(user, ui.Password);
|
user.PasswordHash = UserManager.PasswordHasher.HashPassword(user, ui.Password);
|
||||||
|
|
|
@ -10,6 +10,7 @@ using Ombi.Core.Engine;
|
||||||
using Ombi.Core.Models;
|
using Ombi.Core.Models;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
|
using Ombi.Core.Services;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
||||||
|
@ -22,16 +23,18 @@ namespace Ombi.Controllers.V1
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class MusicRequestController : ControllerBase
|
public class MusicRequestController : ControllerBase
|
||||||
{
|
{
|
||||||
public MusicRequestController(IMusicRequestEngine engine, IVoteEngine voteEngine, ILogger<MusicRequestController> log)
|
public MusicRequestController(IMusicRequestEngine engine, IVoteEngine voteEngine, ILogger<MusicRequestController> log, IRequestLimitService requestLimitService)
|
||||||
{
|
{
|
||||||
_engine = engine;
|
_engine = engine;
|
||||||
_voteEngine = voteEngine;
|
_voteEngine = voteEngine;
|
||||||
_log = log;
|
_log = log;
|
||||||
|
_requestLimitService = requestLimitService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IMusicRequestEngine _engine;
|
private readonly IMusicRequestEngine _engine;
|
||||||
private readonly IVoteEngine _voteEngine;
|
private readonly IVoteEngine _voteEngine;
|
||||||
private readonly ILogger _log;
|
private readonly ILogger _log;
|
||||||
|
private readonly IRequestLimitService _requestLimitService;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets album requests.
|
/// Gets album requests.
|
||||||
|
@ -169,7 +172,7 @@ namespace Ombi.Controllers.V1
|
||||||
[HttpGet("remaining")]
|
[HttpGet("remaining")]
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingMusicRequests()
|
public async Task<RequestQuotaCountModel> GetRemainingMusicRequests()
|
||||||
{
|
{
|
||||||
return await _engine.GetRemainingRequests();
|
return await _requestLimitService.GetRemainingMusicRequests();
|
||||||
}
|
}
|
||||||
private string GetApiAlias()
|
private string GetApiAlias()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,6 +11,7 @@ using Ombi.Core.Engine.Interfaces;
|
||||||
using Ombi.Core.Models;
|
using Ombi.Core.Models;
|
||||||
using Ombi.Core.Models.Requests;
|
using Ombi.Core.Models.Requests;
|
||||||
using Ombi.Core.Models.UI;
|
using Ombi.Core.Models.UI;
|
||||||
|
using Ombi.Core.Services;
|
||||||
using Ombi.Models;
|
using Ombi.Models;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Ombi.Store.Entities.Requests;
|
using Ombi.Store.Entities.Requests;
|
||||||
|
@ -23,13 +24,16 @@ namespace Ombi.Controllers.V1
|
||||||
[ApiController]
|
[ApiController]
|
||||||
public class RequestController : ControllerBase
|
public class RequestController : ControllerBase
|
||||||
{
|
{
|
||||||
|
private readonly IRequestLimitService _requestLimitService;
|
||||||
|
|
||||||
public RequestController(IMovieRequestEngine engine, ITvRequestEngine tvRequestEngine, IVoteEngine vote,
|
public RequestController(IMovieRequestEngine engine, ITvRequestEngine tvRequestEngine, IVoteEngine vote,
|
||||||
ILogger<RequestController> log)
|
ILogger<RequestController> log, IRequestLimitService requestLimitService)
|
||||||
{
|
{
|
||||||
MovieRequestEngine = engine;
|
MovieRequestEngine = engine;
|
||||||
TvRequestEngine = tvRequestEngine;
|
TvRequestEngine = tvRequestEngine;
|
||||||
VoteEngine = vote;
|
VoteEngine = vote;
|
||||||
Log = log;
|
Log = log;
|
||||||
|
_requestLimitService = requestLimitService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMovieRequestEngine MovieRequestEngine { get; }
|
private IMovieRequestEngine MovieRequestEngine { get; }
|
||||||
|
@ -523,7 +527,7 @@ namespace Ombi.Controllers.V1
|
||||||
[HttpGet("movie/remaining")]
|
[HttpGet("movie/remaining")]
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingMovieRequests()
|
public async Task<RequestQuotaCountModel> GetRemainingMovieRequests()
|
||||||
{
|
{
|
||||||
return await MovieRequestEngine.GetRemainingRequests();
|
return await _requestLimitService.GetRemainingMovieRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -532,7 +536,7 @@ namespace Ombi.Controllers.V1
|
||||||
[HttpGet("tv/remaining")]
|
[HttpGet("tv/remaining")]
|
||||||
public async Task<RequestQuotaCountModel> GetRemainingTvRequests()
|
public async Task<RequestQuotaCountModel> GetRemainingTvRequests()
|
||||||
{
|
{
|
||||||
return await TvRequestEngine.GetRemainingRequests();
|
return await _requestLimitService.GetRemainingTvRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetApiAlias()
|
private string GetApiAlias()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue