mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-08-19 21:03:17 -07:00
Merge pull request #7 from tidusjar/develop
Bringing develop up to date
This commit is contained in:
commit
ccb496f252
86 changed files with 4083 additions and 351 deletions
|
@ -9,7 +9,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System.Threading.Tasks;
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Api.Plex.Models.Friends;
|
using Ombi.Api.Plex.Models.Friends;
|
||||||
|
using Ombi.Api.Plex.Models.OAuth;
|
||||||
using Ombi.Api.Plex.Models.Server;
|
using Ombi.Api.Plex.Models.Server;
|
||||||
using Ombi.Api.Plex.Models.Status;
|
using Ombi.Api.Plex.Models.Status;
|
||||||
|
|
||||||
|
@ -20,5 +22,8 @@ namespace Ombi.Api.Plex
|
||||||
Task<PlexFriends> GetUsers(string authToken);
|
Task<PlexFriends> GetUsers(string authToken);
|
||||||
Task<PlexAccount> GetAccount(string authToken);
|
Task<PlexAccount> GetAccount(string authToken);
|
||||||
Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId);
|
Task<PlexMetadata> GetRecentlyAdded(string authToken, string uri, string sectionId);
|
||||||
|
Task<OAuthPin> CreatePin();
|
||||||
|
Task<OAuthPin> GetPin(int pinId);
|
||||||
|
Uri GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard);
|
||||||
}
|
}
|
||||||
}
|
}
|
27
src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs
Normal file
27
src/Ombi.Api.Plex/Models/OAuth/OAuthPin.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Plex.Models.OAuth
|
||||||
|
{
|
||||||
|
public class OAuthPin
|
||||||
|
{
|
||||||
|
public int id { get; set; }
|
||||||
|
public string code { get; set; }
|
||||||
|
public bool trusted { get; set; }
|
||||||
|
public string clientIdentifier { get; set; }
|
||||||
|
public Location location { get; set; }
|
||||||
|
public int expiresIn { get; set; }
|
||||||
|
public DateTime createdAt { get; set; }
|
||||||
|
public DateTime expiresAt { get; set; }
|
||||||
|
public string authToken { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Location
|
||||||
|
{
|
||||||
|
public string code { get; set; }
|
||||||
|
public string country { get; set; }
|
||||||
|
public string city { get; set; }
|
||||||
|
public string subdivisions { get; set; }
|
||||||
|
public string coordinates { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,20 +1,53 @@
|
||||||
using System.Net.Http;
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Api.Plex.Models.Friends;
|
using Ombi.Api.Plex.Models.Friends;
|
||||||
|
using Ombi.Api.Plex.Models.OAuth;
|
||||||
using Ombi.Api.Plex.Models.Server;
|
using Ombi.Api.Plex.Models.Server;
|
||||||
using Ombi.Api.Plex.Models.Status;
|
using Ombi.Api.Plex.Models.Status;
|
||||||
|
using Ombi.Core.Settings;
|
||||||
|
using Ombi.Core.Settings.Models.External;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Settings.Settings.Models;
|
||||||
|
|
||||||
namespace Ombi.Api.Plex
|
namespace Ombi.Api.Plex
|
||||||
{
|
{
|
||||||
public class PlexApi : IPlexApi
|
public class PlexApi : IPlexApi
|
||||||
{
|
{
|
||||||
public PlexApi(IApi api)
|
public PlexApi(IApi api, ISettingsService<CustomizationSettings> settings)
|
||||||
{
|
{
|
||||||
Api = api;
|
Api = api;
|
||||||
|
_custom = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IApi Api { get; }
|
private IApi Api { get; }
|
||||||
|
private readonly ISettingsService<CustomizationSettings> _custom;
|
||||||
|
|
||||||
|
private string _app;
|
||||||
|
private string ApplicationName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_app))
|
||||||
|
{
|
||||||
|
var settings = _custom.GetSettings();
|
||||||
|
if (settings.ApplicationName.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
_app = "Ombi";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_app = settings.ApplicationName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _app;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private const string SignInUri = "https://plex.tv/users/sign_in.json";
|
private const string SignInUri = "https://plex.tv/users/sign_in.json";
|
||||||
private const string FriendsUri = "https://plex.tv/pms/friends/all";
|
private const string FriendsUri = "https://plex.tv/pms/friends/all";
|
||||||
|
@ -156,6 +189,50 @@ namespace Ombi.Api.Plex
|
||||||
return await Api.Request<PlexMetadata>(request);
|
return await Api.Request<PlexMetadata>(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<OAuthPin> CreatePin()
|
||||||
|
{
|
||||||
|
var request = new Request($"api/v2/pins", "https://plex.tv/", HttpMethod.Post);
|
||||||
|
request.AddQueryString("strong", "true");
|
||||||
|
AddHeaders(request);
|
||||||
|
|
||||||
|
return await Api.Request<OAuthPin>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<OAuthPin> GetPin(int pinId)
|
||||||
|
{
|
||||||
|
var request = new Request($"api/v2/pins/{pinId}", "https://plex.tv/", HttpMethod.Get);
|
||||||
|
AddHeaders(request);
|
||||||
|
|
||||||
|
return await Api.Request<OAuthPin>(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri GetOAuthUrl(int pinId, string code, string applicationUrl, bool wizard)
|
||||||
|
{
|
||||||
|
var request = new Request("auth#", "https://app.plex.tv", HttpMethod.Get);
|
||||||
|
AddHeaders(request);
|
||||||
|
var forwardUrl = wizard
|
||||||
|
? new Request($"Wizard/OAuth/{pinId}", applicationUrl, HttpMethod.Get)
|
||||||
|
: new Request($"Login/OAuth/{pinId}", applicationUrl, HttpMethod.Get);
|
||||||
|
|
||||||
|
request.AddQueryString("forwardUrl", forwardUrl.FullUri.ToString());
|
||||||
|
request.AddQueryString("pinID", pinId.ToString());
|
||||||
|
request.AddQueryString("code", code);
|
||||||
|
request.AddQueryString("context[device][product]", "Ombi");
|
||||||
|
request.AddQueryString("context[device][environment]", "bundled");
|
||||||
|
request.AddQueryString("clientID", $"OmbiV3");
|
||||||
|
|
||||||
|
if (request.FullUri.Fragment.Equals("#"))
|
||||||
|
{
|
||||||
|
var uri = request.FullUri.ToString();
|
||||||
|
var withoutEnd = uri.Remove(uri.Length - 1, 1);
|
||||||
|
var startOfQueryLocation = withoutEnd.IndexOf('?');
|
||||||
|
var better = withoutEnd.Insert(startOfQueryLocation, "#");
|
||||||
|
request.FullUri = new Uri(better);
|
||||||
|
}
|
||||||
|
|
||||||
|
return request.FullUri;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the required headers and also the authorization header
|
/// Adds the required headers and also the authorization header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -174,7 +251,7 @@ namespace Ombi.Api.Plex
|
||||||
private void AddHeaders(Request request)
|
private void AddHeaders(Request request)
|
||||||
{
|
{
|
||||||
request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3");
|
request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3");
|
||||||
request.AddHeader("X-Plex-Product", "Ombi");
|
request.AddHeader("X-Plex-Product", ApplicationName);
|
||||||
request.AddHeader("X-Plex-Version", "3");
|
request.AddHeader("X-Plex-Version", "3");
|
||||||
request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml");
|
request.AddContentHeader("Content-Type", request.ContentType == ContentType.Json ? "application/json" : "application/xml");
|
||||||
request.AddHeader("Accept", "application/json");
|
request.AddHeader("Accept", "application/json");
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Api.Pushover.Models;
|
using Ombi.Api.Pushover.Models;
|
||||||
|
@ -17,7 +18,7 @@ namespace Ombi.Api.Pushover
|
||||||
|
|
||||||
public async Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken)
|
public async Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken)
|
||||||
{
|
{
|
||||||
var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={message}", PushoverEndpoint, HttpMethod.Post);
|
var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={WebUtility.HtmlEncode(message)}", PushoverEndpoint, HttpMethod.Post);
|
||||||
|
|
||||||
var result = await _api.Request<PushoverResponse>(request);
|
var result = await _api.Request<PushoverResponse>(request);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="Polly" Version="5.8.0" />
|
<PackageReference Include="Polly" Version="5.8.0" />
|
||||||
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
|
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -10,7 +10,7 @@ namespace Ombi.Api
|
||||||
{
|
{
|
||||||
public Request()
|
public Request()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Request(string endpoint, string baseUrl, HttpMethod http, ContentType contentType = ContentType.Json)
|
public Request(string endpoint, string baseUrl, HttpMethod http, ContentType contentType = ContentType.Json)
|
||||||
|
@ -105,10 +105,10 @@ namespace Ombi.Api
|
||||||
hasQuery = true;
|
hasQuery = true;
|
||||||
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
startingTag = builder.Query.Contains("?") ? "&" : "?";
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Query = hasQuery
|
builder.Query = hasQuery
|
||||||
? $"{builder.Query}{startingTag}{key}={value}"
|
? $"{builder.Query}{startingTag}{key}={value}"
|
||||||
: $"{startingTag}{key}={value}";
|
: $"{startingTag}{key}={value}";
|
||||||
|
|
||||||
_modified = builder.Uri;
|
_modified = builder.Uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
76
src/Ombi.Core/Authentication/PlexOAuthManager.cs
Normal file
76
src/Ombi.Core/Authentication/PlexOAuthManager.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Plex;
|
||||||
|
using Ombi.Api.Plex.Models;
|
||||||
|
using Ombi.Api.Plex.Models.OAuth;
|
||||||
|
using Ombi.Core.Settings;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Settings.Settings.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Authentication
|
||||||
|
{
|
||||||
|
public class PlexOAuthManager : IPlexOAuthManager
|
||||||
|
{
|
||||||
|
public PlexOAuthManager(IPlexApi api, ISettingsService<CustomizationSettings> settings)
|
||||||
|
{
|
||||||
|
_api = api;
|
||||||
|
_customizationSettingsService = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IPlexApi _api;
|
||||||
|
private readonly ISettingsService<CustomizationSettings> _customizationSettingsService;
|
||||||
|
|
||||||
|
public async Task<OAuthPin> RequestPin()
|
||||||
|
{
|
||||||
|
var pin = await _api.CreatePin();
|
||||||
|
return pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetAccessTokenFromPin(int pinId)
|
||||||
|
{
|
||||||
|
var pin = await _api.GetPin(pinId);
|
||||||
|
if (pin.expiresAt < DateTime.UtcNow)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pin.authToken.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
// Looks like we do not have a pin yet, we should retry a few times.
|
||||||
|
var retryCount = 0;
|
||||||
|
var retryMax = 5;
|
||||||
|
var retryWaitMs = 1000;
|
||||||
|
while (pin.authToken.IsNullOrEmpty() && retryCount < retryMax)
|
||||||
|
{
|
||||||
|
retryCount++;
|
||||||
|
await Task.Delay(retryWaitMs);
|
||||||
|
pin = await _api.GetPin(pinId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pin.authToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<PlexAccount> GetAccount(string accessToken)
|
||||||
|
{
|
||||||
|
return await _api.GetAccount(accessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<Uri> GetOAuthUrl(int pinId, string code)
|
||||||
|
{
|
||||||
|
var settings = await _customizationSettingsService.GetSettingsAsync();
|
||||||
|
if (settings.ApplicationUrl.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var url = _api.GetOAuthUrl(pinId, code, settings.ApplicationUrl, false);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress)
|
||||||
|
{
|
||||||
|
var url = _api.GetOAuthUrl(pinId, code, websiteAddress, true);
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,14 +32,7 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
private OmbiUser _user;
|
private OmbiUser _user;
|
||||||
protected async Task<OmbiUser> GetUser()
|
protected async Task<OmbiUser> GetUser()
|
||||||
{
|
{
|
||||||
if (IsApiUser)
|
return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName.Equals(Username, StringComparison.CurrentCultureIgnoreCase)));
|
||||||
{
|
|
||||||
return new OmbiUser
|
|
||||||
{
|
|
||||||
UserName = Username,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return _user ?? (_user = await UserManager.Users.FirstOrDefaultAsync(x => x.UserName == Username));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async Task<string> UserAlias()
|
protected async Task<string> UserAlias()
|
||||||
|
@ -49,10 +42,6 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
|
|
||||||
protected async Task<bool> IsInRole(string roleName)
|
protected async Task<bool> IsInRole(string roleName)
|
||||||
{
|
{
|
||||||
if (IsApiUser && roleName != OmbiRoles.Disabled)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return await UserManager.IsInRoleAsync(await GetUser(), roleName);
|
return await UserManager.IsInRoleAsync(await GetUser(), roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +61,5 @@ namespace Ombi.Core.Engine.Interfaces
|
||||||
var ruleResults = await Rules.StartSpecificRules(model, rule);
|
var ruleResults = await Rules.StartSpecificRules(model, rule);
|
||||||
return ruleResults;
|
return ruleResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsApiUser => Username.Equals("Api", StringComparison.CurrentCultureIgnoreCase);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -63,13 +63,17 @@ namespace Ombi.Core.Engine
|
||||||
var recentlyAddedLog = new HashSet<RecentlyAddedLog>();
|
var recentlyAddedLog = new HashSet<RecentlyAddedLog>();
|
||||||
foreach (var p in plexContent)
|
foreach (var p in plexContent)
|
||||||
{
|
{
|
||||||
|
if (!p.HasTheMovieDb)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (p.Type == PlexMediaTypeEntity.Movie)
|
if (p.Type == PlexMediaTypeEntity.Movie)
|
||||||
{
|
{
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Plex,
|
Type = RecentlyAddedType.Plex,
|
||||||
ContentId = p.Id,
|
ContentId = int.Parse(p.TheMovieDbId),
|
||||||
ContentType = ContentType.Parent
|
ContentType = ContentType.Parent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -78,12 +82,18 @@ namespace Ombi.Core.Engine
|
||||||
// Add the episodes
|
// Add the episodes
|
||||||
foreach (var ep in p.Episodes)
|
foreach (var ep in p.Episodes)
|
||||||
{
|
{
|
||||||
|
if (!ep.Series.HasTvDb)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Plex,
|
Type = RecentlyAddedType.Plex,
|
||||||
ContentId = ep.Id,
|
ContentId = int.Parse(ep.Series.TvDbId),
|
||||||
ContentType = ContentType.Episode
|
ContentType = ContentType.Episode,
|
||||||
|
EpisodeNumber = ep.EpisodeNumber,
|
||||||
|
SeasonNumber = ep.SeasonNumber
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,13 +101,17 @@ namespace Ombi.Core.Engine
|
||||||
|
|
||||||
foreach (var e in embyContent)
|
foreach (var e in embyContent)
|
||||||
{
|
{
|
||||||
|
if (e.TheMovieDbId.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (e.Type == EmbyMediaType.Movie)
|
if (e.Type == EmbyMediaType.Movie)
|
||||||
{
|
{
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Emby,
|
Type = RecentlyAddedType.Emby,
|
||||||
ContentId = e.Id,
|
ContentId = int.Parse(e.TheMovieDbId),
|
||||||
ContentType = ContentType.Parent
|
ContentType = ContentType.Parent
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -106,12 +120,18 @@ namespace Ombi.Core.Engine
|
||||||
// Add the episodes
|
// Add the episodes
|
||||||
foreach (var ep in e.Episodes)
|
foreach (var ep in e.Episodes)
|
||||||
{
|
{
|
||||||
|
if (ep.Series.TvDbId.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Emby,
|
Type = RecentlyAddedType.Emby,
|
||||||
ContentId = ep.Id,
|
ContentId = int.Parse(ep.Series.TvDbId),
|
||||||
ContentType = ContentType.Episode
|
ContentType = ContentType.Episode,
|
||||||
|
EpisodeNumber = ep.EpisodeNumber,
|
||||||
|
SeasonNumber = ep.SeasonNumber
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,6 +277,7 @@ namespace Ombi.Core.Engine
|
||||||
results.ImdbId = request.ImdbId;
|
results.ImdbId = request.ImdbId;
|
||||||
results.Overview = request.Overview;
|
results.Overview = request.Overview;
|
||||||
results.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath);
|
results.PosterPath = PosterPathHelper.FixPosterPath(request.PosterPath);
|
||||||
|
results.Background = PosterPathHelper.FixBackgroundPath(request.Background);
|
||||||
results.QualityOverride = request.QualityOverride;
|
results.QualityOverride = request.QualityOverride;
|
||||||
results.RootFolder = request.RootFolder;
|
results.RootFolder = request.RootFolder;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace Ombi.Core.Helpers
|
||||||
public ChildRequests ChildRequest { get; set; }
|
public ChildRequests ChildRequest { get; set; }
|
||||||
public List<SeasonsViewModel> TvRequests { get; protected set; }
|
public List<SeasonsViewModel> TvRequests { get; protected set; }
|
||||||
public string PosterPath { get; protected set; }
|
public string PosterPath { get; protected set; }
|
||||||
|
public string BackdropPath { get; protected set; }
|
||||||
public DateTime FirstAir { get; protected set; }
|
public DateTime FirstAir { get; protected set; }
|
||||||
public TvRequests NewRequest { get; protected set; }
|
public TvRequests NewRequest { get; protected set; }
|
||||||
protected TvMazeShow ShowInfo { get; set; }
|
protected TvMazeShow ShowInfo { get; set; }
|
||||||
|
@ -44,6 +45,7 @@ namespace Ombi.Core.Helpers
|
||||||
{
|
{
|
||||||
var showIds = await MovieDbApi.GetTvExternals(result.Id);
|
var showIds = await MovieDbApi.GetTvExternals(result.Id);
|
||||||
ShowInfo.externals.imdb = showIds.imdb_id;
|
ShowInfo.externals.imdb = showIds.imdb_id;
|
||||||
|
BackdropPath = result.BackdropPath;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +242,8 @@ namespace Ombi.Core.Helpers
|
||||||
ImdbId = ShowInfo.externals?.imdb ?? string.Empty,
|
ImdbId = ShowInfo.externals?.imdb ?? string.Empty,
|
||||||
TvDbId = tv.TvDbId,
|
TvDbId = tv.TvDbId,
|
||||||
ChildRequests = new List<ChildRequests>(),
|
ChildRequests = new List<ChildRequests>(),
|
||||||
TotalSeasons = tv.Seasons.Count()
|
TotalSeasons = tv.Seasons.Count(),
|
||||||
|
Background = BackdropPath
|
||||||
};
|
};
|
||||||
NewRequest.ChildRequests.Add(ChildRequest);
|
NewRequest.ChildRequests.Add(ChildRequest);
|
||||||
|
|
||||||
|
|
16
src/Ombi.Core/IPlexOAuthManager.cs
Normal file
16
src/Ombi.Core/IPlexOAuthManager.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Plex.Models;
|
||||||
|
using Ombi.Api.Plex.Models.OAuth;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Authentication
|
||||||
|
{
|
||||||
|
public interface IPlexOAuthManager
|
||||||
|
{
|
||||||
|
Task<string> GetAccessTokenFromPin(int pinId);
|
||||||
|
Task<OAuthPin> RequestPin();
|
||||||
|
Task<Uri> GetOAuthUrl(int pinId, string code);
|
||||||
|
Uri GetWizardOAuthUrl(int pinId, string code, string websiteAddress);
|
||||||
|
Task<PlexAccount> GetAccount(string accessToken);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ namespace Ombi.Core.Models.Search
|
||||||
public bool Requested { get; set; }
|
public bool Requested { get; set; }
|
||||||
public bool Available { get; set; }
|
public bool Available { get; set; }
|
||||||
public string PlexUrl { get; set; }
|
public string PlexUrl { get; set; }
|
||||||
|
public string EmbyUrl { get; set; }
|
||||||
public string Quality { get; set; }
|
public string Quality { get; set; }
|
||||||
public abstract RequestType Type { get; }
|
public abstract RequestType Type { get; }
|
||||||
|
|
||||||
|
|
|
@ -11,12 +11,12 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="6.1.1" />
|
<PackageReference Include="AutoMapper" Version="6.1.1" />
|
||||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="3.0.1" />
|
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="3.0.1" />
|
||||||
<PackageReference Include="Hangfire" Version="1.6.17" />
|
<PackageReference Include="Hangfire" Version="1.6.19" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.0.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.5" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.5" />
|
||||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.0.0-alpha6-79" />
|
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.0.0-alpha6-79" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,7 @@ namespace Ombi.Core.Rule.Rules.Search
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
obj.Available = true;
|
obj.Available = true;
|
||||||
|
obj.EmbyUrl = item.Url;
|
||||||
|
|
||||||
if (obj.Type == RequestType.TvShow)
|
if (obj.Type == RequestType.TvShow)
|
||||||
{
|
{
|
||||||
|
|
|
@ -51,6 +51,7 @@ using Ombi.Store.Repository.Requests;
|
||||||
using Ombi.Updater;
|
using Ombi.Updater;
|
||||||
using PlexContentCacher = Ombi.Schedule.Jobs.Plex;
|
using PlexContentCacher = Ombi.Schedule.Jobs.Plex;
|
||||||
using Ombi.Api.Telegram;
|
using Ombi.Api.Telegram;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Core.Processor;
|
using Ombi.Core.Processor;
|
||||||
using Ombi.Schedule.Jobs.Plex.Interfaces;
|
using Ombi.Schedule.Jobs.Plex.Interfaces;
|
||||||
using Ombi.Schedule.Jobs.SickRage;
|
using Ombi.Schedule.Jobs.SickRage;
|
||||||
|
@ -82,6 +83,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IRecentlyAddedEngine, RecentlyAddedEngine>();
|
services.AddTransient<IRecentlyAddedEngine, RecentlyAddedEngine>();
|
||||||
services.AddTransient<ITvSender, TvSender>();
|
services.AddTransient<ITvSender, TvSender>();
|
||||||
services.AddTransient<IMassEmailSender, MassEmailSender>();
|
services.AddTransient<IMassEmailSender, MassEmailSender>();
|
||||||
|
services.AddTransient<IPlexOAuthManager, PlexOAuthManager>();
|
||||||
}
|
}
|
||||||
public static void RegisterHttp(this IServiceCollection services)
|
public static void RegisterHttp(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
|
|
17
src/Ombi.Helpers/EmbyHelper.cs
Normal file
17
src/Ombi.Helpers/EmbyHelper.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ombi.Helpers
|
||||||
|
{
|
||||||
|
public class EmbyHelper
|
||||||
|
{
|
||||||
|
public static string GetEmbyMediaUrl(string mediaId)
|
||||||
|
{
|
||||||
|
var url =
|
||||||
|
$"http://app.emby.media/itemdetails.html?id={mediaId}";
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,5 +14,12 @@ namespace Ombi.Helpers
|
||||||
yield return source1;
|
yield return source1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static HashSet<T> ToHashSet<T>(
|
||||||
|
this IEnumerable<T> source,
|
||||||
|
IEqualityComparer<T> comparer = null)
|
||||||
|
{
|
||||||
|
return new HashSet<T>(source, comparer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,7 +12,7 @@
|
||||||
<PackageReference Include="EasyCrypto" Version="3.3.2" />
|
<PackageReference Include="EasyCrypto" Version="3.3.2" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.0.1" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" />
|
<PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" />
|
||||||
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
|
@ -18,5 +18,19 @@ namespace Ombi.Helpers
|
||||||
|
|
||||||
return poster;
|
return poster;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string FixBackgroundPath(string background)
|
||||||
|
{
|
||||||
|
// https://image.tmdb.org/t/p/w1280/fJAvGOitU8y53ByeHnM4avtKFaG.jpg
|
||||||
|
|
||||||
|
if (background.Contains("image.tmdb.org", CompareOptions.IgnoreCase))
|
||||||
|
{
|
||||||
|
// Somehow we have a full path here for the poster, we only want the last segment
|
||||||
|
var backgroundSegments = background.Split('/');
|
||||||
|
return backgroundSegments.Last();
|
||||||
|
}
|
||||||
|
|
||||||
|
return background;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ensure.That" Version="7.0.0-pre32" />
|
<PackageReference Include="Ensure.That" Version="7.0.0-pre32" />
|
||||||
<PackageReference Include="MailKit" Version="1.20.0" />
|
<PackageReference Include="MailKit" Version="2.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -66,6 +66,8 @@ namespace Ombi.Schedule
|
||||||
RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
|
RecurringJob.AddOrUpdate(() => _embyUserImporter.Start(), JobSettingsHelper.UserImporter(s));
|
||||||
RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
|
RecurringJob.AddOrUpdate(() => _plexUserImporter.Start(), JobSettingsHelper.UserImporter(s));
|
||||||
RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
|
RecurringJob.AddOrUpdate(() => _newsletter.Start(), JobSettingsHelper.Newsletter(s));
|
||||||
|
|
||||||
|
BackgroundJob.Enqueue(() => _refreshMetadata.Start());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
||||||
Title = tvInfo.Name,
|
Title = tvInfo.Name,
|
||||||
Type = EmbyMediaType.Series,
|
Type = EmbyMediaType.Series,
|
||||||
EmbyId = tvShow.Id,
|
EmbyId = tvShow.Id,
|
||||||
|
Url = EmbyHelper.GetEmbyMediaUrl(tvShow.Id),
|
||||||
AddedAt = DateTime.UtcNow
|
AddedAt = DateTime.UtcNow
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -135,6 +136,7 @@ namespace Ombi.Schedule.Jobs.Emby
|
||||||
Title = movieInfo.Name,
|
Title = movieInfo.Name,
|
||||||
Type = EmbyMediaType.Movie,
|
Type = EmbyMediaType.Movie,
|
||||||
EmbyId = movieInfo.Id,
|
EmbyId = movieInfo.Id,
|
||||||
|
Url = EmbyHelper.GetEmbyMediaUrl(movieInfo.Id),
|
||||||
AddedAt = DateTime.UtcNow,
|
AddedAt = DateTime.UtcNow,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MailKit;
|
using MailKit;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.TheMovieDb;
|
using Ombi.Api.TheMovieDb;
|
||||||
using Ombi.Api.TheMovieDb.Models;
|
using Ombi.Api.TheMovieDb.Models;
|
||||||
using Ombi.Api.TvMaze;
|
using Ombi.Api.TvMaze;
|
||||||
|
@ -26,7 +29,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IRepository<RecentlyAddedLog> addedLog,
|
public NewsletterJob(IPlexContentRepository plex, IEmbyContentRepository emby, IRepository<RecentlyAddedLog> addedLog,
|
||||||
IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService<CustomizationSettings> custom,
|
IMovieDbApi movieApi, ITvMazeApi tvApi, IEmailProvider email, ISettingsService<CustomizationSettings> custom,
|
||||||
ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo,
|
ISettingsService<EmailNotificationSettings> emailSettings, INotificationTemplatesRepository templateRepo,
|
||||||
UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter)
|
UserManager<OmbiUser> um, ISettingsService<NewsletterSettings> newsletter, ILogger<NewsletterJob> log)
|
||||||
{
|
{
|
||||||
_plex = plex;
|
_plex = plex;
|
||||||
_emby = emby;
|
_emby = emby;
|
||||||
|
@ -42,6 +45,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
_emailSettings.ClearCache();
|
_emailSettings.ClearCache();
|
||||||
_customizationSettings.ClearCache();
|
_customizationSettings.ClearCache();
|
||||||
_newsletterSettings.ClearCache();
|
_newsletterSettings.ClearCache();
|
||||||
|
_log = log;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly IPlexContentRepository _plex;
|
private readonly IPlexContentRepository _plex;
|
||||||
|
@ -55,6 +59,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
private readonly ISettingsService<EmailNotificationSettings> _emailSettings;
|
private readonly ISettingsService<EmailNotificationSettings> _emailSettings;
|
||||||
private readonly ISettingsService<NewsletterSettings> _newsletterSettings;
|
private readonly ISettingsService<NewsletterSettings> _newsletterSettings;
|
||||||
private readonly UserManager<OmbiUser> _userManager;
|
private readonly UserManager<OmbiUser> _userManager;
|
||||||
|
private readonly ILogger _log;
|
||||||
|
|
||||||
public async Task Start(NewsletterSettings settings, bool test)
|
public async Task Start(NewsletterSettings settings, bool test)
|
||||||
{
|
{
|
||||||
|
@ -74,152 +79,172 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var customization = await _customizationSettings.GetSettingsAsync();
|
try
|
||||||
|
|
||||||
// Get the Content
|
|
||||||
var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking();
|
|
||||||
var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking();
|
|
||||||
|
|
||||||
var addedLog = _recentlyAddedLog.GetAll();
|
|
||||||
var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId);
|
|
||||||
var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId);
|
|
||||||
|
|
||||||
var addedPlexEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode).Select(x => x.ContentId);
|
|
||||||
var addedEmbyEpisodesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode).Select(x => x.ContentId);
|
|
||||||
|
|
||||||
// Filter out the ones that we haven't sent yet
|
|
||||||
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(x.Id));
|
|
||||||
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(x.Id));
|
|
||||||
|
|
||||||
var plexEpisodesToSend = _plex.GetAllEpisodes().Include(x => x.Series).Where(x => !addedPlexEpisodesLogIds.Contains(x.Id)).AsNoTracking();
|
|
||||||
var embyEpisodesToSend = _emby.GetAllEpisodes().Include(x => x.Series).Where(x => !addedEmbyEpisodesLogIds.Contains(x.Id)).AsNoTracking();
|
|
||||||
|
|
||||||
var body = string.Empty;
|
|
||||||
if (test)
|
|
||||||
{
|
{
|
||||||
var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
|
||||||
var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
|
||||||
var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10);
|
var customization = await _customizationSettings.GetSettingsAsync();
|
||||||
var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10);
|
// Get the Content
|
||||||
body = await BuildHtml(plexm, embym, plext, embyt, settings);
|
var plexContent = _plex.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||||
}
|
var embyContent = _emby.GetAll().Include(x => x.Episodes).AsNoTracking();
|
||||||
else
|
|
||||||
{
|
var addedLog = _recentlyAddedLog.GetAll();
|
||||||
body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings);
|
var addedPlexMovieLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Parent).Select(x => x.ContentId);
|
||||||
if (body.IsNullOrEmpty())
|
var addedEmbyMoviesLogIds = addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Parent).Select(x => x.ContentId);
|
||||||
|
|
||||||
|
var addedPlexEpisodesLogIds =
|
||||||
|
addedLog.Where(x => x.Type == RecentlyAddedType.Plex && x.ContentType == ContentType.Episode);
|
||||||
|
var addedEmbyEpisodesLogIds =
|
||||||
|
addedLog.Where(x => x.Type == RecentlyAddedType.Emby && x.ContentType == ContentType.Episode);
|
||||||
|
|
||||||
|
// Filter out the ones that we haven't sent yet
|
||||||
|
var plexContentMoviesToSend = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie && !addedPlexMovieLogIds.Contains(int.Parse(x.TheMovieDbId)));
|
||||||
|
var embyContentMoviesToSend = embyContent.Where(x => x.Type == EmbyMediaType.Movie && !addedEmbyMoviesLogIds.Contains(int.Parse(x.TheMovieDbId)));
|
||||||
|
_log.LogInformation("Plex Movies to send: {0}", plexContentMoviesToSend.Count());
|
||||||
|
_log.LogInformation("Emby Movies to send: {0}", embyContentMoviesToSend.Count());
|
||||||
|
|
||||||
|
var plexEpisodesToSend =
|
||||||
|
FilterPlexEpisodes(_plex.GetAllEpisodes().Include(x => x.Series).AsNoTracking(), addedPlexEpisodesLogIds);
|
||||||
|
var embyEpisodesToSend = FilterEmbyEpisodes(_emby.GetAllEpisodes().Include(x => x.Series).AsNoTracking(),
|
||||||
|
addedEmbyEpisodesLogIds);
|
||||||
|
|
||||||
|
_log.LogInformation("Plex Episodes to send: {0}", plexEpisodesToSend.Count());
|
||||||
|
_log.LogInformation("Emby Episodes to send: {0}", embyEpisodesToSend.Count());
|
||||||
|
var body = string.Empty;
|
||||||
|
if (test)
|
||||||
{
|
{
|
||||||
return;
|
var plexm = plexContent.Where(x => x.Type == PlexMediaTypeEntity.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
||||||
|
var embym = embyContent.Where(x => x.Type == EmbyMediaType.Movie).OrderByDescending(x => x.AddedAt).Take(10);
|
||||||
|
var plext = _plex.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).Take(10).ToHashSet();
|
||||||
|
var embyt = _emby.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.AddedAt).Take(10).ToHashSet();
|
||||||
|
body = await BuildHtml(plexm, embym, plext, embyt, settings);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
}
|
|
||||||
|
|
||||||
if (!test)
|
|
||||||
{
|
|
||||||
// Get the users to send it to
|
|
||||||
var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter);
|
|
||||||
if (!users.Any())
|
|
||||||
{
|
{
|
||||||
return;
|
body = await BuildHtml(plexContentMoviesToSend, embyContentMoviesToSend, plexEpisodesToSend, embyEpisodesToSend, settings);
|
||||||
}
|
if (body.IsNullOrEmpty())
|
||||||
|
|
||||||
foreach (var emails in settings.ExternalEmails)
|
|
||||||
{
|
|
||||||
users.Add(new OmbiUser
|
|
||||||
{
|
{
|
||||||
UserName = emails,
|
return;
|
||||||
Email = emails
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
var emailTasks = new List<Task>();
|
|
||||||
foreach (var user in users)
|
if (!test)
|
||||||
{
|
{
|
||||||
if (user.Email.IsNullOrEmpty())
|
// Get the users to send it to
|
||||||
|
var users = await _userManager.GetUsersInRoleAsync(OmbiRoles.RecievesNewsletter);
|
||||||
|
if (!users.Any())
|
||||||
{
|
{
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var messageContent = ParseTemplate(template, customization, user);
|
foreach (var emails in settings.ExternalEmails)
|
||||||
var email = new NewsletterTemplate();
|
|
||||||
|
|
||||||
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo);
|
|
||||||
|
|
||||||
emailTasks.Add(_email.Send(
|
|
||||||
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = user.Email },
|
|
||||||
emailSettings));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now add all of this to the Recently Added log
|
|
||||||
var recentlyAddedLog = new HashSet<RecentlyAddedLog>();
|
|
||||||
foreach (var p in plexContentMoviesToSend)
|
|
||||||
{
|
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
users.Add(new OmbiUser
|
||||||
Type = RecentlyAddedType.Plex,
|
{
|
||||||
ContentType = ContentType.Parent,
|
UserName = emails,
|
||||||
ContentId = p.Id
|
Email = emails
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
var emailTasks = new List<Task>();
|
||||||
|
foreach (var user in users)
|
||||||
foreach (var p in plexEpisodesToSend)
|
|
||||||
{
|
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
// Get the users to send it to
|
||||||
Type = RecentlyAddedType.Plex,
|
if (user.Email.IsNullOrEmpty())
|
||||||
ContentType = ContentType.Episode,
|
{
|
||||||
ContentId = p.Id
|
continue;
|
||||||
});
|
}
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var e in embyContentMoviesToSend)
|
var messageContent = ParseTemplate(template, customization, user);
|
||||||
{
|
var email = new NewsletterTemplate();
|
||||||
if (e.Type == EmbyMediaType.Movie)
|
|
||||||
|
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo);
|
||||||
|
|
||||||
|
emailTasks.Add(_email.Send(
|
||||||
|
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = user.Email },
|
||||||
|
emailSettings));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now add all of this to the Recently Added log
|
||||||
|
var recentlyAddedLog = new HashSet<RecentlyAddedLog>();
|
||||||
|
foreach (var p in plexContentMoviesToSend)
|
||||||
|
{
|
||||||
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
|
{
|
||||||
|
AddedAt = DateTime.Now,
|
||||||
|
Type = RecentlyAddedType.Plex,
|
||||||
|
ContentType = ContentType.Parent,
|
||||||
|
ContentId = int.Parse(p.TheMovieDbId),
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var p in plexEpisodesToSend)
|
||||||
|
{
|
||||||
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
|
{
|
||||||
|
AddedAt = DateTime.Now,
|
||||||
|
Type = RecentlyAddedType.Plex,
|
||||||
|
ContentType = ContentType.Episode,
|
||||||
|
ContentId = int.Parse(p.Series.TvDbId),
|
||||||
|
EpisodeNumber = p.EpisodeNumber,
|
||||||
|
SeasonNumber = p.SeasonNumber
|
||||||
|
});
|
||||||
|
}
|
||||||
|
foreach (var e in embyContentMoviesToSend)
|
||||||
|
{
|
||||||
|
if (e.Type == EmbyMediaType.Movie)
|
||||||
|
{
|
||||||
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
|
{
|
||||||
|
AddedAt = DateTime.Now,
|
||||||
|
Type = RecentlyAddedType.Emby,
|
||||||
|
ContentType = ContentType.Parent,
|
||||||
|
ContentId = int.Parse(e.TheMovieDbId),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var p in embyEpisodesToSend)
|
||||||
{
|
{
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
recentlyAddedLog.Add(new RecentlyAddedLog
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
AddedAt = DateTime.Now,
|
||||||
Type = RecentlyAddedType.Emby,
|
Type = RecentlyAddedType.Emby,
|
||||||
ContentType = ContentType.Parent,
|
ContentType = ContentType.Episode,
|
||||||
ContentId = e.Id
|
ContentId = int.Parse(p.Series.TvDbId),
|
||||||
|
EpisodeNumber = p.EpisodeNumber,
|
||||||
|
SeasonNumber = p.SeasonNumber
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
await _recentlyAddedLog.AddRange(recentlyAddedLog);
|
||||||
|
await Task.WhenAll(emailTasks.ToArray());
|
||||||
}
|
}
|
||||||
|
else
|
||||||
foreach (var p in embyEpisodesToSend)
|
|
||||||
{
|
{
|
||||||
recentlyAddedLog.Add(new RecentlyAddedLog
|
var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin);
|
||||||
|
foreach (var a in admins)
|
||||||
{
|
{
|
||||||
AddedAt = DateTime.Now,
|
if (a.Email.IsNullOrEmpty())
|
||||||
Type = RecentlyAddedType.Emby,
|
{
|
||||||
ContentType = ContentType.Episode,
|
continue;
|
||||||
ContentId = p.Id
|
}
|
||||||
});
|
var messageContent = ParseTemplate(template, customization, a);
|
||||||
}
|
|
||||||
await _recentlyAddedLog.AddRange(recentlyAddedLog);
|
|
||||||
|
|
||||||
await Task.WhenAll(emailTasks.ToArray());
|
var email = new NewsletterTemplate();
|
||||||
}
|
|
||||||
else
|
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo);
|
||||||
{
|
|
||||||
var admins = await _userManager.GetUsersInRoleAsync(OmbiRoles.Admin);
|
await _email.Send(
|
||||||
foreach (var a in admins)
|
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email },
|
||||||
{
|
emailSettings);
|
||||||
if (a.Email.IsNullOrEmpty())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
var messageContent = ParseTemplate(template, customization, a);
|
|
||||||
|
|
||||||
var email = new NewsletterTemplate();
|
|
||||||
|
|
||||||
var html = email.LoadTemplate(messageContent.Subject, messageContent.Message, body, customization.Logo);
|
|
||||||
|
|
||||||
await _email.Send(
|
|
||||||
new NotificationMessage { Message = html, Subject = messageContent.Subject, To = a.Email },
|
|
||||||
emailSettings);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_log.LogError(e, "Error when attempting to create newsletter");
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,6 +254,40 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
await Start(newsletterSettings, false);
|
await Start(newsletterSettings, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private HashSet<PlexEpisode> FilterPlexEpisodes(IEnumerable<PlexEpisode> source, IQueryable<RecentlyAddedLog> recentlyAdded)
|
||||||
|
{
|
||||||
|
var itemsToReturn = new HashSet<PlexEpisode>();
|
||||||
|
foreach (var ep in source)
|
||||||
|
{
|
||||||
|
var tvDbId = int.Parse(ep.Series.TvDbId);
|
||||||
|
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsToReturn.Add(ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemsToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HashSet<EmbyEpisode> FilterEmbyEpisodes(IEnumerable<EmbyEpisode> source, IQueryable<RecentlyAddedLog> recentlyAdded)
|
||||||
|
{
|
||||||
|
var itemsToReturn = new HashSet<EmbyEpisode>();
|
||||||
|
foreach (var ep in source)
|
||||||
|
{
|
||||||
|
var tvDbId = int.Parse(ep.Series.TvDbId);
|
||||||
|
if (recentlyAdded.Any(x => x.ContentId == tvDbId && x.EpisodeNumber == ep.EpisodeNumber && x.SeasonNumber == ep.SeasonNumber))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
itemsToReturn.Add(ep);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemsToReturn;
|
||||||
|
}
|
||||||
|
|
||||||
private NotificationMessageContent ParseTemplate(NotificationTemplates template, CustomizationSettings settings, OmbiUser username)
|
private NotificationMessageContent ParseTemplate(NotificationTemplates template, CustomizationSettings settings, OmbiUser username)
|
||||||
{
|
{
|
||||||
var resolver = new NotificationMessageResolver();
|
var resolver = new NotificationMessageResolver();
|
||||||
|
@ -239,7 +298,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
return resolver.ParseMessage(template, curlys);
|
return resolver.ParseMessage(template, curlys);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend, IQueryable<PlexEpisode> plexEpisodes, IQueryable<EmbyEpisode> embyEp, NewsletterSettings settings)
|
private async Task<string> BuildHtml(IQueryable<PlexServerContent> plexContentToSend, IQueryable<EmbyContent> embyContentToSend, HashSet<PlexEpisode> plexEpisodes, HashSet<EmbyEpisode> embyEp, NewsletterSettings settings)
|
||||||
{
|
{
|
||||||
var sb = new StringBuilder();
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
@ -285,8 +344,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
_log.LogError(e, "Error when Processing Plex Movies {0}", info.Title);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -315,7 +373,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
theMovieDbId = result.id.ToString();
|
theMovieDbId = result.id.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId));
|
var info = await _movieApi.GetMovieInformationWithExtraInfo(int.Parse(theMovieDbId));
|
||||||
if (info == null)
|
if (info == null)
|
||||||
{
|
{
|
||||||
|
@ -327,8 +385,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
_log.LogError(e, "Error when processing Emby Movies {0}", info.Title);
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -366,7 +423,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
AddParagraph(sb, info.Overview);
|
AddParagraph(sb, info.Overview);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessPlexTv(IQueryable<PlexEpisode> plexContent, StringBuilder sb)
|
private async Task ProcessPlexTv(HashSet<PlexEpisode> plexContent, StringBuilder sb)
|
||||||
{
|
{
|
||||||
var series = new List<PlexServerContent>();
|
var series = new List<PlexServerContent>();
|
||||||
foreach (var plexEpisode in plexContent)
|
foreach (var plexEpisode in plexContent)
|
||||||
|
@ -437,7 +494,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
sb.Append("<tr>");
|
sb.Append("<tr>");
|
||||||
sb.Append(
|
sb.Append(
|
||||||
"<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
"<td align=\"center\" style=\"font-family: sans-serif; font-size: 14px; vertical-align: top;\" valign=\"top\">");
|
||||||
|
|
||||||
var title = $"{t.Title} ({t.ReleaseYear})";
|
var title = $"{t.Title} ({t.ReleaseYear})";
|
||||||
|
|
||||||
Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/");
|
Href(sb, $"https://www.imdb.com/title/{info.externals.imdb}/");
|
||||||
|
@ -483,7 +540,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//Log.Error(e);
|
_log.LogError(e, "Error when processing Plex TV {0}", t.Title);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -494,7 +551,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessEmbyTv(IQueryable<EmbyEpisode> embyContent, StringBuilder sb)
|
private async Task ProcessEmbyTv(HashSet<EmbyEpisode> embyContent, StringBuilder sb)
|
||||||
{
|
{
|
||||||
var series = new List<EmbyContent>();
|
var series = new List<EmbyContent>();
|
||||||
foreach (var episode in embyContent)
|
foreach (var episode in embyContent)
|
||||||
|
@ -584,7 +641,7 @@ namespace Ombi.Schedule.Jobs.Ombi
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
//Log.Error(e);
|
_log.LogError(e, "Error when processing Emby TV {0}", t.Title);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,9 +10,9 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Dapper" Version="1.50.2" />
|
<PackageReference Include="Dapper" Version="1.50.2" />
|
||||||
<PackageReference Include="Hangfire" Version="1.6.17" />
|
<PackageReference Include="Hangfire" Version="1.6.19" />
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.6.17" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.6.19" />
|
||||||
<PackageReference Include="Hangfire.Console" Version="1.3.7" />
|
<PackageReference Include="Hangfire.Console" Version="1.3.10" />
|
||||||
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
||||||
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
|
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
|
||||||
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
|
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -7,7 +7,6 @@ namespace Ombi.Core.Settings.Models.External
|
||||||
{
|
{
|
||||||
public bool Enable { get; set; }
|
public bool Enable { get; set; }
|
||||||
public List<PlexServers> Servers { get; set; }
|
public List<PlexServers> Servers { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PlexServers : ExternalSettings
|
public class PlexServers : ExternalSettings
|
||||||
|
|
|
@ -7,6 +7,6 @@ namespace Ombi.Settings.Settings.Models.Notifications
|
||||||
public bool DisableTv { get; set; }
|
public bool DisableTv { get; set; }
|
||||||
public bool DisableMovies { get; set; }
|
public bool DisableMovies { get; set; }
|
||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
public List<string> ExternalEmails { get; set; }
|
public List<string> ExternalEmails { get; set; } = new List<string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -123,7 +123,23 @@ namespace Ombi.Store.Context
|
||||||
{
|
{
|
||||||
NormalizedName = OmbiRoles.RecievesNewsletter.ToUpper()
|
NormalizedName = OmbiRoles.RecievesNewsletter.ToUpper()
|
||||||
});
|
});
|
||||||
|
SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure we have the API User
|
||||||
|
var apiUserExists = Users.Any(x => x.UserName.Equals("Api", StringComparison.CurrentCultureIgnoreCase));
|
||||||
|
if (!apiUserExists)
|
||||||
|
{
|
||||||
|
Users.Add(new OmbiUser
|
||||||
|
{
|
||||||
|
UserName = "Api",
|
||||||
|
UserType = UserType.SystemUser,
|
||||||
|
NormalizedUserName = "API",
|
||||||
|
|
||||||
|
});
|
||||||
|
SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
//Check if templates exist
|
//Check if templates exist
|
||||||
var templates = NotificationTemplates.ToList();
|
var templates = NotificationTemplates.ToList();
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace Ombi.Store.Entities
|
||||||
public string TheMovieDbId { get; set; }
|
public string TheMovieDbId { get; set; }
|
||||||
public string TvDbId { get; set; }
|
public string TvDbId { get; set; }
|
||||||
|
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
public ICollection<EmbyEpisode> Episodes { get; set; }
|
public ICollection<EmbyEpisode> Episodes { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,9 @@ namespace Ombi.Store.Entities
|
||||||
{
|
{
|
||||||
public RecentlyAddedType Type { get; set; }
|
public RecentlyAddedType Type { get; set; }
|
||||||
public ContentType ContentType { get; set; }
|
public ContentType ContentType { get; set; }
|
||||||
public int ContentId { get; set; } // This is dependant on the type
|
public int ContentId { get; set; } // This is dependant on the type, it's either TMDBID or TVDBID
|
||||||
|
public int? EpisodeNumber { get; set; }
|
||||||
|
public int? SeasonNumber { get; set; }
|
||||||
public DateTime AddedAt { get; set; }
|
public DateTime AddedAt { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace Ombi.Store.Entities.Requests
|
||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string PosterPath { get; set; }
|
public string PosterPath { get; set; }
|
||||||
|
public string Background { get; set; }
|
||||||
public DateTime ReleaseDate { get; set; }
|
public DateTime ReleaseDate { get; set; }
|
||||||
public string Status { get; set; }
|
public string Status { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace Ombi.Store.Entities
|
||||||
{
|
{
|
||||||
public enum UserType
|
public enum UserType
|
||||||
{
|
{
|
||||||
|
SystemUser = 0,
|
||||||
LocalUser = 1,
|
LocalUser = 1,
|
||||||
PlexUser = 2,
|
PlexUser = 2,
|
||||||
EmbyUser = 3,
|
EmbyUser = 3,
|
||||||
|
|
950
src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs
generated
Normal file
950
src/Ombi.Store/Migrations/20180413021646_tvrequestsbackground.Designer.cs
generated
Normal file
|
@ -0,0 +1,950 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(OmbiContext))]
|
||||||
|
[Migration("20180413021646_tvrequestsbackground")]
|
||||||
|
partial class tvrequestsbackground
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AuditArea");
|
||||||
|
|
||||||
|
b.Property<int>("AuditType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateTime");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("User");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Audit");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Agent");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationType");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NotificationTemplates");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("PlayerId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("Alias");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyConnectUserId");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastLoggedIn");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimit");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderUserId");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserAccessToken");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<int>("UserType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ContentId");
|
||||||
|
|
||||||
|
b.Property<int>("ContentType");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RecentlyAddedLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<int>("ParentRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("SeriesType");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentRequestId");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("ChildRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("IssueCategory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Comment");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Date");
|
||||||
|
|
||||||
|
b.Property<int?>("IssuesId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssuesId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("IssueComments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<int>("IssueCategoryId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int?>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ResovledDate");
|
||||||
|
|
||||||
|
b.Property<int>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("UserReportedId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssueCategoryId");
|
||||||
|
|
||||||
|
b.HasIndex("IssueId");
|
||||||
|
|
||||||
|
b.HasIndex("UserReportedId");
|
||||||
|
|
||||||
|
b.ToTable("Issues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DigitalReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("RootPathOverride");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("MovieRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeCount");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int?>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int?>("RootFolder");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TvRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AirDate");
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("Requested");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SeasonId");
|
||||||
|
|
||||||
|
b.ToTable("EpisodeRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ChildRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChildRequestId");
|
||||||
|
|
||||||
|
b.ToTable("SeasonRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany("NotificationUserIds")
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest")
|
||||||
|
.WithMany("ChildRequests")
|
||||||
|
.HasForeignKey("ParentRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues")
|
||||||
|
.WithMany("Comments")
|
||||||
|
.HasForeignKey("IssuesId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IssueCategoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserReportedId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("SeasonId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest")
|
||||||
|
.WithMany("SeasonRequests")
|
||||||
|
.HasForeignKey("ChildRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
public partial class tvrequestsbackground : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Background",
|
||||||
|
table: "TvRequests",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Background",
|
||||||
|
table: "TvRequests");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
950
src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs
generated
Normal file
950
src/Ombi.Store/Migrations/20180419054711_EmbyButton.Designer.cs
generated
Normal file
|
@ -0,0 +1,950 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(OmbiContext))]
|
||||||
|
[Migration("20180419054711_EmbyButton")]
|
||||||
|
partial class EmbyButton
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AuditArea");
|
||||||
|
|
||||||
|
b.Property<int>("AuditType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateTime");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("User");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Audit");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Agent");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationType");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NotificationTemplates");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("PlayerId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("Alias");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyConnectUserId");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastLoggedIn");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimit");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderUserId");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserAccessToken");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<int>("UserType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ContentId");
|
||||||
|
|
||||||
|
b.Property<int>("ContentType");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RecentlyAddedLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<int>("ParentRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("SeriesType");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentRequestId");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("ChildRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("IssueCategory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Comment");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Date");
|
||||||
|
|
||||||
|
b.Property<int?>("IssuesId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssuesId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("IssueComments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<int>("IssueCategoryId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int?>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ResovledDate");
|
||||||
|
|
||||||
|
b.Property<int>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("UserReportedId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssueCategoryId");
|
||||||
|
|
||||||
|
b.HasIndex("IssueId");
|
||||||
|
|
||||||
|
b.HasIndex("UserReportedId");
|
||||||
|
|
||||||
|
b.ToTable("Issues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DigitalReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("RootPathOverride");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("MovieRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeCount");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int?>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int?>("RootFolder");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TvRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AirDate");
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("Requested");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SeasonId");
|
||||||
|
|
||||||
|
b.ToTable("EpisodeRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ChildRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChildRequestId");
|
||||||
|
|
||||||
|
b.ToTable("SeasonRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany("NotificationUserIds")
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest")
|
||||||
|
.WithMany("ChildRequests")
|
||||||
|
.HasForeignKey("ParentRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues")
|
||||||
|
.WithMany("Comments")
|
||||||
|
.HasForeignKey("IssuesId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IssueCategoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserReportedId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("SeasonId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest")
|
||||||
|
.WithMany("SeasonRequests")
|
||||||
|
.HasForeignKey("ChildRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs
Normal file
24
src/Ombi.Store/Migrations/20180419054711_EmbyButton.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
public partial class EmbyButton : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Url",
|
||||||
|
table: "EmbyContent",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Url",
|
||||||
|
table: "EmbyContent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
956
src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs
generated
Normal file
956
src/Ombi.Store/Migrations/20180420225638_NewsletterChanges.Designer.cs
generated
Normal file
|
@ -0,0 +1,956 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.Internal;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Store.Context;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Entities.Requests;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(OmbiContext))]
|
||||||
|
[Migration("20180420225638_NewsletterChanges")]
|
||||||
|
partial class NewsletterChanges
|
||||||
|
{
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "2.0.2-rtm-10011");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("RoleNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetRoleClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("ClaimType");
|
||||||
|
|
||||||
|
b.Property<string>("ClaimValue");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserClaims");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderKey");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderDisplayName");
|
||||||
|
|
||||||
|
b.Property<string>("UserId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasKey("LoginProvider", "ProviderKey");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserLogins");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("RoleId");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "RoleId");
|
||||||
|
|
||||||
|
b.HasIndex("RoleId");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserRoles");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.Property<string>("LoginProvider");
|
||||||
|
|
||||||
|
b.Property<string>("Name");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("UserId", "LoginProvider", "Name");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUserTokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.ApplicationConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ApplicationConfiguration");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Audit", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AuditArea");
|
||||||
|
|
||||||
|
b.Property<int>("AuditType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("DateTime");
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<string>("User");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Audit");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CouchPotatoCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId")
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("EmbyContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyId");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("ParentId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentId");
|
||||||
|
|
||||||
|
b.ToTable("EmbyEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Content");
|
||||||
|
|
||||||
|
b.Property<string>("SettingsName");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("GlobalSettings");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationTemplates", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("Agent");
|
||||||
|
|
||||||
|
b.Property<bool>("Enabled");
|
||||||
|
|
||||||
|
b.Property<string>("Message");
|
||||||
|
|
||||||
|
b.Property<int>("NotificationType");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("NotificationTemplates");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("PlayerId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("NotificationUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("AccessFailedCount");
|
||||||
|
|
||||||
|
b.Property<string>("Alias");
|
||||||
|
|
||||||
|
b.Property<string>("ConcurrencyStamp")
|
||||||
|
.IsConcurrencyToken();
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<bool>("EmailConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("EmbyConnectUserId");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeRequestLimit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastLoggedIn");
|
||||||
|
|
||||||
|
b.Property<bool>("LockoutEnabled");
|
||||||
|
|
||||||
|
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||||
|
|
||||||
|
b.Property<int?>("MovieRequestLimit");
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedEmail")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("NormalizedUserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash");
|
||||||
|
|
||||||
|
b.Property<string>("PhoneNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("PhoneNumberConfirmed");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderUserId");
|
||||||
|
|
||||||
|
b.Property<string>("SecurityStamp");
|
||||||
|
|
||||||
|
b.Property<bool>("TwoFactorEnabled");
|
||||||
|
|
||||||
|
b.Property<string>("UserAccessToken");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.HasMaxLength(256);
|
||||||
|
|
||||||
|
b.Property<int>("UserType");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedEmail")
|
||||||
|
.HasName("EmailIndex");
|
||||||
|
|
||||||
|
b.HasIndex("NormalizedUserName")
|
||||||
|
.IsUnique()
|
||||||
|
.HasName("UserNameIndex");
|
||||||
|
|
||||||
|
b.ToTable("AspNetUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("GrandparentKey");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GrandparentKey");
|
||||||
|
|
||||||
|
b.ToTable("PlexEpisode");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ParentKey");
|
||||||
|
|
||||||
|
b.Property<int>("PlexContentId");
|
||||||
|
|
||||||
|
b.Property<int?>("PlexServerContentId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonKey");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("PlexServerContentId");
|
||||||
|
|
||||||
|
b.ToTable("PlexSeasonsContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int>("Key");
|
||||||
|
|
||||||
|
b.Property<string>("Quality");
|
||||||
|
|
||||||
|
b.Property<string>("ReleaseYear");
|
||||||
|
|
||||||
|
b.Property<string>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("TvDbId");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("PlexServerContent");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RadarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.RecentlyAddedLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AddedAt");
|
||||||
|
|
||||||
|
b.Property<int>("ContentId");
|
||||||
|
|
||||||
|
b.Property<int>("ContentType");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int?>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("RecentlyAddedLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<int>("ParentRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("SeriesType");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ParentRequestId");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("ChildRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueCategory", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Value");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("IssueCategory");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Comment");
|
||||||
|
|
||||||
|
b.Property<DateTime>("Date");
|
||||||
|
|
||||||
|
b.Property<int?>("IssuesId");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssuesId");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("IssueComments");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Description");
|
||||||
|
|
||||||
|
b.Property<int>("IssueCategoryId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("ProviderId");
|
||||||
|
|
||||||
|
b.Property<int?>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("ResovledDate");
|
||||||
|
|
||||||
|
b.Property<int>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Subject");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("UserReportedId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("IssueCategoryId");
|
||||||
|
|
||||||
|
b.HasIndex("IssueId");
|
||||||
|
|
||||||
|
b.HasIndex("UserReportedId");
|
||||||
|
|
||||||
|
b.ToTable("Issues");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<bool?>("Denied");
|
||||||
|
|
||||||
|
b.Property<string>("DeniedReason");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DigitalReleaseDate");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<int?>("IssueId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestedDate");
|
||||||
|
|
||||||
|
b.Property<string>("RequestedUserId");
|
||||||
|
|
||||||
|
b.Property<int>("RootPathOverride");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<int>("TheMovieDbId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("RequestedUserId");
|
||||||
|
|
||||||
|
b.ToTable("MovieRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeCount");
|
||||||
|
|
||||||
|
b.Property<DateTime>("RequestDate");
|
||||||
|
|
||||||
|
b.Property<int>("RequestId");
|
||||||
|
|
||||||
|
b.Property<int>("RequestType");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("RequestLog");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.TvRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
|
b.Property<string>("Overview");
|
||||||
|
|
||||||
|
b.Property<string>("PosterPath");
|
||||||
|
|
||||||
|
b.Property<int?>("QualityOverride");
|
||||||
|
|
||||||
|
b.Property<DateTime>("ReleaseDate");
|
||||||
|
|
||||||
|
b.Property<int?>("RootFolder");
|
||||||
|
|
||||||
|
b.Property<string>("Status");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TvRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SickRageEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("HasFile");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.Property<int>("TvDbId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SonarrEpisodeCache");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime>("AirDate");
|
||||||
|
|
||||||
|
b.Property<bool>("Approved");
|
||||||
|
|
||||||
|
b.Property<bool>("Available");
|
||||||
|
|
||||||
|
b.Property<int>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<bool>("Requested");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonId");
|
||||||
|
|
||||||
|
b.Property<string>("Title");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("SeasonId");
|
||||||
|
|
||||||
|
b.ToTable("EpisodeRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<int>("ChildRequestId");
|
||||||
|
|
||||||
|
b.Property<int>("SeasonNumber");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ChildRequestId");
|
||||||
|
|
||||||
|
b.ToTable("SeasonRequests");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RoleId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("ParentId")
|
||||||
|
.HasPrincipalKey("EmbyId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.NotificationUserId", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany("NotificationUserIds")
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("GrandparentKey")
|
||||||
|
.HasPrincipalKey("Key")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.PlexServerContent")
|
||||||
|
.WithMany("Seasons")
|
||||||
|
.HasForeignKey("PlexServerContentId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.ChildRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.TvRequests", "ParentRequest")
|
||||||
|
.WithMany("ChildRequests")
|
||||||
|
.HasForeignKey("ParentRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.IssueComments", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.Issues", "Issues")
|
||||||
|
.WithMany("Comments")
|
||||||
|
.HasForeignKey("IssuesId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.Issues", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.IssueCategory", "IssueCategory")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("IssueCategoryId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.MovieRequests")
|
||||||
|
.WithMany("Issues")
|
||||||
|
.HasForeignKey("IssueId");
|
||||||
|
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "UserReported")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserReportedId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.MovieRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "RequestedUser")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("RequestedUserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Requests.RequestLog", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
||||||
|
.WithMany("Episodes")
|
||||||
|
.HasForeignKey("SeasonId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.SeasonRequests", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.Requests.ChildRequests", "ChildRequest")
|
||||||
|
.WithMany("SeasonRequests")
|
||||||
|
.HasForeignKey("ChildRequestId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Migrations
|
||||||
|
{
|
||||||
|
public partial class NewsletterChanges : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "EpisodeNumber",
|
||||||
|
table: "RecentlyAddedLog",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "SeasonNumber",
|
||||||
|
table: "RecentlyAddedLog",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.Sql("DELETE FROM RecentlyAddedLog");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "EpisodeNumber",
|
||||||
|
table: "RecentlyAddedLog");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "SeasonNumber",
|
||||||
|
table: "RecentlyAddedLog");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -197,6 +197,8 @@ namespace Ombi.Store.Migrations
|
||||||
|
|
||||||
b.Property<int>("Type");
|
b.Property<int>("Type");
|
||||||
|
|
||||||
|
b.Property<string>("Url");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("EmbyContent");
|
b.ToTable("EmbyContent");
|
||||||
|
@ -453,6 +455,10 @@ namespace Ombi.Store.Migrations
|
||||||
|
|
||||||
b.Property<int>("ContentType");
|
b.Property<int>("ContentType");
|
||||||
|
|
||||||
|
b.Property<int?>("EpisodeNumber");
|
||||||
|
|
||||||
|
b.Property<int?>("SeasonNumber");
|
||||||
|
|
||||||
b.Property<int>("Type");
|
b.Property<int>("Type");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
@ -645,6 +651,8 @@ namespace Ombi.Store.Migrations
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
.ValueGeneratedOnAdd();
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Background");
|
||||||
|
|
||||||
b.Property<string>("ImdbId");
|
b.Property<string>("ImdbId");
|
||||||
|
|
||||||
b.Property<string>("Overview");
|
b.Property<string>("Overview");
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.2" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.0.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.9" />
|
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.9" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -81,6 +81,7 @@ namespace Ombi.Store.Repository
|
||||||
|
|
||||||
public void Update(GlobalSettings entity)
|
public void Update(GlobalSettings entity)
|
||||||
{
|
{
|
||||||
|
Db.Update(entity);
|
||||||
//_cache.Remove(GetName(entity.SettingsName));
|
//_cache.Remove(GetName(entity.SettingsName));
|
||||||
Db.SaveChanges();
|
Db.SaveChanges();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import { CookieComponent } from "./auth/cookie.component";
|
||||||
import { PageNotFoundComponent } from "./errors/not-found.component";
|
import { PageNotFoundComponent } from "./errors/not-found.component";
|
||||||
import { LandingPageComponent } from "./landingpage/landingpage.component";
|
import { LandingPageComponent } from "./landingpage/landingpage.component";
|
||||||
import { LoginComponent } from "./login/login.component";
|
import { LoginComponent } from "./login/login.component";
|
||||||
|
import { LoginOAuthComponent } from "./login/loginoauth.component";
|
||||||
import { ResetPasswordComponent } from "./login/resetpassword.component";
|
import { ResetPasswordComponent } from "./login/resetpassword.component";
|
||||||
import { TokenResetPasswordComponent } from "./login/tokenresetpassword.component";
|
import { TokenResetPasswordComponent } from "./login/tokenresetpassword.component";
|
||||||
|
|
||||||
|
@ -41,6 +42,7 @@ const routes: Routes = [
|
||||||
{ path: "*", component: PageNotFoundComponent },
|
{ path: "*", component: PageNotFoundComponent },
|
||||||
{ path: "", redirectTo: "/search", pathMatch: "full" },
|
{ path: "", redirectTo: "/search", pathMatch: "full" },
|
||||||
{ path: "login", component: LoginComponent },
|
{ path: "login", component: LoginComponent },
|
||||||
|
{ path: "Login/OAuth/:pin", component: LoginOAuthComponent },
|
||||||
{ path: "login/:landing", component: LoginComponent },
|
{ path: "login/:landing", component: LoginComponent },
|
||||||
{ path: "reset", component: ResetPasswordComponent },
|
{ path: "reset", component: ResetPasswordComponent },
|
||||||
{ path: "token", component: TokenResetPasswordComponent },
|
{ path: "token", component: TokenResetPasswordComponent },
|
||||||
|
@ -116,6 +118,7 @@ export function HttpLoaderFactory(http: HttpClient, platformLocation: PlatformLo
|
||||||
ResetPasswordComponent,
|
ResetPasswordComponent,
|
||||||
TokenResetPasswordComponent,
|
TokenResetPasswordComponent,
|
||||||
CookieComponent,
|
CookieComponent,
|
||||||
|
LoginOAuthComponent,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
NotificationService,
|
NotificationService,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
username: string;
|
username: string;
|
||||||
password: string;
|
password: string;
|
||||||
rememberMe: boolean;
|
rememberMe: boolean;
|
||||||
|
usePlexOAuth: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILocalUser {
|
export interface ILocalUser {
|
||||||
|
|
|
@ -18,6 +18,10 @@ export class AuthService extends ServiceHelpers {
|
||||||
return this.http.post(`${this.url}/`, JSON.stringify(login), {headers: this.headers});
|
return this.http.post(`${this.url}/`, JSON.stringify(login), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public oAuth(pin: number): Observable<any> {
|
||||||
|
return this.http.get<any>(`${this.url}/${pin}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
|
||||||
public requiresPassword(login: IUserLogin): Observable<boolean> {
|
public requiresPassword(login: IUserLogin): Observable<boolean> {
|
||||||
return this.http.post<boolean>(`${this.url}/requirePassword`, JSON.stringify(login), {headers: this.headers});
|
return this.http.post<boolean>(`${this.url}/requirePassword`, JSON.stringify(login), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
user: IPlexUser;
|
user: IPlexUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPlexOAuthAccessToken {
|
||||||
|
accessToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IPlexUser {
|
export interface IPlexUser {
|
||||||
email: string;
|
email: string;
|
||||||
uuid: string;
|
uuid: string;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
requested: boolean;
|
requested: boolean;
|
||||||
available: boolean;
|
available: boolean;
|
||||||
plexUrl: string;
|
plexUrl: string;
|
||||||
|
embyUrl: string;
|
||||||
quality: string;
|
quality: string;
|
||||||
digitalReleaseDate: Date;
|
digitalReleaseDate: Date;
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ export interface ISearchTvResult {
|
||||||
requested: boolean;
|
requested: boolean;
|
||||||
available: boolean;
|
available: boolean;
|
||||||
plexUrl: string;
|
plexUrl: string;
|
||||||
|
embyUrl: string;
|
||||||
firstSeason: boolean;
|
firstSeason: boolean;
|
||||||
latestSeason: boolean;
|
latestSeason: boolean;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,29 +7,52 @@ include the remember me checkbox
|
||||||
<div *ngIf="background" @fadeInOut class="bg" [style.background-image]="background"></div>
|
<div *ngIf="background" @fadeInOut class="bg" [style.background-image]="background"></div>
|
||||||
<div class="container" id="login">
|
<div class="container" id="login">
|
||||||
<div class="card card-container">
|
<div class="card card-container">
|
||||||
|
|
||||||
<!-- <img class="profile-img-card" src="//lh3.googleusercontent.com/-6V8xOA6M7BA/AAAAAAAAAAI/AAAAAAAAAAA/rzlHcD0KYwo/photo.jpg?sz=120" alt="" /> -->
|
<!-- <img class="profile-img-card" src="//lh3.googleusercontent.com/-6V8xOA6M7BA/AAAAAAAAAAI/AAAAAAAAAAA/rzlHcD0KYwo/photo.jpg?sz=120" alt="" /> -->
|
||||||
<div *ngIf="!customizationSettings.logo"><img id="profile-img" class="profile-img-card" src="{{baseUrl}}/images/logo.png"/></div>
|
<div *ngIf="!customizationSettings.logo">
|
||||||
<div *ngIf="customizationSettings.logo"><img id="profile-img" class="center" [src]="customizationSettings.logo" /></div>
|
<img id="profile-img" class="profile-img-card" src="{{baseUrl}}/images/logo.png" />
|
||||||
|
</div>
|
||||||
|
<div *ngIf="customizationSettings.logo">
|
||||||
|
<img id="profile-img" class="center" [src]="customizationSettings.logo" />
|
||||||
|
</div>
|
||||||
<p id="profile-name" class="profile-name-card"></p>
|
<p id="profile-name" class="profile-name-card"></p>
|
||||||
|
|
||||||
<form *ngIf="authenticationSettings" class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
<div *ngIf="!plexEnabled || !customizationSettings.applicationUrl || loginWithOmbi">
|
||||||
|
<form *ngIf="authenticationSettings" class="form-signin" novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
||||||
<input type="email" id="inputEmail" class="form-control" formControlName="username" [attr.placeholder]="'Login.UsernamePlaceholder' | translate" autofocus>
|
|
||||||
<input *ngIf="!authenticationSettings.allowNoPassword" type="password" id="inputPassword" class="form-control" formControlName="password" [attr.placeholder]="'Login.PasswordPlaceholder' | translate">
|
<input type="email" id="inputEmail" class="form-control" formControlName="username" [attr.placeholder]="'Login.UsernamePlaceholder' | translate"
|
||||||
<div class="form-group">
|
autofocus>
|
||||||
<div class="checkbox">
|
<input *ngIf="!authenticationSettings.allowNoPassword" type="password" id="inputPassword" class="form-control" formControlName="password"
|
||||||
<input type="checkbox" id="RememberMe" formControlName="rememberMe" >
|
[attr.placeholder]="'Login.PasswordPlaceholder' | translate">
|
||||||
|
<div class="form-group">
|
||||||
<label for="RememberMe" [translate]="'Login.RememberMe'"></label>
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="RememberMe" formControlName="rememberMe">
|
||||||
|
|
||||||
|
<label for="RememberMe" [translate]="'Login.RememberMe'"></label>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<button class="btn btn-success" type="submit" [translate]="'Login.SignInButton'"></button>
|
||||||
<button class="btn btn-success" type="submit" [translate]="'Login.SignInButton'"></button>
|
<a [routerLink]="['/reset']" class="forgot-password col-md-12">
|
||||||
</form><!-- /form -->
|
<b [translate]="'Login.ForgottenPassword'"></b>
|
||||||
<a [routerLink]="['/reset']" class="forgot-password col-md-12">
|
</a>
|
||||||
<b [translate]="'Login.ForgottenPassword'"></b>
|
</form>
|
||||||
</a>
|
<!-- /form -->
|
||||||
</div><!-- /card-container -->
|
</div>
|
||||||
</div><!-- /container -->
|
<!-- Main OAuth Flow -->
|
||||||
|
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
|
||||||
|
<button class="btn btn-success" type="button" (click)="loginWithOmbi = true">
|
||||||
|
Sign In With {{appName}}</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-signin" *ngIf="plexEnabled && customizationSettings.applicationUrl && !loginWithOmbi">
|
||||||
|
<button class="btn btn-primary" type="button" (click)="oauth()">
|
||||||
|
Sign In With Plex</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<!-- /card-container -->
|
||||||
|
</div>
|
||||||
|
<!-- /container -->
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -25,9 +25,20 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
public form: FormGroup;
|
public form: FormGroup;
|
||||||
public customizationSettings: ICustomizationSettings;
|
public customizationSettings: ICustomizationSettings;
|
||||||
public authenticationSettings: IAuthenticationSettings;
|
public authenticationSettings: IAuthenticationSettings;
|
||||||
|
public plexEnabled: boolean;
|
||||||
public background: any;
|
public background: any;
|
||||||
public landingFlag: boolean;
|
public landingFlag: boolean;
|
||||||
public baseUrl: string;
|
public baseUrl: string;
|
||||||
|
public loginWithOmbi: boolean;
|
||||||
|
|
||||||
|
public get appName(): string {
|
||||||
|
if(this.customizationSettings.applicationName) {
|
||||||
|
return this.customizationSettings.applicationName;
|
||||||
|
} else {
|
||||||
|
return "Ombi";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private timer: any;
|
private timer: any;
|
||||||
|
|
||||||
private errorBody: string;
|
private errorBody: string;
|
||||||
|
@ -68,6 +79,7 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
public ngOnInit() {
|
public ngOnInit() {
|
||||||
this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x);
|
this.settingsService.getAuthentication().subscribe(x => this.authenticationSettings = x);
|
||||||
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
||||||
|
this.settingsService.getStatusPlex().subscribe(x => this.plexEnabled = x);
|
||||||
this.images.getRandomBackground().subscribe(x => {
|
this.images.getRandomBackground().subscribe(x => {
|
||||||
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
|
this.background = this.sanitizer.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%),url(" + x.url + ")");
|
||||||
});
|
});
|
||||||
|
@ -90,7 +102,7 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const value = form.value;
|
const value = form.value;
|
||||||
const user = { password: value.password, username: value.username, rememberMe:value.rememberMe };
|
const user = { password: value.password, username: value.username, rememberMe: value.rememberMe, usePlexOAuth: false };
|
||||||
this.authService.requiresPassword(user).subscribe(x => {
|
this.authService.requiresPassword(user).subscribe(x => {
|
||||||
if(x && this.authenticationSettings.allowNoPassword) {
|
if(x && this.authenticationSettings.allowNoPassword) {
|
||||||
// Looks like this user requires a password
|
// Looks like this user requires a password
|
||||||
|
@ -111,6 +123,12 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public oauth() {
|
||||||
|
this.authService.login({usePlexOAuth: true, password:"",rememberMe:true,username:""}).subscribe(x => {
|
||||||
|
window.location.href = x.url;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public ngOnDestroy() {
|
public ngOnDestroy() {
|
||||||
clearInterval(this.timer);
|
clearInterval(this.timer);
|
||||||
}
|
}
|
||||||
|
@ -124,5 +142,4 @@ export class LoginComponent implements OnDestroy, OnInit {
|
||||||
.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%), url(" + x.url + ")");
|
.bypassSecurityTrustStyle("linear-gradient(-10deg, transparent 20%, rgba(0,0,0,0.7) 20.0%, rgba(0,0,0,0.7) 80.0%, transparent 80%), url(" + x.url + ")");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
16
src/Ombi/ClientApp/app/login/loginoauth.component.html
Normal file
16
src/Ombi/ClientApp/app/login/loginoauth.component.html
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
<div >
|
||||||
|
|
||||||
|
<div class="container" id="login">
|
||||||
|
<div class="card card-container">
|
||||||
|
<label>Please Wait...</label>
|
||||||
|
|
||||||
|
<div *ngIf="error">
|
||||||
|
<label>{{error}}</label>
|
||||||
|
|
||||||
|
<a [routerLink]="['/login']">
|
||||||
|
Back </a>
|
||||||
|
</div>
|
||||||
|
</div><!-- /card-container -->
|
||||||
|
</div><!-- /container -->
|
||||||
|
</div>
|
42
src/Ombi/ClientApp/app/login/loginoauth.component.ts
Normal file
42
src/Ombi/ClientApp/app/login/loginoauth.component.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
|
import { AuthService } from "../auth/auth.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "./loginoauth.component.html",
|
||||||
|
})
|
||||||
|
export class LoginOAuthComponent implements OnInit {
|
||||||
|
public pin: number;
|
||||||
|
public error: string;
|
||||||
|
|
||||||
|
constructor(private authService: AuthService, private router: Router,
|
||||||
|
private route: ActivatedRoute) {
|
||||||
|
this.route.params
|
||||||
|
.subscribe((params: any) => {
|
||||||
|
this.pin = params.pin;
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.auth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public auth() {
|
||||||
|
this.authService.oAuth(this.pin).subscribe(x => {
|
||||||
|
if(x.access_token) {
|
||||||
|
localStorage.setItem("id_token", x.access_token);
|
||||||
|
|
||||||
|
if (this.authService.loggedIn()) {
|
||||||
|
this.router.navigate(["search"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(x.errorMessage) {
|
||||||
|
this.error = x.errorMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -228,9 +228,14 @@ export class TvRequestsComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
private loadBackdrop(val: TreeNode): void {
|
private loadBackdrop(val: TreeNode): void {
|
||||||
this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => {
|
if (val.data.background != null) {
|
||||||
val.data.background = this.sanitizer.bypassSecurityTrustStyle
|
val.data.background = this.sanitizer.bypassSecurityTrustStyle
|
||||||
("url(" + x + ")");
|
("url(https://image.tmdb.org/t/p/w1280" + val.data.background + ")");
|
||||||
|
} else {
|
||||||
|
this.imageService.getTvBanner(val.data.tvDbId).subscribe(x => {
|
||||||
|
val.data.background = this.sanitizer.bypassSecurityTrustStyle
|
||||||
|
("url(" + x + ")");
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
<br/>
|
<br/>
|
||||||
<div *ngIf="result.available">
|
<div *ngIf="result.available">
|
||||||
<a *ngIf="result.plexUrl" style="text-align: right" class="btn btn-sm btn-success-outline" href="{{result.plexUrl}}" target="_blank"><i class="fa fa-eye"></i> View On Plex</a>
|
<a *ngIf="result.plexUrl" style="text-align: right" class="btn btn-sm btn-success-outline" href="{{result.plexUrl}}" target="_blank"><i class="fa fa-eye"></i> View On Plex</a>
|
||||||
|
<a *ngIf="result.embyUrl" style="text-align: right" class="btn btn-sm btn-success-outline" href="{{result.embyUrl}}" target="_blank"><i class="fa fa-eye"></i> View On Emby</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="dropdown" *ngIf="result.available && issueCategories && issuesEnabled">
|
<div class="dropdown" *ngIf="result.available && issueCategories && issuesEnabled">
|
||||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
|
||||||
|
|
|
@ -118,17 +118,25 @@
|
||||||
|
|
||||||
<div *ngIf="node.data.fullyAvailable">
|
<div *ngIf="node.data.fullyAvailable">
|
||||||
<button style="text-align: right" class="btn btn-success-outline disabled" disabled>
|
<button style="text-align: right" class="btn btn-success-outline disabled" disabled>
|
||||||
<i class="fa fa-check"></i> {{ 'Common.Available' | translate }}</button>
|
<i class="fa fa-check"></i> {{ 'Common.Available' | translate }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<br />
|
<br />
|
||||||
<div *ngIf="node.data.plexUrl && node.data.available">
|
<div *ngIf="node.data.plexUrl && node.data.available">
|
||||||
<a style="text-align: right" class="btn btn-sm btn-success-outline" href="{{node.data.plexUrl}}"
|
<a style="text-align: right" class="btn btn-sm btn-success-outline" href="{{node.data.plexUrl}}"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
<i class="fa fa-eye"></i> {{ 'Search.ViewOnPlex' | translate }}</a>
|
<i class="fa fa-eye"></i> {{ 'Search.ViewOnPlex' | translate }}
|
||||||
</div>
|
</a>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="node.data.embyUrl && node.data.available">
|
||||||
|
<a style="text-align: right" class="btn btn-sm btn-success-outline" href="{{node.data.embyUrl}}"
|
||||||
|
target="_blank">
|
||||||
|
<i class="fa fa-eye"></i> {{ 'Search.ViewOnEmby' | translate }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<div class="dropdown" *ngIf="issueCategories && issuesEnabled">
|
<div class="dropdown" *ngIf="issueCategories && issuesEnabled">
|
||||||
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true"
|
<button class="btn btn-sm btn-primary-outline dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true">
|
||||||
<i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
<i class="fa fa-plus"></i> {{ 'Requests.ReportIssue' | translate }}
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</button>
|
</button>
|
||||||
|
@ -139,8 +147,8 @@
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="!node.data.available">
|
<div *ngIf="!node.data.available">
|
||||||
<br/>
|
<br />
|
||||||
<br/>
|
<br />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,3 +4,4 @@ export * from "./plex.service";
|
||||||
export * from "./radarr.service";
|
export * from "./radarr.service";
|
||||||
export * from "./sonarr.service";
|
export * from "./sonarr.service";
|
||||||
export * from "./tester.service";
|
export * from "./tester.service";
|
||||||
|
export * from "./plexoauth.service";
|
||||||
|
|
|
@ -29,4 +29,8 @@ export class PlexService extends ServiceHelpers {
|
||||||
public getFriends(): Observable<IUsersModel[]> {
|
public getFriends(): Observable<IUsersModel[]> {
|
||||||
return this.http.get<IUsersModel[]>(`${this.url}Friends`, {headers: this.headers});
|
return this.http.get<IUsersModel[]>(`${this.url}Friends`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public oAuth(wizard: boolean): Observable<any> {
|
||||||
|
return this.http.get<any>(`${this.url}oauth/${wizard}`, {headers: this.headers});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { PlatformLocation } from "@angular/common";
|
||||||
|
import { HttpClient } from "@angular/common/http";
|
||||||
|
import { Injectable } from "@angular/core";
|
||||||
|
|
||||||
|
import { Observable } from "rxjs/Rx";
|
||||||
|
|
||||||
|
import { ServiceHelpers } from "../service.helpers";
|
||||||
|
|
||||||
|
import { IPlexOAuthAccessToken } from "../../interfaces";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PlexOAuthService extends ServiceHelpers {
|
||||||
|
constructor(http: HttpClient, public platformLocation: PlatformLocation) {
|
||||||
|
super(http, "/api/v1/PlexOAuth/", platformLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public oAuth(pin: number): Observable<IPlexOAuthAccessToken> {
|
||||||
|
return this.http.get<IPlexOAuthAccessToken>(`${this.url}${pin}`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,6 +71,10 @@ export class SettingsService extends ServiceHelpers {
|
||||||
return this.http.get<IPlexSettings>(`${this.url}/Plex/`, {headers: this.headers});
|
return this.http.get<IPlexSettings>(`${this.url}/Plex/`, {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getStatusPlex(): Observable<boolean> {
|
||||||
|
return this.http.get<boolean>(`${this.url}/Plexstatus/`, {headers: this.headers});
|
||||||
|
}
|
||||||
|
|
||||||
public savePlex(settings: IPlexSettings): Observable<boolean> {
|
public savePlex(settings: IPlexSettings): Observable<boolean> {
|
||||||
return this.http.post<boolean>(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers});
|
return this.http.post<boolean>(`${this.url}/Plex/`, JSON.stringify(settings), {headers: this.headers});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class CreateAdminComponent {
|
||||||
this.identityService.createWizardUser({username: this.username, password: this.password, usePlexAdminAccount: false}).subscribe(x => {
|
this.identityService.createWizardUser({username: this.username, password: this.password, usePlexAdminAccount: false}).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
// Log me in.
|
// Log me in.
|
||||||
this.auth.login({ username: this.username, password: this.password, rememberMe:false }).subscribe(c => {
|
this.auth.login({ username: this.username, password: this.password, rememberMe: false, usePlexOAuth:false }).subscribe(c => {
|
||||||
|
|
||||||
localStorage.setItem("id_token", c.access_token);
|
localStorage.setItem("id_token", c.access_token);
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,16 @@
|
||||||
<small>Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and friends</small>
|
<small>Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and friends</small>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div style="text-align: center; margin-top: 20px">
|
<div style="text-align: center; margin-top: 20px">
|
||||||
<button (click)="requestAuthToken()" class="btn btn-primary-outline">Request Token <i class="fa fa-key"></i></button>
|
<button (click)="requestAuthToken()" class="btn btn-success-outline">Request Token <i class="fa fa-key"></i></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="text-center">OR</p>
|
||||||
|
<div class="form-group">
|
||||||
|
<div style="text-align: center; margin-top: 20px">
|
||||||
|
<button (click)="oauth()" class="btn btn-primary" type="button">Continue With Plex</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
|
|
||||||
import { ConfirmationService } from "primeng/primeng";
|
|
||||||
|
|
||||||
import { PlexService } from "../../services";
|
import { PlexService } from "../../services";
|
||||||
import { IdentityService, NotificationService, SettingsService } from "../../services";
|
import { IdentityService, NotificationService, SettingsService } from "../../services";
|
||||||
import { AuthService } from "./../../auth/auth.service";
|
import { AuthService } from "./../../auth/auth.service";
|
||||||
|
@ -17,7 +15,6 @@ export class PlexComponent {
|
||||||
|
|
||||||
constructor(private plexService: PlexService, private router: Router,
|
constructor(private plexService: PlexService, private router: Router,
|
||||||
private notificationService: NotificationService,
|
private notificationService: NotificationService,
|
||||||
private confirmationService: ConfirmationService,
|
|
||||||
private identityService: IdentityService,
|
private identityService: IdentityService,
|
||||||
private settings: SettingsService,
|
private settings: SettingsService,
|
||||||
private auth: AuthService) { }
|
private auth: AuthService) { }
|
||||||
|
@ -28,25 +25,21 @@ export class PlexComponent {
|
||||||
this.notificationService.error("Username or password was incorrect. Could not authenticate with Plex.");
|
this.notificationService.error("Username or password was incorrect. Could not authenticate with Plex.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.confirmationService.confirm({
|
|
||||||
message: "Do you want your Plex user to be the main admin account on Ombi?",
|
this.identityService.createWizardUser({
|
||||||
header: "Use Plex Account",
|
|
||||||
icon: "fa fa-check",
|
|
||||||
accept: () => {
|
|
||||||
this.identityService.createWizardUser({
|
|
||||||
username: "",
|
username: "",
|
||||||
password: "",
|
password: "",
|
||||||
usePlexAdminAccount: true,
|
usePlexAdminAccount: true,
|
||||||
}).subscribe(x => {
|
}).subscribe(y => {
|
||||||
if (x) {
|
if (y) {
|
||||||
this.auth.login({ username: this.login, password: this.password, rememberMe:false }).subscribe(c => {
|
this.auth.login({ username: this.login, password: this.password, rememberMe: false, usePlexOAuth: false }).subscribe(c => {
|
||||||
localStorage.setItem("id_token", c.access_token);
|
localStorage.setItem("id_token", c.access_token);
|
||||||
|
|
||||||
// Mark that we have done the settings now
|
// Mark that we have done the settings now
|
||||||
this.settings.getOmbi().subscribe(ombi => {
|
this.settings.getOmbi().subscribe(ombi => {
|
||||||
ombi.wizard = true;
|
ombi.wizard = true;
|
||||||
|
|
||||||
this.settings.saveOmbi(ombi).subscribe(x => {
|
this.settings.saveOmbi(ombi).subscribe(s => {
|
||||||
this.settings.getUserManagementSettings().subscribe(usr => {
|
this.settings.getUserManagementSettings().subscribe(usr => {
|
||||||
|
|
||||||
usr.importPlexAdmin = true;
|
usr.importPlexAdmin = true;
|
||||||
|
@ -64,10 +57,14 @@ export class PlexComponent {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
reject: () => {
|
);
|
||||||
this.router.navigate(["Wizard/CreateAdmin"]);
|
}
|
||||||
},
|
|
||||||
});
|
public oauth() {
|
||||||
|
this.plexService.oAuth(true).subscribe(x => {
|
||||||
|
if(x.url) {
|
||||||
|
window.location.href = x.url;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
14
src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html
Normal file
14
src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.html
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
<img class="landing-header" src="/images/logo.png" width="300" />
|
||||||
|
<div class="landing-block shadow">
|
||||||
|
<div class="media">
|
||||||
|
<div id="contentBody" class="media-body">
|
||||||
|
<h4 class="media-heading landing-title">Plex Authentication</h4>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username" class="control-label">Please Wait</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p-confirmDialog></p-confirmDialog>
|
67
src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts
Normal file
67
src/Ombi/ClientApp/app/wizard/plex/plexoauth.component.ts
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
|
||||||
|
import { IdentityService, PlexOAuthService, SettingsService } from "../../services";
|
||||||
|
import { AuthService } from "./../../auth/auth.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "./plexoauth.component.html",
|
||||||
|
})
|
||||||
|
export class PlexOAuthComponent implements OnInit {
|
||||||
|
public pinId: number;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute,
|
||||||
|
private plexOauth: PlexOAuthService,
|
||||||
|
private identityService: IdentityService,
|
||||||
|
private settings: SettingsService,
|
||||||
|
private router: Router,
|
||||||
|
private auth: AuthService) {
|
||||||
|
|
||||||
|
this.route.params
|
||||||
|
.subscribe((params: any) => {
|
||||||
|
this.pinId = params.pin;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public ngOnInit(): void {
|
||||||
|
this.plexOauth.oAuth(this.pinId).subscribe(x => {
|
||||||
|
if(!x.accessToken) {
|
||||||
|
return;
|
||||||
|
// RETURN
|
||||||
|
}
|
||||||
|
|
||||||
|
this.identityService.createWizardUser({
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
usePlexAdminAccount: true,
|
||||||
|
}).subscribe(u => {
|
||||||
|
if (u) {
|
||||||
|
this.auth.oAuth(this.pinId).subscribe(c => {
|
||||||
|
localStorage.setItem("id_token", c.access_token);
|
||||||
|
|
||||||
|
// Mark that we have done the settings now
|
||||||
|
this.settings.getOmbi().subscribe(ombi => {
|
||||||
|
ombi.wizard = true;
|
||||||
|
|
||||||
|
this.settings.saveOmbi(ombi).subscribe(s => {
|
||||||
|
this.settings.getUserManagementSettings().subscribe(usr => {
|
||||||
|
|
||||||
|
usr.importPlexAdmin = true;
|
||||||
|
this.settings.saveUserManagementSettings(usr).subscribe(saved => {
|
||||||
|
this.router.navigate(["login"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
//this.notificationService.error("Could not get the Plex Admin Information");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,6 +14,8 @@ import { WelcomeComponent } from "./welcome/welcome.component";
|
||||||
import { EmbyService } from "../services";
|
import { EmbyService } from "../services";
|
||||||
import { PlexService } from "../services";
|
import { PlexService } from "../services";
|
||||||
import { IdentityService } from "../services";
|
import { IdentityService } from "../services";
|
||||||
|
import { PlexOAuthService } from "../services";
|
||||||
|
import { PlexOAuthComponent } from "./plex/plexoauth.component";
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{ path: "", component: WelcomeComponent},
|
{ path: "", component: WelcomeComponent},
|
||||||
|
@ -21,6 +23,7 @@ const routes: Routes = [
|
||||||
{ path: "Plex", component: PlexComponent},
|
{ path: "Plex", component: PlexComponent},
|
||||||
{ path: "Emby", component: EmbyComponent},
|
{ path: "Emby", component: EmbyComponent},
|
||||||
{ path: "CreateAdmin", component: CreateAdminComponent},
|
{ path: "CreateAdmin", component: CreateAdminComponent},
|
||||||
|
{ path: "OAuth/:pin", component: PlexOAuthComponent},
|
||||||
];
|
];
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
@ -33,6 +36,7 @@ const routes: Routes = [
|
||||||
WelcomeComponent,
|
WelcomeComponent,
|
||||||
MediaServerComponent,
|
MediaServerComponent,
|
||||||
PlexComponent,
|
PlexComponent,
|
||||||
|
PlexOAuthComponent,
|
||||||
CreateAdminComponent,
|
CreateAdminComponent,
|
||||||
EmbyComponent,
|
EmbyComponent,
|
||||||
],
|
],
|
||||||
|
@ -44,6 +48,7 @@ const routes: Routes = [
|
||||||
IdentityService,
|
IdentityService,
|
||||||
EmbyService,
|
EmbyService,
|
||||||
ConfirmationService,
|
ConfirmationService,
|
||||||
|
PlexOAuthService,
|
||||||
],
|
],
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
37
src/Ombi/Controllers/External/PlexController.cs
vendored
37
src/Ombi/Controllers/External/PlexController.cs
vendored
|
@ -8,6 +8,7 @@ using Microsoft.Extensions.Logging;
|
||||||
using Ombi.Api.Plex;
|
using Ombi.Api.Plex;
|
||||||
using Ombi.Api.Plex.Models;
|
using Ombi.Api.Plex.Models;
|
||||||
using Ombi.Attributes;
|
using Ombi.Attributes;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
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;
|
||||||
|
@ -21,16 +22,18 @@ namespace Ombi.Controllers.External
|
||||||
public class PlexController : Controller
|
public class PlexController : Controller
|
||||||
{
|
{
|
||||||
public PlexController(IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings,
|
public PlexController(IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings,
|
||||||
ILogger<PlexController> logger)
|
ILogger<PlexController> logger, IPlexOAuthManager manager)
|
||||||
{
|
{
|
||||||
PlexApi = plexApi;
|
PlexApi = plexApi;
|
||||||
PlexSettings = plexSettings;
|
PlexSettings = plexSettings;
|
||||||
_log = logger;
|
_log = logger;
|
||||||
|
_plexOAuthManager = manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IPlexApi PlexApi { get; }
|
private IPlexApi PlexApi { get; }
|
||||||
private ISettingsService<PlexSettings> PlexSettings { get; }
|
private ISettingsService<PlexSettings> PlexSettings { get; }
|
||||||
private readonly ILogger<PlexController> _log;
|
private readonly ILogger<PlexController> _log;
|
||||||
|
private readonly IPlexOAuthManager _plexOAuthManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signs into the Plex API.
|
/// Signs into the Plex API.
|
||||||
|
@ -173,5 +176,37 @@ namespace Ombi.Controllers.External
|
||||||
// Filter out any dupes
|
// Filter out any dupes
|
||||||
return vm.DistinctBy(x => x.Id);
|
return vm.DistinctBy(x => x.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("oauth/{wizard:bool}")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> OAuth(bool wizard)
|
||||||
|
{
|
||||||
|
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
|
||||||
|
// Plex OAuth
|
||||||
|
// Redirect them to Plex
|
||||||
|
// We need a PIN first
|
||||||
|
var pin = await _plexOAuthManager.RequestPin();
|
||||||
|
|
||||||
|
Uri url;
|
||||||
|
if (!wizard)
|
||||||
|
{
|
||||||
|
url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var websiteAddress =$"{this.Request.Scheme}://{this.Request.Host}{this.Request.PathBase}";
|
||||||
|
url = _plexOAuthManager.GetWizardOAuthUrl(pin.id, pin.code, websiteAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url == null)
|
||||||
|
{
|
||||||
|
return new JsonResult(new
|
||||||
|
{
|
||||||
|
error = "Application URL has not been set"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResult(new {url = url.ToString()});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -213,7 +213,7 @@ namespace Ombi.Controllers
|
||||||
[PowerUser]
|
[PowerUser]
|
||||||
public async Task<IEnumerable<UserViewModel>> GetAllUsers()
|
public async Task<IEnumerable<UserViewModel>> GetAllUsers()
|
||||||
{
|
{
|
||||||
var users = await UserManager.Users
|
var users = await UserManager.Users.Where(x => x.UserType != UserType.SystemUser)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
var model = new List<UserViewModel>();
|
var model = new List<UserViewModel>();
|
||||||
|
|
78
src/Ombi/Controllers/PlexOAuthController.cs
Normal file
78
src/Ombi/Controllers/PlexOAuthController.cs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Net;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Http.Internal;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.Plex;
|
||||||
|
using Ombi.Core.Authentication;
|
||||||
|
using Ombi.Core.Settings;
|
||||||
|
using Ombi.Core.Settings.Models.External;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
|
||||||
|
namespace Ombi.Controllers
|
||||||
|
{
|
||||||
|
[ApiExplorerSettings(IgnoreApi = true)]
|
||||||
|
[ApiV1]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public class PlexOAuthController : Controller
|
||||||
|
{
|
||||||
|
public PlexOAuthController(IPlexOAuthManager manager, IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings,
|
||||||
|
ILogger<PlexOAuthController> log)
|
||||||
|
{
|
||||||
|
_manager = manager;
|
||||||
|
_plexApi = plexApi;
|
||||||
|
_plexSettings = plexSettings;
|
||||||
|
_log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IPlexOAuthManager _manager;
|
||||||
|
private readonly IPlexApi _plexApi;
|
||||||
|
private readonly ISettingsService<PlexSettings> _plexSettings;
|
||||||
|
private readonly ILogger _log;
|
||||||
|
|
||||||
|
[HttpGet("{pinId:int}")]
|
||||||
|
public async Task<IActionResult> OAuthWizardCallBack([FromRoute] int pinId)
|
||||||
|
{
|
||||||
|
var accessToken = await _manager.GetAccessTokenFromPin(pinId);
|
||||||
|
if (accessToken.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return Json(new
|
||||||
|
{
|
||||||
|
success = false,
|
||||||
|
error = "Authentication did not work. Please try again"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var settings = await _plexSettings.GetSettingsAsync();
|
||||||
|
var server = await _plexApi.GetServer(accessToken);
|
||||||
|
var servers = server.Server.FirstOrDefault();
|
||||||
|
if (servers == null)
|
||||||
|
{
|
||||||
|
_log.LogWarning("Looks like we can't find any Plex Servers");
|
||||||
|
}
|
||||||
|
_log.LogDebug("Adding first server");
|
||||||
|
|
||||||
|
settings.Enable = true;
|
||||||
|
settings.Servers = new List<PlexServers> {
|
||||||
|
new PlexServers
|
||||||
|
{
|
||||||
|
PlexAuthToken = accessToken,
|
||||||
|
Id = new Random().Next(),
|
||||||
|
Ip = servers?.LocalAddresses?.Split(new []{','}, StringSplitOptions.RemoveEmptyEntries)?.FirstOrDefault() ?? string.Empty,
|
||||||
|
MachineIdentifier = servers?.MachineIdentifier ?? string.Empty,
|
||||||
|
Port = int.Parse(servers?.Port ?? "0"),
|
||||||
|
Ssl = (servers?.Scheme ?? "http") != "http",
|
||||||
|
Name = "Server 1",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await _plexSettings.SaveSettingsAsync(settings);
|
||||||
|
return Json(new { accessToken });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -142,7 +142,19 @@ namespace Ombi.Controllers
|
||||||
[HttpGet("plex")]
|
[HttpGet("plex")]
|
||||||
public async Task<PlexSettings> PlexSettings()
|
public async Task<PlexSettings> PlexSettings()
|
||||||
{
|
{
|
||||||
return await Get<PlexSettings>();
|
var s = await Get<PlexSettings>();
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("plexstatus")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<bool> PlexStatusSettings()
|
||||||
|
{
|
||||||
|
var s = await Get<PlexSettings>();
|
||||||
|
|
||||||
|
|
||||||
|
return s.Enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -274,12 +286,6 @@ namespace Ombi.Controllers
|
||||||
public async Task<IActionResult> GetThemeContent([FromQuery]string url)
|
public async Task<IActionResult> GetThemeContent([FromQuery]string url)
|
||||||
{
|
{
|
||||||
var css = await _githubApi.GetThemesRawContent(url);
|
var css = await _githubApi.GetThemesRawContent(url);
|
||||||
var ombiSettings = await OmbiSettings();
|
|
||||||
if (ombiSettings.BaseUrl != null)
|
|
||||||
{
|
|
||||||
int index = css.IndexOf("/api/");
|
|
||||||
css = css.Insert(index, ombiSettings.BaseUrl);
|
|
||||||
}
|
|
||||||
return Content(css, "text/css");
|
return Content(css, "text/css");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Security.Claims;
|
using System.Security.Claims;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
@ -9,6 +10,7 @@ using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Ombi.Api;
|
||||||
using Ombi.Core.Authentication;
|
using Ombi.Core.Authentication;
|
||||||
using Ombi.Helpers;
|
using Ombi.Helpers;
|
||||||
using Ombi.Models;
|
using Ombi.Models;
|
||||||
|
@ -23,18 +25,21 @@ namespace Ombi.Controllers
|
||||||
[Produces("application/json")]
|
[Produces("application/json")]
|
||||||
public class TokenController
|
public class TokenController
|
||||||
{
|
{
|
||||||
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, IAuditRepository audit, ITokenRepository token)
|
public TokenController(OmbiUserManager um, IOptions<TokenAuthentication> ta, IAuditRepository audit, ITokenRepository token,
|
||||||
|
IPlexOAuthManager oAuthManager)
|
||||||
{
|
{
|
||||||
_userManager = um;
|
_userManager = um;
|
||||||
_tokenAuthenticationOptions = ta.Value;
|
_tokenAuthenticationOptions = ta.Value;
|
||||||
_audit = audit;
|
_audit = audit;
|
||||||
_token = token;
|
_token = token;
|
||||||
|
_plexOAuthManager = oAuthManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly TokenAuthentication _tokenAuthenticationOptions;
|
private readonly TokenAuthentication _tokenAuthenticationOptions;
|
||||||
private readonly IAuditRepository _audit;
|
private readonly IAuditRepository _audit;
|
||||||
private readonly ITokenRepository _token;
|
private readonly ITokenRepository _token;
|
||||||
private readonly OmbiUserManager _userManager;
|
private readonly OmbiUserManager _userManager;
|
||||||
|
private readonly IPlexOAuthManager _plexOAuthManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the token.
|
/// Gets the token.
|
||||||
|
@ -44,71 +49,132 @@ namespace Ombi.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
|
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
|
||||||
{
|
{
|
||||||
await _audit.Record(AuditType.None, AuditArea.Authentication,
|
if (!model.UsePlexOAuth)
|
||||||
|
{
|
||||||
|
await _audit.Record(AuditType.None, AuditArea.Authentication,
|
||||||
$"UserName {model.Username} attempting to authenticate");
|
$"UserName {model.Username} attempting to authenticate");
|
||||||
|
|
||||||
var user = await _userManager.FindByNameAsync(model.Username);
|
var user = await _userManager.FindByNameAsync(model.Username);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
// Could this be an email login?
|
||||||
|
user = await _userManager.FindByEmailAsync(model.Username);
|
||||||
|
|
||||||
|
if (user == null)
|
||||||
|
{
|
||||||
|
return new UnauthorizedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
user.EmailLogin = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Verify Password
|
||||||
|
if (await _userManager.CheckPasswordAsync(user, model.Password))
|
||||||
|
{
|
||||||
|
return await CreateToken(model.RememberMe, user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Plex OAuth
|
||||||
|
// Redirect them to Plex
|
||||||
|
// We need a PIN first
|
||||||
|
var pin = await _plexOAuthManager.RequestPin();
|
||||||
|
|
||||||
|
//https://app.plex.tv/auth#?forwardUrl=http://google.com/&clientID=Ombi-Test&context%5Bdevice%5D%5Bproduct%5D=Ombi%20SSO&pinID=798798&code=4lgfd
|
||||||
|
var url = await _plexOAuthManager.GetOAuthUrl(pin.id, pin.code);
|
||||||
|
if (url == null)
|
||||||
|
{
|
||||||
|
return new JsonResult(new
|
||||||
|
{
|
||||||
|
error = "Application URL has not been set"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return new JsonResult(new { url = url.ToString() });
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UnauthorizedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IActionResult> CreateToken(bool rememberMe, OmbiUser user)
|
||||||
|
{
|
||||||
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
|
|
||||||
|
if (roles.Contains(OmbiRoles.Disabled))
|
||||||
|
{
|
||||||
|
return new UnauthorizedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
user.LastLoggedIn = DateTime.UtcNow;
|
||||||
|
await _userManager.UpdateAsync(user);
|
||||||
|
|
||||||
|
var claims = new List<Claim>
|
||||||
|
{
|
||||||
|
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
|
||||||
|
new Claim(ClaimTypes.NameIdentifier, user.Id),
|
||||||
|
new Claim(ClaimTypes.Name, user.UserName),
|
||||||
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||||
|
};
|
||||||
|
claims.AddRange(roles.Select(role => new Claim("role", role)));
|
||||||
|
|
||||||
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey));
|
||||||
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
claims: claims,
|
||||||
|
expires: rememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5),
|
||||||
|
signingCredentials: creds,
|
||||||
|
audience: "Ombi", issuer: "Ombi"
|
||||||
|
);
|
||||||
|
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
if (rememberMe)
|
||||||
|
{
|
||||||
|
// Save the token so we can refresh it later
|
||||||
|
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
|
||||||
|
}
|
||||||
|
|
||||||
|
return new JsonResult(new
|
||||||
|
{
|
||||||
|
access_token = accessToken,
|
||||||
|
expiration = token.ValidTo
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{pinId:int}")]
|
||||||
|
public async Task<IActionResult> OAuth(int pinId)
|
||||||
|
{
|
||||||
|
var accessToken = await _plexOAuthManager.GetAccessTokenFromPin(pinId);
|
||||||
|
|
||||||
|
if (accessToken.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
// Looks like we are not authenticated.
|
||||||
|
return new JsonResult(new
|
||||||
|
{
|
||||||
|
errorMessage = "Could not authenticate with Plex"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's look for the users account
|
||||||
|
var account = await _plexOAuthManager.GetAccount(accessToken);
|
||||||
|
|
||||||
|
// Get the ombi user
|
||||||
|
var user = await _userManager.FindByNameAsync(account.user.username);
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
// Could this be an email login?
|
// Could this be an email login?
|
||||||
user = await _userManager.FindByEmailAsync(model.Username);
|
user = await _userManager.FindByEmailAsync(account.user.email);
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return new UnauthorizedResult();
|
return new UnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
user.EmailLogin = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify Password
|
return await CreateToken(true, user);
|
||||||
if (await _userManager.CheckPasswordAsync(user, model.Password))
|
|
||||||
{
|
|
||||||
var roles = await _userManager.GetRolesAsync(user);
|
|
||||||
|
|
||||||
if (roles.Contains(OmbiRoles.Disabled))
|
|
||||||
{
|
|
||||||
return new UnauthorizedResult();
|
|
||||||
}
|
|
||||||
|
|
||||||
user.LastLoggedIn = DateTime.UtcNow;
|
|
||||||
await _userManager.UpdateAsync(user);
|
|
||||||
|
|
||||||
var claims = new List<Claim>
|
|
||||||
{
|
|
||||||
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
|
|
||||||
new Claim(ClaimTypes.NameIdentifier, user.Id),
|
|
||||||
new Claim(ClaimTypes.Name, user.UserName),
|
|
||||||
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
|
||||||
};
|
|
||||||
claims.AddRange(roles.Select(role => new Claim("role", role)));
|
|
||||||
|
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey));
|
|
||||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
|
||||||
|
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
|
||||||
claims: claims,
|
|
||||||
expires: model.RememberMe ? DateTime.UtcNow.AddDays(7) : DateTime.UtcNow.AddHours(5),
|
|
||||||
signingCredentials: creds,
|
|
||||||
audience: "Ombi", issuer:"Ombi"
|
|
||||||
);
|
|
||||||
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
|
|
||||||
if (model.RememberMe)
|
|
||||||
{
|
|
||||||
// Save the token so we can refresh it later
|
|
||||||
//await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new JsonResult(new
|
|
||||||
{
|
|
||||||
access_token = accessToken,
|
|
||||||
expiration = token.ValidTo
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return new UnauthorizedResult();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -127,7 +193,7 @@ namespace Ombi.Controllers
|
||||||
{
|
{
|
||||||
return new UnauthorizedResult();
|
return new UnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,5 +6,6 @@
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
public bool RememberMe { get; set; }
|
public bool RememberMe { get; set; }
|
||||||
public bool UsePlexAdminAccount { get; set; }
|
public bool UsePlexAdminAccount { get; set; }
|
||||||
|
public bool UsePlexOAuth { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -61,13 +61,13 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AutoMapper" Version="6.1.1" />
|
<PackageReference Include="AutoMapper" Version="6.1.1" />
|
||||||
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
|
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
|
||||||
<PackageReference Include="Hangfire.AspNetCore" Version="1.6.17" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.6.19" />
|
||||||
<PackageReference Include="Hangfire.Console" Version="1.3.7" />
|
<PackageReference Include="Hangfire.Console" Version="1.3.10" />
|
||||||
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
||||||
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
|
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
|
||||||
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
|
<PackageReference Include="Hangfire.SQLite" Version="1.4.2" />
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6" />
|
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.7" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="2.0.1" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
|
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.0.2" />
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="3.2.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="3.2.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
|
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
|
||||||
<PackageReference Include="Serilog.Sinks.SQLite" Version="3.8.3" />
|
<PackageReference Include="Serilog.Sinks.SQLite" Version="3.8.3" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="1.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="2.4.0" />
|
||||||
<PackageReference Include="System.Security.Cryptography.Csp" Version="4.3.0" />
|
<PackageReference Include="System.Security.Cryptography.Csp" Version="4.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace Ombi
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(!baseUrl.Equals(dbBaseUrl.Value))
|
else if(baseUrl.HasValue() && !baseUrl.Equals(dbBaseUrl.Value))
|
||||||
{
|
{
|
||||||
dbBaseUrl.Value = baseUrl;
|
dbBaseUrl.Value = baseUrl;
|
||||||
ctx.SaveChanges();
|
ctx.SaveChanges();
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
"profiles": {
|
"profiles": {
|
||||||
"IIS Express": {
|
"IIS Express": {
|
||||||
"commandName": "IISExpress",
|
"commandName": "IISExpress",
|
||||||
|
"commandLineArgs": "-baseurl /testing",
|
||||||
"launchBrowser": true,
|
"launchBrowser": true,
|
||||||
"environmentVariables": {
|
"environmentVariables": {
|
||||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
|
|
@ -173,26 +173,22 @@ namespace Ombi
|
||||||
settings.ApiKey = Guid.NewGuid().ToString("N");
|
settings.ApiKey = Guid.NewGuid().ToString("N");
|
||||||
ombiService.SaveSettings(settings);
|
ombiService.SaveSettings(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if it's in the startup args
|
||||||
|
var appConfig = serviceProvider.GetService<IApplicationConfigRepository>();
|
||||||
|
var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result;
|
||||||
|
if (baseUrl != null)
|
||||||
|
{
|
||||||
|
if (baseUrl.Value.HasValue())
|
||||||
|
{
|
||||||
|
settings.BaseUrl = baseUrl.Value;
|
||||||
|
ombiService.SaveSettings(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (settings.BaseUrl.HasValue())
|
if (settings.BaseUrl.HasValue())
|
||||||
{
|
{
|
||||||
app.UsePathBase(settings.BaseUrl);
|
app.UsePathBase(settings.BaseUrl);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Check if it's in the startup args
|
|
||||||
var appConfig = serviceProvider.GetService<IApplicationConfigRepository>();
|
|
||||||
var baseUrl = appConfig.Get(ConfigurationTypes.BaseUrl).Result;
|
|
||||||
if (baseUrl != null)
|
|
||||||
{
|
|
||||||
if (baseUrl.Value.HasValue())
|
|
||||||
{
|
|
||||||
settings.BaseUrl = baseUrl.Value;
|
|
||||||
ombiService.SaveSettings(settings);
|
|
||||||
|
|
||||||
app.UsePathBase(settings.BaseUrl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)});
|
app.UseHangfireServer(new BackgroundJobServerOptions { WorkerCount = 1, ServerTimeout = TimeSpan.FromDays(1), ShutdownTimeout = TimeSpan.FromDays(1)});
|
||||||
app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire",
|
app.UseHangfireDashboard(settings.BaseUrl.HasValue() ? $"{settings.BaseUrl}/hangfire" : "/hangfire",
|
||||||
|
@ -223,7 +219,6 @@ namespace Ombi
|
||||||
app.UseSwaggerUI(c =>
|
app.UseSwaggerUI(c =>
|
||||||
{
|
{
|
||||||
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
|
||||||
c.ShowJsonEditor();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
app.UseMvc(routes =>
|
app.UseMvc(routes =>
|
||||||
|
|
|
@ -17,56 +17,56 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var appName = customization.ApplicationName;
|
var appName = customization.ApplicationName;
|
||||||
if(string.IsNullOrEmpty(appName))
|
if (string.IsNullOrEmpty(appName))
|
||||||
{
|
{
|
||||||
appName = "Ombi";
|
appName = "Ombi";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!--
|
<!--
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bbbbbbbb
|
|
||||||
OOOOOOOOO b::::::b iiii
|
|
||||||
OO:::::::::OO b::::::b i::::i
|
|
||||||
OO:::::::::::::OO b::::::b iiii
|
|
||||||
O:::::::OOO:::::::O b:::::b
|
|
||||||
O::::::O O::::::O mmmmmmm mmmmmmm b:::::bbbbbbbbb iiiiiii
|
|
||||||
O:::::O O:::::O mm:::::::m m:::::::mm b::::::::::::::bb i:::::i
|
|
||||||
O:::::O O:::::Om::::::::::mm::::::::::mb::::::::::::::::b i::::i
|
|
||||||
O:::::O O:::::Om::::::::::::::::::::::mb:::::bbbbb:::::::b i::::i
|
|
||||||
O:::::O O:::::Om:::::mmm::::::mmm:::::mb:::::b b::::::b i::::i
|
|
||||||
O:::::O O:::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
|
||||||
O:::::O O:::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
|
||||||
O::::::O O::::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
|
||||||
O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i
|
|
||||||
OO:::::::::::::OO m::::m m::::m m::::mb::::::::::::::::b i::::::i
|
|
||||||
OO:::::::::OO m::::m m::::m m::::mb:::::::::::::::b i::::::i
|
|
||||||
OOOOOOOOO mmmmmm mmmmmm mmmmmmbbbbbbbbbbbbbbbb iiiiiiii
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-->
|
|
||||||
<meta charset="utf-8"/>
|
bbbbbbbb
|
||||||
|
OOOOOOOOO b::::::b iiii
|
||||||
|
OO:::::::::OO b::::::b i::::i
|
||||||
|
OO:::::::::::::OO b::::::b iiii
|
||||||
|
O:::::::OOO:::::::O b:::::b
|
||||||
|
O::::::O O::::::O mmmmmmm mmmmmmm b:::::bbbbbbbbb iiiiiii
|
||||||
|
O:::::O O:::::O mm:::::::m m:::::::mm b::::::::::::::bb i:::::i
|
||||||
|
O:::::O O:::::Om::::::::::mm::::::::::mb::::::::::::::::b i::::i
|
||||||
|
O:::::O O:::::Om::::::::::::::::::::::mb:::::bbbbb:::::::b i::::i
|
||||||
|
O:::::O O:::::Om:::::mmm::::::mmm:::::mb:::::b b::::::b i::::i
|
||||||
|
O:::::O O:::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
||||||
|
O:::::O O:::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
||||||
|
O::::::O O::::::Om::::m m::::m m::::mb:::::b b:::::b i::::i
|
||||||
|
O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i
|
||||||
|
OO:::::::::::::OO m::::m m::::m m::::mb::::::::::::::::b i::::::i
|
||||||
|
OO:::::::::OO m::::m m::::m m::::mb:::::::::::::::b i::::::i
|
||||||
|
OOOOOOOOO mmmmmm mmmmmm mmmmmmbbbbbbbbbbbbbbbb iiiiiiii
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
<meta charset="utf-8" />
|
||||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||||
<meta name="description" content="Ombi, media request tool">
|
<meta name="description" content="Ombi, media request tool">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>@appName</title>
|
<title>@appName</title>
|
||||||
<meta property="og:title" content=“@appName”/>
|
<meta property="og:title" content=“@appName” />
|
||||||
<meta property="og:image" content="~/images/logo.png"/>
|
<meta property="og:image" content="~/images/logo.png" />
|
||||||
<meta property="og:site_name" content=“@appName”/>
|
<meta property="og:site_name" content=“@appName” />
|
||||||
<base href="/@baseUrl"/>
|
<base href="/@baseUrl" />
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="~/images/favicon/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="~/images/favicon/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="~/images/favicon/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="~/images/favicon/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="~/images/favicon/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="~/images/favicon/favicon-16x16.png">
|
||||||
|
@ -80,23 +80,35 @@ O:::::::OOO:::::::Om::::m m::::m m::::mb:::::bbbbbb::::::bi::::::i
|
||||||
|
|
||||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
||||||
|
|
||||||
<link rel="stylesheet" href="~/loading.css" asp-append-version="true"/>
|
<link rel="stylesheet" href="~/loading.css" asp-append-version="true" />
|
||||||
<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true"/>
|
<link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />
|
||||||
<script src="~/dist/vendor.js" asp-append-version="true" defer></script>
|
<script src="~/dist/vendor.js" asp-append-version="true" defer></script>
|
||||||
<script src="~/dist/main.js" asp-append-version="true" defer></script>
|
<script src="~/dist/main.js" asp-append-version="true" defer></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@{
|
@{
|
||||||
if (customization.HasPresetTheme)
|
if (customization.HasPresetTheme)
|
||||||
{
|
{
|
||||||
|
if (!string.IsNullOrEmpty(baseUrl))
|
||||||
|
{
|
||||||
|
if (!customization.PresetThemeContent.Contains("/" + baseUrl))
|
||||||
|
{
|
||||||
|
var index = customization.PresetThemeContent.IndexOf("/api/");
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
customization.PresetThemeContent = customization.PresetThemeContent.Insert(index, "/" + baseUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@Html.Raw(customization.PresetThemeContent)
|
@Html.Raw(customization.PresetThemeContent)
|
||||||
</style>
|
</style>
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(customization.CustomCssLink))
|
if (!string.IsNullOrEmpty(customization.CustomCssLink))
|
||||||
{
|
{
|
||||||
<link rel="stylesheet" href="@customization.CustomCssLink" asp-append-version="true"/>
|
<link rel="stylesheet" href="@customization.CustomCssLink" asp-append-version="true" />
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Se på Plex",
|
"ViewOnPlex": "Se på Plex",
|
||||||
|
"ViewOnEmby": "Se på Emby",
|
||||||
"RequestAdded": "{{title}} er anmodet med succes",
|
"RequestAdded": "{{title}} er anmodet med succes",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "In Plex anschauen",
|
"ViewOnPlex": "In Plex anschauen",
|
||||||
|
"ViewOnEmby": "In Emby anschauen",
|
||||||
"RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt",
|
"RequestAdded": "Anfrage für {{title}} wurde erfolgreich hinzugefügt",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease":"Theatrical Release: {{date}}",
|
"TheatricalRelease":"Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "View On Plex",
|
"ViewOnPlex": "View On Plex",
|
||||||
|
"ViewOnEmby": "View On Emby",
|
||||||
"RequestAdded": "Request for {{title}} has been added successfully",
|
"RequestAdded": "Request for {{title}} has been added successfully",
|
||||||
"Similar":"Similar",
|
"Similar":"Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Ver en Plex",
|
"ViewOnPlex": "Ver en Plex",
|
||||||
|
"ViewOnEmby": "Ver en Emby",
|
||||||
"RequestAdded": "La solicitud de {{title}} se ha agregado con éxito",
|
"RequestAdded": "La solicitud de {{title}} se ha agregado con éxito",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Regarder sur Plex",
|
"ViewOnPlex": "Regarder sur Plex",
|
||||||
|
"ViewOnEmby": "Regarder sur Emby",
|
||||||
"RequestAdded": "La demande pour {{title}} a été ajoutée avec succès",
|
"RequestAdded": "La demande pour {{title}} a été ajoutée avec succès",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Guarda su Plex",
|
"ViewOnPlex": "Guarda su Plex",
|
||||||
|
"ViewOnEmby": "Guarda su Emby",
|
||||||
"RequestAdded": "La richiesta per {{title}} è stata aggiunta correttamente",
|
"RequestAdded": "La richiesta per {{title}} è stata aggiunta correttamente",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Bekijk op Plex",
|
"ViewOnPlex": "Bekijk op Plex",
|
||||||
|
"ViewOnEmby": "Bekijk op Emby",
|
||||||
"RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd",
|
"RequestAdded": "Aanvraag voor {{title}} is succesvol toegevoegd",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital utgivelse: {{date}}",
|
"DigitalDate": "Digital utgivelse: {{date}}",
|
||||||
"TheatricalRelease": "Kinopremiere: {{date}}",
|
"TheatricalRelease": "Kinopremiere: {{date}}",
|
||||||
"ViewOnPlex": "Spill av på Plex",
|
"ViewOnPlex": "Spill av på Plex",
|
||||||
|
"ViewOnEmby": "Spill av på Emby",
|
||||||
"RequestAdded": "Forespørsel om {{title}} er lagt til",
|
"RequestAdded": "Forespørsel om {{title}} er lagt til",
|
||||||
"Similar": "Lignende",
|
"Similar": "Lignende",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
"DigitalDate": "Digital Release: {{date}}",
|
"DigitalDate": "Digital Release: {{date}}",
|
||||||
"TheatricalRelease": "Theatrical Release: {{date}}",
|
"TheatricalRelease": "Theatrical Release: {{date}}",
|
||||||
"ViewOnPlex": "Visa på Plex",
|
"ViewOnPlex": "Visa på Plex",
|
||||||
|
"ViewOnEmby": "Visa på Emby",
|
||||||
"RequestAdded": "Efterfrågan om {{title}} har lagts till",
|
"RequestAdded": "Efterfrågan om {{title}} har lagts till",
|
||||||
"Similar": "Similar",
|
"Similar": "Similar",
|
||||||
"Movies": {
|
"Movies": {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue