Merge remote-tracking branch 'upstream/dev'

This commit is contained in:
Patrick Frisch 2017-04-10 15:34:03 +02:00
commit cd2c9a40e5
283 changed files with 10998 additions and 1985 deletions

View file

@ -42,6 +42,7 @@ using Nancy.Validation;
using NLog;
using Ombi.Api;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Movie;
using Ombi.Core;
using Ombi.Core.Models;
using Ombi.Core.SettingModels;
@ -94,11 +95,14 @@ namespace Ombi.UI.Modules.Admin
private IJobRecord JobRecorder { get; }
private IAnalytics Analytics { get; }
private IRecentlyAdded RecentlyAdded { get; }
private IMassEmail MassEmail { get; }
private ISettingsService<NotificationSettingsV2> NotifySettings { get; }
private ISettingsService<DiscordNotificationSettings> DiscordSettings { get; }
private IDiscordApi DiscordApi { get; }
private ISettingsService<RadarrSettings> RadarrSettings { get; }
private IRadarrApi RadarrApi { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IEmbyApi EmbyApi { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
public AdminModule(ISettingsService<PlexRequestSettings> prService,
@ -124,10 +128,11 @@ namespace Ombi.UI.Modules.Admin
ISlackApi slackApi, ISettingsService<MattermostNotificationSettings> mattermostSettings,
IMattermostApi mattermostApi, ISettingsService<LandingPageSettings> lp,
ISettingsService<ScheduledJobsSettings> scheduler, IJobRecord rec, IAnalytics analytics,
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded,
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded, IMassEmail massEmail,
ISettingsService<WatcherSettings> watcherSettings ,
ISettingsService<DiscordNotificationSettings> discord,
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi
IDiscordApi discordapi, ISettingsService<RadarrSettings> settings, IRadarrApi radarrApi,
ISettingsService<EmbySettings> embySettings, IEmbyApi emby
, ISecurityExtensions security) : base("admin", prService, security)
{
PrService = prService;
@ -160,12 +165,15 @@ namespace Ombi.UI.Modules.Admin
Analytics = analytics;
NotifySettings = notifyService;
RecentlyAdded = recentlyAdded;
MassEmail = massEmail;
WatcherSettings = watcherSettings;
DiscordSettings = discord;
DiscordApi = discordapi;
RadarrSettings = settings;
RadarrApi = radarrApi;
EmbyApi = emby;
EmbySettings = embySettings;
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["/"] = _ => Admin();
@ -175,7 +183,7 @@ namespace Ombi.UI.Modules.Admin
Post["/", true] = async (x, ct) => await SaveAdmin();
Post["/requestauth"] = _ => RequestAuthToken();
Post["/requestauth", true] = async (x, ct) => await RequestAuthToken();
Get["/getusers"] = _ => GetUsers();
@ -185,6 +193,10 @@ namespace Ombi.UI.Modules.Admin
Get["/plex"] = _ => Plex();
Post["/plex", true] = async (x, ct) => await SavePlex();
Get["/emby", true] = async (x, ct) => await Emby();
Post["/emby", true] = async (x, ct) => await SaveEmby();
Get["/sonarr"] = _ => Sonarr();
Post["/sonarr"] = _ => SaveSonarr();
Post["/sonarrprofiles"] = _ => GetSonarrQualityProfiles();
@ -218,6 +230,11 @@ namespace Ombi.UI.Modules.Admin
Get["/newsletter", true] = async (x, ct) => await Newsletter();
Post["/newsletter", true] = async (x, ct) => await SaveNewsletter();
Post["/testnewsletteradminemail"] = x => TestNewsletterAdminEmail();
Get["/massemail"] = _ => MassEmailView();
Post["/testmassadminemail"] = x => TestMassAdminEmail();
Post["/sendmassemail"] = x => SendMassEmail();
Post["/createapikey"] = x => CreateApiKey();
@ -246,7 +263,6 @@ namespace Ombi.UI.Modules.Admin
Get["/notificationsettings", true] = async (x, ct) => await NotificationSettings();
Post["/notificationsettings"] = x => SaveNotificationSettings();
Post["/recentlyAddedTest"] = x => RecentlyAddedTest();
}
private async Task<Negotiator> Authentication()
@ -312,7 +328,7 @@ namespace Ombi.UI.Modules.Admin
: new JsonResponseModel { Result = false, Message = "We could not save to the database, please try again" });
}
private Response RequestAuthToken()
private async Task<Response> RequestAuthToken()
{
var user = this.Bind<PlexAuth>();
@ -328,11 +344,11 @@ namespace Ombi.UI.Modules.Admin
return Response.AsJson(new { Result = false, Message = "Incorrect username or password!" });
}
var oldSettings = PlexService.GetSettings();
var oldSettings = await PlexService.GetSettingsAsync();
if (oldSettings != null)
{
oldSettings.PlexAuthToken = model.user.authentication_token;
PlexService.SaveSettings(oldSettings);
await PlexService.SaveSettingsAsync(oldSettings);
}
else
{
@ -340,10 +356,14 @@ namespace Ombi.UI.Modules.Admin
{
PlexAuthToken = model.user.authentication_token
};
PlexService.SaveSettings(newModel);
await PlexService.SaveSettingsAsync(newModel);
}
return Response.AsJson(new { Result = true, AuthToken = model.user.authentication_token });
var server = PlexApi.GetServer(model.user.authentication_token);
var machine =
server.Server.FirstOrDefault(x => x.AccessToken == model.user.authentication_token)?.MachineIdentifier;
return Response.AsJson(new { Result = true, AuthToken = model.user.authentication_token, Identifier = machine });
}
@ -441,13 +461,32 @@ namespace Ombi.UI.Modules.Admin
private async Task<Response> SavePlex()
{
var plexSettings = this.Bind<PlexSettings>();
var valid = this.Validate(plexSettings);
if (!valid.IsValid)
if (plexSettings.Enable)
{
var valid = this.Validate(plexSettings);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
}
if (plexSettings.Enable)
{
return Response.AsJson(valid.SendJsonError());
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Emby is enabled, we cannot enable Plex and Emby"
});
}
}
if (string.IsNullOrEmpty(plexSettings.MachineIdentifier))
if (string.IsNullOrEmpty(plexSettings.MachineIdentifier) && plexSettings.Enable)
{
//Lookup identifier
var server = PlexApi.GetServer(plexSettings.PlexAuthToken);
@ -462,6 +501,49 @@ namespace Ombi.UI.Modules.Admin
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private async Task<Negotiator> Emby()
{
var settings = await EmbySettings.GetSettingsAsync();
return View["Emby", settings];
}
private async Task<Response> SaveEmby()
{
var emby = this.Bind<EmbySettings>();
var valid = this.Validate(emby);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
if (emby.Enable)
{
var plexSettings = await PlexService.GetSettingsAsync();
if (plexSettings.Enable)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Plex is enabled, we cannot enable Plex and Emby"
});
}
}
// Get the users
var users = EmbyApi.GetUsers(emby.FullUri, emby.ApiKey);
// Find admin
var admin = users.FirstOrDefault(x => x.Policy.IsAdministrator);
emby.AdministratorId = admin?.Id;
var result = await EmbySettings.SaveSettingsAsync(emby);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Emby!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private Negotiator Sonarr()
{
var settings = SonarrService.GetSettings();
@ -757,6 +839,10 @@ namespace Ombi.UI.Modules.Admin
{
return Response.AsJson(valid.SendJsonError());
}
if (!settings.Enabled)
{
return Response.AsJson(new CouchPotatoProfiles{list = new List<ProfileList>()});
}
var profiles = CpApi.GetProfiles(settings.FullUri, settings.ApiKey);
// set the cache
@ -859,6 +945,10 @@ namespace Ombi.UI.Modules.Admin
var settings = await NewsLetterService.GetSettingsAsync();
return View["NewsletterSettings", settings];
}
private Negotiator MassEmailView()
{
return View["MassEmail"];
}
private async Task<Response> SaveNewsletter()
{
@ -1116,9 +1206,10 @@ namespace Ombi.UI.Modules.Admin
Analytics.TrackEventAsync(Category.Admin, Action.Update, "Update Landing Page", Username, CookieHelper.GetAnalyticClientId(Cookies));
var plexSettings = await PlexService.GetSettingsAsync();
if (string.IsNullOrEmpty(plexSettings.Ip))
var embySettings = await EmbySettings.GetSettingsAsync();
if (string.IsNullOrEmpty(plexSettings.Ip) && string.IsNullOrEmpty(embySettings.Ip))
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We cannot enable the landing page if Plex is not setup!" });
return Response.AsJson(new JsonResponseModel { Result = false, Message = "We cannot enable the landing page if Plex/Emby is not setup!" });
}
if (settings.Enabled && settings.EnabledNoticeTime && string.IsNullOrEmpty(settings.NoticeMessage))
@ -1137,6 +1228,10 @@ namespace Ombi.UI.Modules.Admin
{
var s = await ScheduledJobSettings.GetSettingsAsync();
var allJobs = await JobRecorder.GetJobsAsync();
var emby = await EmbySettings.GetSettingsAsync();
var plex = await PlexService.GetSettingsAsync();
var dict = new Dictionary<string, DateTime>();
@ -1150,13 +1245,32 @@ namespace Ombi.UI.Modules.Admin
}
else
{
dict.Add(j.Name,j.LastRun);
if (j.Name.Contains("Plex"))
{
if (plex.Enable)
{
dict.Add(j.Name, j.LastRun);
}
}
else if (j.Name.Contains("Emby"))
{
if (emby.Enable)
{
dict.Add(j.Name, j.LastRun);
}
}
else
{
dict.Add(j.Name, j.LastRun);
}
}
}
var model = new ScheduledJobsViewModel
{
Emby = emby.Enable,
Plex = plex.Enable,
CouchPotatoCacher = s.CouchPotatoCacher,
PlexAvailabilityChecker = s.PlexAvailabilityChecker,
SickRageCacher = s.SickRageCacher,
@ -1169,7 +1283,13 @@ namespace Ombi.UI.Modules.Admin
FaultQueueHandler = s.FaultQueueHandler,
PlexEpisodeCacher = s.PlexEpisodeCacher,
PlexUserChecker = s.PlexUserChecker,
UserRequestLimitResetter = s.UserRequestLimitResetter
UserRequestLimitResetter = s.UserRequestLimitResetter,
EmbyAvailabilityChecker = s.EmbyAvailabilityChecker,
EmbyContentCacher = s.EmbyContentCacher,
EmbyEpisodeCacher = s.EmbyEpisodeCacher,
EmbyUserChecker = s.EmbyUserChecker,
RadarrCacher = s.RadarrCacher,
WatcherCacher = s.WatcherCacher
};
return View["SchedulerSettings", model];
}
@ -1232,13 +1352,13 @@ namespace Ombi.UI.Modules.Admin
var model = this.Bind<NotificationSettingsV2>();
return View["NotificationSettings", model];
}
private Response RecentlyAddedTest()
private Response TestNewsletterAdminEmail()
{
try
{
Log.Debug("Clicked TEST");
RecentlyAdded.Test();
Log.Debug("Clicked Admin Newsletter Email Test");
RecentlyAdded.RecentlyAddedAdminTest();
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to administrator" });
}
catch (Exception e)
@ -1247,5 +1367,50 @@ namespace Ombi.UI.Modules.Admin
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
}
}
private Response TestMassAdminEmail()
{
try
{
var settings = this.Bind<MassEmailSettings>();
Log.Debug("Clicked Admin Mass Email Test");
if (settings.Subject == null) {
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Subject" });
}
if (settings.Body == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Body" });
}
MassEmail.MassEmailAdminTest(settings.Body.Replace("\n", "<br/>"), settings.Subject);
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to administrator" });
}
catch (Exception e)
{
Log.Error(e);
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
}
}
private Response SendMassEmail()
{
try
{
var settings = this.Bind<MassEmailSettings>();
Log.Debug("Clicked Admin Mass Email Test");
if (settings.Subject == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Subject" });
}
if (settings.Body == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please Set a Body" });
}
MassEmail.SendMassEmail(settings.Body.Replace("\n", "<br/>"), settings.Subject);
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Sent email to All users" });
}
catch (Exception e)
{
Log.Error(e);
return Response.AsJson(new JsonResponseModel { Result = false, Message = e.Message });
}
}
}
}

View file

@ -25,7 +25,10 @@
// ************************************************************************/
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using Nancy;
using Nancy.Responses.Negotiation;
using Ombi.Core;
using Ombi.Core.SettingModels;
@ -48,6 +51,7 @@ namespace Ombi.UI.Modules.Admin
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["Index", "/faultqueue"] = x => Index();
Get["DeleteFault", "/deleteFault", true] = async (x,ct) => await DeleteFault(Convert.ToInt32(Request.Form.id));
}
private IRepository<RequestQueue> RequestQueue { get; }
@ -69,5 +73,35 @@ namespace Ombi.UI.Modules.Admin
return View["RequestFaultQueue", model];
}
public async Task<Response> DeleteFault(int faultId)
{
if (faultId == 0)
{
return Response.AsJson(new JsonResponseModel
{
Result = true,
Message = "Fault does not exist"
});
}
var fault = await RequestQueue.GetAsync(faultId);
if (fault == null)
{
return Response.AsJson(new JsonResponseModel
{
Result = true,
Message = "Fault does not exist"
});
}
await RequestQueue.DeleteAsync(fault);
return Response.AsJson(new JsonResponseModel
{
Result = true
});
}
}
}

View file

@ -69,6 +69,7 @@ namespace Ombi.UI.Modules.Admin
Post["/sonarrrootfolders"] = _ => GetSonarrRootFolders();
Post["/radarrrootfolders"] = _ => GetSonarrRootFolders();
Get["/watcher", true] = async (x, ct) => await Watcher();
Post["/watcher", true] = async (x, ct) => await SaveWatcher();
@ -156,7 +157,7 @@ namespace Ombi.UI.Modules.Admin
var cp = await CpSettings.GetSettingsAsync();
if (cp.Enabled)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "CouchPotato is enabled, we cannot enable Watcher and CouchPotato" });
return Response.AsJson(new JsonResponseModel { Result = false, Message = "CouchPotato is enabled, we cannot enable Radarr and CouchPotato" });
}
var valid = this.Validate(radarrSettings);
@ -191,7 +192,22 @@ namespace Ombi.UI.Modules.Admin
{
var settings = this.Bind<SonarrSettings>();
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
// set the cache
if (rootFolders != null)
{
Cache.Set(CacheKeys.SonarrRootFolders, rootFolders);
}
return Response.AsJson(rootFolders);
}
private Response GetRadarrRootFolders()
{
var settings = this.Bind<RadarrSettings>();
var rootFolders = RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
// set the cache
if (rootFolders != null)

View file

@ -33,6 +33,7 @@ using Ombi.Core.SettingModels;
using Ombi.Helpers.Permissions;
using Ombi.Services.Interfaces;
using Ombi.Services.Jobs;
using Ombi.Services.Jobs.Interfaces;
using Ombi.UI.Models;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
@ -44,7 +45,8 @@ namespace Ombi.UI.Modules.Admin
ISecurityExtensions security, IPlexContentCacher contentCacher, ISonarrCacher sonarrCacher, IWatcherCacher watcherCacher,
IRadarrCacher radarrCacher, ICouchPotatoCacher cpCacher, IStoreBackup store, ISickRageCacher srCacher, IAvailabilityChecker plexChceker,
IStoreCleanup cleanup, IUserRequestLimitResetter requestLimit, IPlexEpisodeCacher episodeCacher, IRecentlyAdded recentlyAdded,
IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker) : base("admin", settingsService, security)
IFaultQueueHandler faultQueueHandler, IPlexUserChecker plexUserChecker, IEmbyAvailabilityChecker embyAvailabilityChecker, IEmbyEpisodeCacher embyEpisode,
IEmbyContentCacher embyContentCacher, IEmbyUserChecker embyUser) : base("admin", settingsService, security)
{
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
@ -62,6 +64,10 @@ namespace Ombi.UI.Modules.Admin
RecentlyAdded = recentlyAdded;
FaultQueueHandler = faultQueueHandler;
PlexUserChecker = plexUserChecker;
EmbyAvailabilityChecker = embyAvailabilityChecker;
EmbyContentCacher = embyContentCacher;
EmbyEpisodeCacher = embyEpisode;
EmbyUserChecker = embyUser;
Post["/schedulerun", true] = async (x, ct) => await ScheduleRun((string)Request.Form.key);
}
@ -80,10 +86,16 @@ namespace Ombi.UI.Modules.Admin
private IRecentlyAdded RecentlyAdded { get; }
private IFaultQueueHandler FaultQueueHandler { get; }
private IPlexUserChecker PlexUserChecker { get; }
private IEmbyAvailabilityChecker EmbyAvailabilityChecker { get; }
private IEmbyContentCacher EmbyContentCacher { get; }
private IEmbyEpisodeCacher EmbyEpisodeCacher { get; }
private IEmbyUserChecker EmbyUserChecker { get; }
private async Task<Response> ScheduleRun(string key)
{
await Task.Yield();
if (key.Equals(JobNames.PlexCacher, StringComparison.CurrentCultureIgnoreCase))
{
PlexContentCacher.CacheContent();
@ -132,7 +144,7 @@ namespace Ombi.UI.Modules.Admin
}
if (key.Equals(JobNames.RecentlyAddedEmail, StringComparison.CurrentCultureIgnoreCase))
{
RecentlyAdded.Start();
RecentlyAdded.StartNewsLetter();
}
if (key.Equals(JobNames.FaultQueueHandler, StringComparison.CurrentCultureIgnoreCase))
{
@ -142,6 +154,22 @@ namespace Ombi.UI.Modules.Admin
{
RequestLimit.Start();
}
if (key.Equals(JobNames.EmbyEpisodeCacher, StringComparison.CurrentCultureIgnoreCase))
{
EmbyEpisodeCacher.Start();
}
if (key.Equals(JobNames.EmbyCacher, StringComparison.CurrentCultureIgnoreCase))
{
EmbyContentCacher.CacheContent();
}
if (key.Equals(JobNames.EmbyChecker, StringComparison.CurrentCultureIgnoreCase))
{
EmbyAvailabilityChecker.CheckAndUpdateAll();
}
if (key.Equals(JobNames.EmbyUserChecker, StringComparison.CurrentCultureIgnoreCase))
{
EmbyUserChecker.Start();
}
return Response.AsJson(new JsonResponseModel { Result = true });

View file

@ -35,7 +35,10 @@ using MarkdownSharp;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
using Ombi.Api.Interfaces;
using Ombi.Common.Processes;
using Ombi.Core;
using Ombi.Core.Models;
using Ombi.Core.SettingModels;
using Ombi.Core.StatusChecker;
using Ombi.Helpers;
@ -49,11 +52,13 @@ namespace Ombi.UI.Modules.Admin
{
public class SystemStatusModule : BaseModule
{
public SystemStatusModule(ISettingsService<PlexRequestSettings> settingsService, ICacheProvider cache, ISettingsService<SystemSettings> ss, ISecurityExtensions security, IAnalytics a) : base("admin", settingsService, security)
public SystemStatusModule(ISettingsService<PlexRequestSettings> settingsService, ICacheProvider cache, ISettingsService<SystemSettings> ss,
ISecurityExtensions security, IAnalytics a, IAppveyorApi appveyor) : base("admin", settingsService, security)
{
Cache = cache;
SystemSettings = ss;
Analytics = a;
AppveyorApi = appveyor;
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
@ -61,11 +66,13 @@ namespace Ombi.UI.Modules.Admin
Post["/save", true] = async (x, ct) => await Save();
Post["/autoupdate"] = x => AutoUpdate();
Get["/changes", true] = async (x, ct) => await GetLatestChanges();
}
private ICacheProvider Cache { get; }
private ISettingsService<SystemSettings> SystemSettings { get; }
private IAnalytics Analytics { get; }
private IAppveyorApi AppveyorApi { get; }
private async Task<Negotiator> Status()
{
@ -81,19 +88,19 @@ namespace Ombi.UI.Modules.Admin
{
new BranchDropdown
{
Name = EnumHelper<Branches>.GetDisplayValue(Branches.Stable),
Name =EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Stable).DisplayName,
Value = Branches.Stable,
Selected = settings.Branch == Branches.Stable
},
new BranchDropdown
{
Name = EnumHelper<Branches>.GetDisplayValue(Branches.EarlyAccessPreview),
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.EarlyAccessPreview).DisplayName,
Value = Branches.EarlyAccessPreview,
Selected = settings.Branch == Branches.EarlyAccessPreview
},
new BranchDropdown
{
Name = EnumHelper<Branches>.GetDisplayValue(Branches.Dev),
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Dev).DisplayName,
Value = Branches.Dev,
Selected = settings.Branch == Branches.Dev
},
@ -102,6 +109,34 @@ namespace Ombi.UI.Modules.Admin
return View["Status", settings];
}
public async Task<Response> GetLatestChanges()
{
var settings = await SystemSettings.GetSettingsAsync();
var branchName = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(settings.Branch).BranchName;
var changes = AppveyorApi.GetProjectHistory(branchName);
var currentVersion = AssemblyHelper.GetProductVersion();
var model = new List<RecentUpdatesModel>();
foreach (var build in changes.builds)
{
model.Add(new RecentUpdatesModel
{
Date = build.finished,
Message = BuildAppveyorMessage(build.message, build.messageExtended),
Version = build.version,
Installed = currentVersion.Equals(build.version, StringComparison.CurrentCultureIgnoreCase) ,
Branch = branchName
});
}
return Response.AsJson(model);
}
private string BuildAppveyorMessage(string message, string extended)
{
return extended == null ? message : $"{message} {extended}";
}
private async Task<Response> Save()
{
@ -123,7 +158,7 @@ namespace Ombi.UI.Modules.Admin
var url = Request.Form["url"];
var args = (string)Request.Form["args"].ToString();
var lowered = args.ToLower();
var appPath = Path.Combine(Path.GetDirectoryName(Assembly.GetAssembly(typeof(SystemStatusModule)).Location ?? string.Empty) ?? string.Empty, "Ombi.Updater.exe");
var appPath = Path.Combine(Path.GetDirectoryName(Assembly.GetAssembly(typeof(SystemStatusModule)).Location ?? string.Empty) ?? string.Empty, Path.Combine("UpdateService", "Ombi.Updater.exe"));
if (!string.IsNullOrEmpty(lowered))
{
@ -133,7 +168,7 @@ namespace Ombi.UI.Modules.Admin
}
}
var startArgs = string.IsNullOrEmpty(lowered) ? appPath : $"{lowered} Ombi.Updater.exe";
var startArgs = string.IsNullOrEmpty(lowered) || lowered == "Nancy.DynamicDictionaryValue".ToLower() ? appPath : $"{lowered} Ombi.Updater.exe";
var startInfo = Type.GetType("Mono.Runtime") != null
? new ProcessStartInfo(startArgs) { Arguments = $"{url} {lowered}", }
@ -141,7 +176,7 @@ namespace Ombi.UI.Modules.Admin
Process.Start(startInfo);
Environment.Exit(0);
//Environment.Exit(0);
return Nancy.Response.NoBody;
}

View file

@ -46,7 +46,7 @@ namespace Ombi.UI.Modules
public ApplicationTesterModule(ICouchPotatoApi cpApi, ISonarrApi sonarrApi, IPlexApi plexApi,
ISickRageApi srApi, IHeadphonesApi hpApi, ISettingsService<PlexRequestSettings> pr, ISecurityExtensions security,
IWatcherApi watcherApi, IRadarrApi radarrApi) : base("test", pr, security)
IWatcherApi watcherApi, IRadarrApi radarrApi, IEmbyApi emby) : base("test", pr, security)
{
this.RequiresAuthentication();
@ -57,6 +57,7 @@ namespace Ombi.UI.Modules
HeadphonesApi = hpApi;
WatcherApi = watcherApi;
RadarrApi = radarrApi;
Emby = emby;
Post["/cp"] = _ => CouchPotatoTest();
Post["/sonarr"] = _ => SonarrTest();
@ -66,6 +67,7 @@ namespace Ombi.UI.Modules
Post["/headphones"] = _ => HeadphonesTest();
Post["/plexdb"] = _ => TestPlexDb();
Post["/watcher"] = _ => WatcherTest();
Post["/emby"] = _ => EmbyTest();
}
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
@ -76,6 +78,7 @@ namespace Ombi.UI.Modules
private IHeadphonesApi HeadphonesApi { get; }
private IWatcherApi WatcherApi { get; }
private IRadarrApi RadarrApi { get; }
private IEmbyApi Emby { get; set; }
private Response CouchPotatoTest()
{
@ -213,7 +216,7 @@ namespace Ombi.UI.Modules
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Plex, please check your settings." });
}
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
{
Log.Warn("Exception thrown when attempting to get Plex's status: ");
Log.Warn(e);
@ -225,6 +228,35 @@ namespace Ombi.UI.Modules
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
}
}
private Response EmbyTest()
{
var emby = this.Bind<EmbySettings>();
var valid = this.Validate(emby);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
try
{
var status = Emby.GetUsers(emby?.FullUri, emby?.ApiKey);
return status != null
? Response.AsJson(new JsonResponseModel { Result = true, Message = "Connected to Emby successfully!" })
: Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not connect to Emby, please check your settings." });
}
catch (Exception e) // Exceptions are expected, if we cannot connect so we will just log and swallow them.
{
Log.Warn("Exception thrown when attempting to get Emby's users: ");
Log.Warn(e);
var message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.Message}";
if (e.InnerException != null)
{
message = $"Could not connect to Emby, please check your settings. <strong>Exception Message:</strong> {e.InnerException.Message}";
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = message });
}
}
private Response SickRageTest()
{

View file

@ -193,7 +193,7 @@ namespace Ombi.UI.Modules
{
// Approve it
request.Approved = true;
Log.Warn("We approved movie: {0} but could not add it to CouchPotato/Watcher because it has not been setup", request.Title);
Log.Warn("We approved movie: {0} but could not add it to CouchPotato/Watcher/Radarr because it has not been setup", request.Title);
// Update the record
var inserted = await Service.UpdateRequestAsync(request);

View file

@ -145,7 +145,7 @@ namespace Ombi.UI.Modules
Deleted = issue.Deleted,
Type = issue.Type,
ProviderId = issue.ProviderId,
PosterUrl = issue.PosterUrl,
PosterUrl = issue.PosterUrl.Contains("https://image.tmdb.org/t/p/w150/") ? issue.PosterUrl : $"https://image.tmdb.org/t/p/w150/{issue.PosterUrl}",
Id = issue.Id
};
return View["Details", m];

View file

@ -40,12 +40,15 @@ namespace Ombi.UI.Modules
public class LandingPageModule : BaseModule
{
public LandingPageModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<LandingPageSettings> landing,
ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security) : base("landing", settingsService, security)
ISettingsService<PlexSettings> ps, IPlexApi pApi, IResourceLinker linker, ISecurityExtensions security, ISettingsService<EmbySettings> emby,
IEmbyApi embyApi) : base("landing", settingsService, security)
{
LandingSettings = landing;
PlexSettings = ps;
PlexApi = pApi;
Linker = linker;
EmbySettings = emby;
EmbyApi = embyApi;
Get["LandingPageIndex","/", true] = async (x, ct) =>
{
@ -75,26 +78,49 @@ namespace Ombi.UI.Modules
private ISettingsService<LandingPageSettings> LandingSettings { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IPlexApi PlexApi { get; }
private IEmbyApi EmbyApi { get; }
private IResourceLinker Linker { get; }
private async Task<Response> CheckStatus()
{
var plexSettings = await PlexSettings.GetSettingsAsync();
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
if (plexSettings.Enable)
{
return Response.AsJson(false);
}
try
{
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri);
return Response.AsJson(status != null);
}
catch (Exception)
{
return Response.AsJson(false);
if (string.IsNullOrEmpty(plexSettings.PlexAuthToken) || string.IsNullOrEmpty(plexSettings.Ip))
{
return Response.AsJson(false);
}
try
{
var status = PlexApi.GetStatus(plexSettings.PlexAuthToken, plexSettings.FullUri);
return Response.AsJson(status != null);
}
catch (Exception)
{
return Response.AsJson(false);
}
}
var emby = await EmbySettings.GetSettingsAsync();
if (emby.Enable)
{
if (string.IsNullOrEmpty(emby.AdministratorId) || string.IsNullOrEmpty(emby.Ip))
{
return Response.AsJson(false);
}
try
{
var status = EmbyApi.GetSystemInformation(emby.ApiKey, emby.FullUri);
return Response.AsJson(status?.Version != null);
}
catch (Exception)
{
return Response.AsJson(false);
}
}
return Response.AsJson(false);
}
}
}

View file

@ -29,10 +29,12 @@ using System;
using System.Linq;
using System.Threading.Tasks;
using Nancy;
using Nancy.Responses;
using NLog;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Core.StatusChecker;
using Ombi.Core.Users;
using Ombi.Helpers;
using Ombi.Services.Interfaces;
using Ombi.Services.Jobs;
@ -43,14 +45,16 @@ namespace Ombi.UI.Modules
{
public class LayoutModule : BaseAuthModule
{
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec, ISecurityExtensions security) : base("layout", pr, security)
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec, ISecurityExtensions security, IUserHelper helper) : base("layout", pr, security)
{
Cache = provider;
SystemSettings = settings;
Job = rec;
UserHelper = helper;
Get["/", true] = async (x,ct) => await CheckLatestVersion();
Get["/cacher", true] = async (x,ct) => await CacherRunning();
Get["/gravatar"] = x => GetGravatarImage();
}
private ICacheProvider Cache { get; }
@ -58,6 +62,7 @@ namespace Ombi.UI.Modules
private static Logger Log = LogManager.GetCurrentClassLogger();
private ISettingsService<SystemSettings> SystemSettings { get; }
private IJobRecord Job { get; }
private IUserHelper UserHelper { get; }
private async Task<Response> CheckLatestVersion()
{
@ -116,5 +121,31 @@ namespace Ombi.UI.Modules
return Response.AsJson(new { CurrentlyRunning = false, IsAdmin });
}
}
private Response GetGravatarImage()
{
if (LoggedIn)
{
var user = UserHelper.GetUser(Username);
var hashed = StringHasher.CalcuateMd5Hash(user.EmailAddress);
if (string.IsNullOrEmpty(hashed))
{
return Response.AsJson(new JsonResponseModel
{
Result = false
});
}
return
Response.AsJson(new JsonResponseModel
{
Result = true,
Message = $"https://www.gravatar.com/avatar/{hashed}"
});
}
else
{
return Response.AsJson(new JsonResponseModel {Result = false});
}
}
}
}

View file

@ -33,6 +33,7 @@ using Nancy;
using Nancy.Responses.Negotiation;
using NLog;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Sonarr;
using Ombi.Core;
using Ombi.Core.Models;
using Ombi.Core.SettingModels;
@ -65,9 +66,13 @@ namespace Ombi.UI.Modules
ISickRageApi sickRageApi,
ICacheProvider cache,
IAnalytics an,
INotificationEngine engine,
IPlexNotificationEngine engine,
IEmbyNotificationEngine embyEngine,
ISecurityExtensions security,
ISettingsService<CustomizationSettings> customSettings) : base("requests", prSettings, security)
ISettingsService<CustomizationSettings> customSettings,
ISettingsService<EmbySettings> embyS,
ISettingsService<RadarrSettings> radarr,
IRadarrApi radarrApi) : base("requests", prSettings, security)
{
Service = service;
PrSettings = prSettings;
@ -81,8 +86,12 @@ namespace Ombi.UI.Modules
CpApi = cpApi;
Cache = cache;
Analytics = an;
NotificationEngine = engine;
PlexNotificationEngine = engine;
EmbyNotificationEngine = embyEngine;
CustomizationSettings = customSettings;
EmbySettings = embyS;
Radarr = radarr;
RadarrApi = radarrApi;
Get["/", true] = async (x, ct) => await LoadRequests();
Get["/movies", true] = async (x, ct) => await GetMovies();
@ -96,7 +105,8 @@ namespace Ombi.UI.Modules
Post["/changeavailability", true] = async (x, ct) => await ChangeRequestAvailability((int)Request.Form.Id, (bool)Request.Form.Available);
Post["/changeRootFolder", true] = async (x, ct) => await ChangeRootFolder((int) Request.Form.requestId, (int) Request.Form.rootFolderId);
Post["/changeRootFoldertv", true] = async (x, ct) => await ChangeRootFolder(RequestType.TvShow, (int)Request.Form.requestId, (int)Request.Form.rootFolderId);
Post["/changeRootFoldermovie", true] = async (x, ct) => await ChangeRootFolder(RequestType.Movie, (int)Request.Form.requestId, (int)Request.Form.rootFolderId);
Get["/UpdateFilters", true] = async (x, ct) => await GetFilterAndSortSettings();
}
@ -111,11 +121,15 @@ namespace Ombi.UI.Modules
private ISettingsService<SickRageSettings> SickRageSettings { get; }
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
private ISettingsService<RadarrSettings> Radarr { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private ISonarrApi SonarrApi { get; }
private IRadarrApi RadarrApi { get; }
private ISickRageApi SickRageApi { get; }
private ICouchPotatoApi CpApi { get; }
private ICacheProvider Cache { get; }
private INotificationEngine NotificationEngine { get; }
private INotificationEngine PlexNotificationEngine { get; }
private INotificationEngine EmbyNotificationEngine { get; }
private async Task<Negotiator> LoadRequests()
{
@ -138,32 +152,64 @@ namespace Ombi.UI.Modules
}
List<QualityModel> qualities = new List<QualityModel>();
var rootFolders = new List<RootFolderModel>();
var radarr = await Radarr.GetSettingsAsync();
if (IsAdmin)
{
var cpSettings = CpSettings.GetSettings();
if (cpSettings.Enabled)
try
{
try
var cpSettings = await CpSettings.GetSettingsAsync();
if (cpSettings.Enabled)
{
var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () =>
try
{
return await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey)).ConfigureAwait(false);
});
if (result != null)
var result = await Cache.GetOrSetAsync(CacheKeys.CouchPotatoQualityProfiles, async () =>
{
return
await Task.Run(() => CpApi.GetProfiles(cpSettings.FullUri, cpSettings.ApiKey))
.ConfigureAwait(false);
});
if (result != null)
{
qualities =
result.list.Select(x => new QualityModel { Id = x._id, Name = x.label }).ToList();
}
}
catch (Exception e)
{
qualities = result.list.Select(x => new QualityModel { Id = x._id, Name = x.label }).ToList();
Log.Info(e);
}
}
catch (Exception e)
if (radarr.Enabled)
{
Log.Info(e);
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.RadarrRootFolders, async () =>
{
return await Task.Run(() => RadarrApi.GetRootFolders(radarr.ApiKey, radarr.FullUri));
});
rootFolders =
rootFoldersResult.Select(
x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace })
.ToList();
var result = await Cache.GetOrSetAsync(CacheKeys.RadarrQualityProfiles, async () =>
{
return await Task.Run(() => RadarrApi.GetProfiles(radarr.ApiKey, radarr.FullUri));
});
qualities = result.Select(x => new QualityModel { Id = x.id.ToString(), Name = x.name }).ToList();
}
}
catch (Exception e)
{
Log.Error(e);
}
}
var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests);
var allowViewUsers = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ViewUsers);
var viewModel = dbMovies.Select(movie => new RequestViewModel
{
ProviderId = movie.ProviderId,
@ -180,7 +226,7 @@ namespace Ombi.UI.Modules
Approved = movie.Available || movie.Approved,
Title = movie.Title,
Overview = movie.Overview,
RequestedUsers = canManageRequest ? movie.AllUsers.ToArray() : new string[] { },
RequestedUsers = canManageRequest || allowViewUsers ? movie.AllUsers.ToArray() : new string[] { },
ReleaseYear = movie.ReleaseDate.Year.ToString(),
Available = movie.Available,
Admin = canManageRequest,
@ -188,6 +234,9 @@ namespace Ombi.UI.Modules
Denied = movie.Denied,
DeniedReason = movie.DeniedReason,
Qualities = qualities.ToArray(),
HasRootFolders = rootFolders.Any(),
RootFolders = rootFolders.ToArray(),
CurrentRootPath = radarr.Enabled ? GetRootPath(movie.RootFolderSelected, radarr).Result : null
}).ToList();
return Response.AsJson(viewModel);
@ -220,14 +269,14 @@ namespace Ombi.UI.Modules
});
qualities = result.Select(x => new QualityModel { Id = x.id.ToString(), Name = x.name }).ToList();
var rootFoldersResult =await Cache.GetOrSetAsync(CacheKeys.SonarrRootFolders, async () =>
{
return await Task.Run(() => SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri));
});
rootFolders = rootFoldersResult.Select(x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace}).ToList();
}
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.SonarrRootFolders, async () =>
{
return await Task.Run(() => SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri));
});
rootFolders = rootFoldersResult.Select(x => new RootFolderModel { Id = x.id.ToString(), Path = x.path, FreeSpace = x.freespace }).ToList();
}
else
{
var sickRageSettings = await SickRageSettings.GetSettingsAsync();
@ -247,6 +296,8 @@ namespace Ombi.UI.Modules
var canManageRequest = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ManageRequests);
var allowViewUsers = Security.HasAnyPermissions(User, Permissions.Administrator, Permissions.ViewUsers);
var viewModel = dbTv.Select(tv => new RequestViewModel
{
ProviderId = tv.ProviderId,
@ -254,7 +305,7 @@ namespace Ombi.UI.Modules
Status = tv.Status,
ImdbId = tv.ImdbId,
Id = tv.Id,
PosterPath = tv.PosterPath.Contains("http:") ? tv.PosterPath.Replace("http:", "https:") : tv.PosterPath, // We make the poster path https on request, but this is just incase
PosterPath = tv.PosterPath?.Contains("http:") ?? false ? tv.PosterPath?.Replace("http:", "https:") : tv.PosterPath ?? string.Empty, // We make the poster path https on request, but this is just incase
ReleaseDate = tv.ReleaseDate,
ReleaseDateTicks = tv.ReleaseDate.Ticks,
RequestedDate = tv.RequestedDate,
@ -263,7 +314,7 @@ namespace Ombi.UI.Modules
Approved = tv.Available || tv.Approved,
Title = tv.Title,
Overview = tv.Overview,
RequestedUsers = canManageRequest ? tv.AllUsers.ToArray() : new string[] { },
RequestedUsers = canManageRequest || allowViewUsers ? tv.AllUsers.ToArray() : new string[] { },
ReleaseYear = tv.ReleaseDate.Year.ToString(),
Available = tv.Available,
Admin = canManageRequest,
@ -273,7 +324,7 @@ namespace Ombi.UI.Modules
TvSeriesRequestType = tv.SeasonsRequested,
Qualities = qualities.ToArray(),
Episodes = tv.Episodes.ToArray(),
RootFolders = rootFolders.ToArray(),
RootFolders = rootFolders.ToArray(),
HasRootFolders = rootFolders.Any(),
CurrentRootPath = sonarrSettings.Enabled ? GetRootPath(tv.RootFolderSelected, sonarrSettings).Result : null
}).ToList();
@ -293,13 +344,48 @@ namespace Ombi.UI.Modules
return r.path;
}
// Return default path
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(int.Parse(sonarrSettings.RootPath)))?.path ?? string.Empty;
int outRoot;
var defaultPath = int.TryParse(sonarrSettings.RootPath, out outRoot);
if (defaultPath)
{
// Return default path
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(outRoot))?.path ?? string.Empty;
}
else
{
return rootFoldersResult.FirstOrDefault()?.path ?? string.Empty;
}
}
private async Task<string> GetRootPath(int pathId, RadarrSettings radarrSettings)
{
var rootFoldersResult = await Cache.GetOrSetAsync(CacheKeys.RadarrRootFolders, async () =>
{
return await Task.Run(() => RadarrApi.GetRootFolders(radarrSettings.ApiKey, radarrSettings.FullUri));
});
foreach (var r in rootFoldersResult.Where(r => r.id == pathId))
{
return r.path;
}
int outRoot;
var defaultPath = int.TryParse(radarrSettings.RootPath, out outRoot);
if (defaultPath)
{
// Return default path
return rootFoldersResult.FirstOrDefault(x => x.id.Equals(outRoot))?.path ?? string.Empty;
}
else
{
return rootFoldersResult.FirstOrDefault()?.path ?? string.Empty;
}
}
private async Task<Response> GetAlbumRequests()
{
var settings = PrSettings.GetSettings();
var dbAlbum = await Service.GetAllAsync();
dbAlbum = dbAlbum.Where(x => x.Type == RequestType.Album);
if (Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests) && !IsAdmin)
@ -438,8 +524,21 @@ namespace Ombi.UI.Modules
originalRequest.Available = available;
var result = await Service.UpdateRequestAsync(originalRequest);
var plexService = await PlexSettings.GetSettingsAsync();
await NotificationEngine.NotifyUsers(originalRequest, plexService.PlexAuthToken, available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
var plexSettings = await PlexSettings.GetSettingsAsync();
if (plexSettings.Enable)
{
await
PlexNotificationEngine.NotifyUsers(originalRequest,
available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
await EmbyNotificationEngine.NotifyUsers(originalRequest,
available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined);
}
return Response.AsJson(result
? new { Result = true, Available = available, Message = string.Empty }
: new { Result = false, Available = false, Message = "Could not update the availability, please try again or check the logs" });
@ -461,11 +560,21 @@ namespace Ombi.UI.Modules
return Response.AsJson(vm);
}
private async Task<Response> ChangeRootFolder(int id, int rootFolderId)
private async Task<Response> ChangeRootFolder(RequestType type, int id, int rootFolderId)
{
// Get all root folders
var settings = await SonarrSettings.GetSettingsAsync();
var rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
var rootFolders = new List<SonarrRootFolder>();
if (type == RequestType.TvShow)
{
// Get all root folders
var settings = await SonarrSettings.GetSettingsAsync();
rootFolders = SonarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
}
else
{
var settings = await Radarr.GetSettingsAsync();
rootFolders = RadarrApi.GetRootFolders(settings.ApiKey, settings.FullUri);
}
// Get Request
var allRequests = await Service.GetAllAsync();
@ -473,7 +582,7 @@ namespace Ombi.UI.Modules
if (request == null)
{
return Response.AsJson(new JsonResponseModel {Result = false});
return Response.AsJson(new JsonResponseModel { Result = false });
}
foreach (var folder in rootFolders)
@ -487,7 +596,7 @@ namespace Ombi.UI.Modules
await Service.UpdateRequestAsync(request);
return Response.AsJson(new JsonResponseModel {Result = true});
}
}
return Response.AsJson(new JsonResponseModel { Result = true });
}
}
}

View file

@ -47,6 +47,8 @@ namespace Ombi.UI.Modules
public async Task<Response> Netflix(string title)
{
await Task.Yield();
var result = NetflixApi.CheckNetflix(title);
if (!string.IsNullOrEmpty(result.Message))

View file

@ -50,9 +50,11 @@ using Ombi.Helpers;
using Ombi.Helpers.Analytics;
using Ombi.Helpers.Permissions;
using Ombi.Services.Interfaces;
using Ombi.Services.Jobs;
using Ombi.Services.Notification;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Models.Emby;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
using Ombi.UI.Helpers;
@ -67,8 +69,8 @@ namespace Ombi.UI.Modules
{
public class SearchModule : BaseAuthModule
{
public SearchModule(ICacheProvider cache,
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker checker,
public SearchModule(ICacheProvider cache,
ISettingsService<PlexRequestSettings> prSettings, IAvailabilityChecker plexChecker,
IRequestService request, ISonarrApi sonarrApi, ISettingsService<SonarrSettings> sonarrSettings,
ISettingsService<SickRageSettings> sickRageService, ISickRageApi srApi,
INotificationService notify, IMusicBrainzApi mbApi, IHeadphonesApi hpApi,
@ -77,7 +79,8 @@ namespace Ombi.UI.Modules
ISettingsService<PlexSettings> plexService, ISettingsService<AuthenticationSettings> auth,
IRepository<UsersToNotify> u, ISettingsService<EmailNotificationSettings> email,
IIssueService issue, IAnalytics a, IRepository<RequestLimit> rl, ITransientFaultQueue tfQueue, IRepository<PlexContent> content,
ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher, ITraktApi traktApi, ISettingsService<CustomizationSettings> cus)
ISecurityExtensions security, IMovieSender movieSender, IRadarrCacher radarrCacher, ITraktApi traktApi, ISettingsService<CustomizationSettings> cus,
IEmbyAvailabilityChecker embyChecker, IRepository<EmbyContent> embyContent, ISettingsService<EmbySettings> embySettings)
: base("search", prSettings, security)
{
Auth = auth;
@ -86,7 +89,7 @@ namespace Ombi.UI.Modules
PrService = prSettings;
MovieApi = new TheMovieDbApi();
Cache = cache;
Checker = checker;
PlexChecker = plexChecker;
CpCacher = cpCacher;
SonarrCacher = sonarrCacher;
SickRageCacher = sickRageCacher;
@ -112,9 +115,14 @@ namespace Ombi.UI.Modules
RadarrCacher = radarrCacher;
TraktApi = traktApi;
CustomizationSettings = cus;
EmbyChecker = embyChecker;
EmbyContentRepository = embyContent;
EmbySettings = embySettings;
Get["SearchIndex", "/", true] = async (x, ct) => await RequestLoad();
Get["actor/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm);
Get["actor/new/{searchTerm}", true] = async (x, ct) => await SearchPerson((string)x.searchTerm, true);
Get["movie/{searchTerm}", true] = async (x, ct) => await SearchMovie((string)x.searchTerm);
Get["tv/{searchTerm}", true] = async (x, ct) => await SearchTvShow((string)x.searchTerm);
Get["music/{searchTerm}", true] = async (x, ct) => await SearchAlbum((string)x.searchTerm);
@ -135,7 +143,7 @@ namespace Ombi.UI.Modules
async (x, ct) => await RequestTvShow((int)Request.Form.tvId, (string)Request.Form.seasons);
Post["request/tvEpisodes", true] = async (x, ct) => await RequestTvShow(0, "episode");
Post["request/album", true] = async (x, ct) => await RequestAlbum((string)Request.Form.albumId);
Get["/seasons"] = x => GetSeasons();
Get["/episodes", true] = async (x, ct) => await GetEpisodes();
}
@ -143,6 +151,7 @@ namespace Ombi.UI.Modules
private IWatcherCacher WatcherCacher { get; }
private IMovieSender MovieSender { get; }
private IRepository<PlexContent> PlexContentRepository { get; }
private IRepository<EmbyContent> EmbyContentRepository { get; }
private TvMazeApi TvApi { get; }
private IPlexApi PlexApi { get; }
private TheMovieDbApi MovieApi { get; }
@ -152,13 +161,15 @@ namespace Ombi.UI.Modules
private IRequestService RequestService { get; }
private ICacheProvider Cache { get; }
private ISettingsService<AuthenticationSettings> Auth { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private ISettingsService<PlexSettings> PlexService { get; }
private ISettingsService<PlexRequestSettings> PrService { get; }
private ISettingsService<SonarrSettings> SonarrService { get; }
private ISettingsService<SickRageSettings> SickRageService { get; }
private ISettingsService<HeadphonesSettings> HeadphonesService { get; }
private ISettingsService<EmailNotificationSettings> EmailNotificationSettings { get; }
private IAvailabilityChecker Checker { get; }
private IAvailabilityChecker PlexChecker { get; }
private IEmbyAvailabilityChecker EmbyChecker { get; }
private ICouchPotatoCacher CpCacher { get; }
private ISonarrCacher SonarrCacher { get; }
private ISickRageCacher SickRageCacher { get; }
@ -173,15 +184,28 @@ namespace Ombi.UI.Modules
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
private long _plexMovieCacheTime = 0;
private IEnumerable<PlexContent> _plexMovies = null;
private long _embyMovieCacheTime = 0;
private IEnumerable<EmbyContent> _embyMovies = null;
private long _dbMovieCacheTime = 0;
private Dictionary<int, RequestedModel> _dbMovies = null;
private async Task<Negotiator> RequestLoad()
{
var settings = await PrService.GetSettingsAsync();
var custom = await CustomizationSettings.GetSettingsAsync();
var emby = await EmbySettings.GetSettingsAsync();
var plex = await PlexService.GetSettingsAsync();
var searchViewModel = new SearchLoadViewModel
{
Settings = settings,
CustomizationSettings = custom
CustomizationSettings = custom,
Emby = emby.Enable,
Plex = plex.Enable
};
@ -209,6 +233,53 @@ namespace Ombi.UI.Modules
return await ProcessMovies(MovieSearchType.Search, searchTerm);
}
private async Task<Response> SearchPerson(string searchTerm)
{
var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm));
return await TransformMovieResultsToResponse(movies);
}
private async Task<Response> SearchPerson(string searchTerm, bool filterExisting)
{
var movies = TransformMovieListToMovieResultList(await MovieApi.SearchPerson(searchTerm, AlreadyAvailable));
return await TransformMovieResultsToResponse(movies);
}
private async Task<bool> AlreadyAvailable(int id, string title, string year)
{
var plexSettings = await PlexService.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
return IsMovieInCache(id, String.Empty) ||
(plexSettings.Enable && PlexChecker.IsMovieAvailable(PlexMovies(), title, year)) ||
(embySettings.Enable && EmbyChecker.IsMovieAvailable(EmbyMovies(), title, year, String.Empty));
}
private IEnumerable<PlexContent> PlexMovies()
{ long now = DateTime.Now.Ticks;
if(_plexMovies == null || (now - _plexMovieCacheTime) > 10000)
{
var content = PlexContentRepository.GetAll();
_plexMovies = PlexChecker.GetPlexMovies(content);
_plexMovieCacheTime = now;
}
return _plexMovies;
}
private IEnumerable<EmbyContent> EmbyMovies()
{
long now = DateTime.Now.Ticks;
if (_embyMovies == null || (now - _embyMovieCacheTime) > 10000)
{
var content = EmbyContentRepository.GetAll();
_embyMovies = EmbyChecker.GetEmbyMovies(content);
_embyMovieCacheTime = now;
}
return _embyMovies;
}
private Response GetTvPoster(int theTvDbId)
{
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
@ -220,15 +291,10 @@ namespace Ombi.UI.Modules
}
return banner;
}
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
{
List<MovieResult> apiMovies;
switch (searchType)
{
case MovieSearchType.Search:
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
apiMovies = movies.Select(x =>
private List<MovieResult> TransformSearchMovieListToMovieResultList(List<TMDbLib.Objects.Search.SearchMovie> searchMovies)
{
return searchMovies.Select(x =>
new MovieResult
{
Adult = x.Adult,
@ -247,6 +313,39 @@ namespace Ombi.UI.Modules
VoteCount = x.VoteCount
})
.ToList();
}
private List<MovieResult> TransformMovieListToMovieResultList(List<TMDbLib.Objects.Movies.Movie> movies)
{
return movies.Select(x =>
new MovieResult
{
Adult = x.Adult,
BackdropPath = x.BackdropPath,
GenreIds = x.Genres.Select(y => y.Id).ToList(),
Id = x.Id,
OriginalLanguage = x.OriginalLanguage,
OriginalTitle = x.OriginalTitle,
Overview = x.Overview,
Popularity = x.Popularity,
PosterPath = x.PosterPath,
ReleaseDate = x.ReleaseDate,
Title = x.Title,
Video = x.Video,
VoteAverage = x.VoteAverage,
VoteCount = x.VoteCount
})
.ToList();
}
private async Task<Response> ProcessMovies(MovieSearchType searchType, string searchTerm)
{
List<MovieResult> apiMovies;
switch (searchType)
{
case MovieSearchType.Search:
var movies = await MovieApi.SearchMovie(searchTerm).ConfigureAwait(false);
apiMovies = TransformSearchMovieListToMovieResultList(movies);
break;
case MovieSearchType.CurrentlyPlaying:
apiMovies = await MovieApi.GetCurrentPlayingMovies();
@ -259,21 +358,31 @@ namespace Ombi.UI.Modules
break;
}
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.Movie);
return await TransformMovieResultsToResponse(apiMovies);
}
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
var dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
private async Task<Dictionary<int, RequestedModel>> RequestedMovies()
{
long now = DateTime.Now.Ticks;
if (_dbMovies == null || (now - _dbMovieCacheTime) > 10000)
{
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.Movie);
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
_dbMovies = distinctResults.ToDictionary(x => x.ProviderId);
_dbMovieCacheTime = now;
}
return _dbMovies;
}
var cpCached = CpCacher.QueuedIds();
var watcherCached = WatcherCacher.QueuedIds();
var radarrCached = RadarrCacher.QueuedIds();
var content = PlexContentRepository.GetAll();
var plexMovies = Checker.GetPlexMovies(content);
private async Task<Response> TransformMovieResultsToResponse(List<MovieResult> movies)
{
await Task.Yield();
var viewMovies = new List<SearchMovieViewModel>();
var counter = 0;
foreach (var movie in apiMovies)
Dictionary<int, RequestedModel> dbMovies = await RequestedMovies();
foreach (var movie in movies)
{
var viewMovie = new SearchMovieViewModel
{
@ -293,11 +402,10 @@ namespace Ombi.UI.Modules
VoteCount = movie.VoteCount
};
var imdbId = string.Empty;
if (counter <= 5) // Let's only do it for the first 5 items
{
var movieInfo = MovieApi.GetMovieInformationWithVideos(movie.Id);
// TODO needs to be careful about this, it's adding extra time to search...
// https://www.themoviedb.org/talk/5807f4cdc3a36812160041f2
viewMovie.ImdbId = movieInfo?.imdb_id;
@ -313,16 +421,37 @@ namespace Ombi.UI.Modules
counter++;
}
var canSee = CanUserSeeThisRequest(viewMovie.Id, Security.HasPermissions(User, Permissions.UsersCanViewOnlyOwnRequests), dbMovies);
var plexMovie = Checker.GetMovie(plexMovies.ToArray(), movie.Title, movie.ReleaseDate?.Year.ToString(),
imdbId);
if (plexMovie != null)
var plexSettings = await PlexService.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
if (plexSettings.Enable)
{
viewMovie.Available = true;
viewMovie.PlexUrl = plexMovie.Url;
var content = PlexContentRepository.GetAll();
var plexMovies = PlexChecker.GetPlexMovies(content);
var plexMovie = PlexChecker.GetMovie(plexMovies.ToArray(), movie.Title,
movie.ReleaseDate?.Year.ToString(),
viewMovie.ImdbId);
if (plexMovie != null)
{
viewMovie.Available = true;
viewMovie.PlexUrl = plexMovie.Url;
}
}
else if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
if (embySettings.Enable)
{
var embyContent = EmbyContentRepository.GetAll();
var embyMovies = EmbyChecker.GetEmbyMovies(embyContent);
var embyMovie = EmbyChecker.GetMovie(embyMovies.ToArray(), movie.Title,
movie.ReleaseDate?.Year.ToString(), viewMovie.ImdbId);
if (embyMovie != null)
{
viewMovie.Available = true;
}
}
if (dbMovies.ContainsKey(movie.Id) && canSee) // compare to the requests db
{
var dbm = dbMovies[movie.Id];
@ -330,20 +459,11 @@ namespace Ombi.UI.Modules
viewMovie.Approved = dbm.Approved;
viewMovie.Available = dbm.Available;
}
else if (cpCached.Contains(movie.Id) && canSee) // compare to the couchpotato db
else if (canSee)
{
viewMovie.Approved = true;
viewMovie.Requested = true;
}
else if(watcherCached.Contains(imdbId) && canSee) // compare to the watcher db
{
viewMovie.Approved = true;
viewMovie.Requested = true;
}
else if (radarrCached.Contains(movie.Id) && canSee)
{
viewMovie.Approved = true;
viewMovie.Requested = true;
bool exists = IsMovieInCache(movie, viewMovie.ImdbId);
viewMovie.Approved = exists;
viewMovie.Requested = exists;
}
viewMovies.Add(viewMovie);
}
@ -351,6 +471,19 @@ namespace Ombi.UI.Modules
return Response.AsJson(viewMovies);
}
private bool IsMovieInCache(MovieResult movie, string imdbId)
{ int id = movie.Id;
return IsMovieInCache(id, imdbId);
}
private bool IsMovieInCache(int id, string imdbId)
{ var cpCached = CpCacher.QueuedIds();
var watcherCached = WatcherCacher.QueuedIds();
var radarrCached = RadarrCacher.QueuedIds();
return cpCached.Contains(id) || watcherCached.Contains(imdbId) || radarrCached.Contains(id);
}
private bool CanUserSeeThisRequest(int movieId, bool usersCanViewOnlyOwnRequests,
Dictionary<int, RequestedModel> moviesInDb)
{
@ -372,11 +505,11 @@ namespace Ombi.UI.Modules
case ShowSearchType.Popular:
Analytics.TrackEventAsync(Category.Search, Action.TvShow, "Popular", Username, CookieHelper.GetAnalyticClientId(Cookies));
var popularShows = await TraktApi.GetPopularShows();
foreach (var popularShow in popularShows)
{
var theTvDbId = int.Parse(popularShow.Ids.Tvdb.ToString());
var model = new SearchTvShowViewModel
{
FirstAired = popularShow.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
@ -405,6 +538,11 @@ namespace Ombi.UI.Modules
{
var show = anticipatedShow.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel
{
@ -434,6 +572,12 @@ namespace Ombi.UI.Modules
{
var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel
{
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
@ -462,6 +606,12 @@ namespace Ombi.UI.Modules
{
var show = watched.Show;
var theTvDbId = int.Parse(show.Ids.Tvdb.ToString());
var result = TvApi.ShowLookupByTheTvDbId(theTvDbId);
if (result == null)
{
continue;
}
var model = new SearchTvShowViewModel
{
FirstAired = show.FirstAired?.ToString("yyyy-MM-ddTHH:mm:ss"),
@ -493,51 +643,55 @@ namespace Ombi.UI.Modules
private async Task<List<SearchTvShowViewModel>> MapToTvModel(List<SearchTvShowViewModel> shows, PlexRequestSettings prSettings)
{
var plexSettings = await PlexService.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
var providerId = string.Empty;
// Get the requests
var allResults = await RequestService.GetAllAsync();
allResults = allResults.Where(x => x.Type == RequestType.TvShow);
var distinctResults = allResults.DistinctBy(x => x.ProviderId);
var dbTv = distinctResults.ToDictionary(x => x.ProviderId);
// Check the external applications
var sonarrCached = SonarrCacher.QueuedIds().ToList();
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
var dbTv = distinctResults.ToDictionary(x => x.ImdbId);
var content = PlexContentRepository.GetAll();
var plexTvShows = Checker.GetPlexTvShows(content).ToList();
var plexTvShows = PlexChecker.GetPlexTvShows(content);
var embyContent = EmbyContentRepository.GetAll();
var embyCached = EmbyChecker.GetEmbyTvShows(embyContent).ToList();
foreach (var show in shows)
{
if (plexSettings.AdvancedSearch)
var providerId = show.Id.ToString();
if (embySettings.Enable)
{
providerId = show.Id.ToString();
var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4), providerId);
if (embyShow != null)
{
show.Available = true;
}
}
if (plexSettings.Enable)
{
var plexShow = PlexChecker.GetTvShow(plexTvShows.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4),
providerId);
if (plexShow != null)
{
show.Available = true;
show.PlexUrl = plexShow.Url;
}
}
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), show.SeriesName, show.FirstAired?.Substring(0, 4),
providerId);
if (plexShow != null)
if (show.ImdbId != null && !show.Available)
{
show.Available = true;
show.PlexUrl = plexShow.Url;
}
else
{
if (dbTv.ContainsKey(show.Id))
var imdbId = show.ImdbId;
if (dbTv.ContainsKey(imdbId))
{
var dbt = dbTv[show.Id];
var dbt = dbTv[imdbId];
show.Requested = true;
show.Episodes = dbt.Episodes.ToList();
show.Approved = dbt.Approved;
}
if (sonarrCached.Select(x => x.TvdbId).Contains(show.Id) || sickRageCache.Contains(show.Id))
// compare to the sonarr/sickrage db
{
show.Requested = true;
}
}
}
return shows;
@ -549,6 +703,7 @@ namespace Ombi.UI.Modules
Analytics.TrackEventAsync(Category.Search, Action.TvShow, searchTerm, Username,
CookieHelper.GetAnalyticClientId(Cookies));
var plexSettings = await PlexService.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
var prSettings = await PrService.GetSettingsAsync();
var providerId = string.Empty;
@ -571,7 +726,9 @@ namespace Ombi.UI.Modules
var sonarrCached = SonarrCacher.QueuedIds();
var sickRageCache = SickRageCacher.QueuedIds(); // consider just merging sonarr/sickrage arrays
var content = PlexContentRepository.GetAll();
var plexTvShows = Checker.GetPlexTvShows(content);
var plexTvShows = PlexChecker.GetPlexTvShows(content);
var embyContent = EmbyContentRepository.GetAll();
var embyCached = EmbyChecker.GetEmbyTvShows(embyContent);
var viewTv = new List<SearchTvShowViewModel>();
foreach (var t in apiTv)
@ -605,20 +762,28 @@ namespace Ombi.UI.Modules
EnableTvRequestsForOnlySeries = (prSettings.DisableTvRequestsByEpisode && prSettings.DisableTvRequestsBySeason)
};
providerId = viewT.Id.ToString();
if (plexSettings.AdvancedSearch)
if (embySettings.Enable)
{
providerId = viewT.Id.ToString();
var embyShow = EmbyChecker.GetTvShow(embyCached.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4), providerId);
if (embyShow != null)
{
viewT.Available = true;
}
}
var plexShow = Checker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
if (plexSettings.Enable)
{
var plexShow = PlexChecker.GetTvShow(plexTvShows.ToArray(), t.show.name, t.show.premiered?.Substring(0, 4),
providerId);
if (plexShow != null)
{
viewT.Available = true;
viewT.PlexUrl = plexShow.Url;
if (plexShow != null)
{
viewT.Available = true;
viewT.PlexUrl = plexShow.Url;
}
}
else if (t.show?.externals?.thetvdb != null)
if (t.show?.externals?.thetvdb != null && !viewT.Available)
{
var tvdbid = (int)t.show.externals.thetvdb;
if (dbTv.ContainsKey(tvdbid))
@ -658,7 +823,7 @@ namespace Ombi.UI.Modules
var dbAlbum = allResults.ToDictionary(x => x.MusicBrainzId);
var content = PlexContentRepository.GetAll();
var plexAlbums = Checker.GetPlexAlbums(content);
var plexAlbums = PlexChecker.GetPlexAlbums(content);
var viewAlbum = new List<SearchMusicViewModel>();
foreach (var a in apiAlbums)
@ -678,7 +843,7 @@ namespace Ombi.UI.Modules
DateTime release;
DateTimeHelper.CustomParse(a.ReleaseEvents?.FirstOrDefault()?.date, out release);
var artist = a.ArtistCredit?.FirstOrDefault()?.artist;
var plexAlbum = Checker.GetAlbum(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name);
var plexAlbum = PlexChecker.GetAlbum(plexAlbums.ToArray(), a.title, release.ToString("yyyy"), artist?.name);
if (plexAlbum != null)
{
viewA.Available = true;
@ -719,7 +884,7 @@ namespace Ombi.UI.Modules
Message = "You have reached your weekly request limit for Movies! Please contact your admin."
});
}
var embySettings = await EmbySettings.GetSettingsAsync();
Analytics.TrackEventAsync(Category.Search, Action.Request, "Movie", Username,
CookieHelper.GetAnalyticClientId(Cookies));
var movieInfo = await MovieApi.GetMovieInformation(movieId);
@ -760,8 +925,8 @@ namespace Ombi.UI.Modules
{
var content = PlexContentRepository.GetAll();
var movies = Checker.GetPlexMovies(content);
if (Checker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
var movies = PlexChecker.GetPlexMovies(content);
if (PlexChecker.IsMovieAvailable(movies.ToArray(), movieInfo.Title, movieInfo.ReleaseDate?.Year.ToString()))
{
return
Response.AsJson(new JsonResponseModel
@ -778,7 +943,7 @@ namespace Ombi.UI.Modules
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName)
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullMovieName,GetMediaServerName())
});
}
//#endif
@ -817,13 +982,13 @@ namespace Ombi.UI.Modules
return
Response.AsJson(new JsonResponseModel
{
Message = "Could not add movie, please contract your administrator",
Message = "Could not add movie, please contact your administrator",
Result = false
});
}
if (!result.MovieSendingEnabled)
{
return await AddRequest(model, settings, $"{fullMovieName} {Resources.UI.Search_SuccessfullyAdded}");
}
@ -918,7 +1083,7 @@ namespace Ombi.UI.Modules
});
}
}
var embySettings = await EmbySettings.GetSettingsAsync();
var showInfo = TvApi.ShowLookupByTheTvDbId(showId);
DateTime firstAir;
DateTime.TryParse(showInfo.premiered, out firstAir);
@ -1025,7 +1190,7 @@ namespace Ombi.UI.Modules
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,embySettings.Enable ? "Emby" : "Plex")}"
});
}
}
@ -1043,66 +1208,134 @@ namespace Ombi.UI.Modules
try
{
var content = PlexContentRepository.GetAll();
var shows = Checker.GetPlexTvShows(content);
var providerId = string.Empty;
var plexSettings = await PlexService.GetSettingsAsync();
if (plexSettings.AdvancedSearch)
if (plexSettings.Enable)
{
providerId = showId.ToString();
}
if (episodeRequest)
{
var cachedEpisodesTask = await Checker.GetEpisodes();
var cachedEpisodes = cachedEpisodesTask.ToList();
foreach (var d in difference) // difference is from an existing request
{
if (
cachedEpisodes.Any(
x =>
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
x.ProviderId == providerId))
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message =
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {Resources.UI.Search_AlreadyInPlex}"
});
}
}
var content = PlexContentRepository.GetAll();
var shows = PlexChecker.GetPlexTvShows(content);
var diff = await GetEpisodeRequestDifference(showId, model);
model.Episodes = diff.ToList();
}
else
{
if (plexSettings.EnableTvEpisodeSearching)
var providerId = string.Empty;
if (plexSettings.AdvancedSearch)
{
foreach (var s in showInfo.Season)
providerId = showId.ToString();
}
if (episodeRequest)
{
var cachedEpisodesTask = await PlexChecker.GetEpisodes();
var cachedEpisodes = cachedEpisodesTask.ToList();
foreach (var d in difference) // difference is from an existing request
{
var result = Checker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber, s.EpisodeNumber);
if (result)
if (
cachedEpisodes.Any(
x =>
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
x.ProviderId == providerId))
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
Message =
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
});
}
}
var diff = await GetEpisodeRequestDifference(showId, model);
model.Episodes = diff.ToList();
}
else if (Checker.IsTvShowAvailable(shows.ToArray(), showInfo.name, showInfo.premiered?.Substring(0, 4),
providerId, model.SeasonList))
else
{
return
Response.AsJson(new JsonResponseModel
if (plexSettings.EnableTvEpisodeSearching)
{
foreach (var s in showInfo.Season)
{
Result = false,
Message = $"{fullShowName} {Resources.UI.Search_AlreadyInPlex}"
});
var result = PlexChecker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber,
s.EpisodeNumber);
if (result)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
});
}
}
}
else if (PlexChecker.IsTvShowAvailable(shows.ToArray(), showInfo.name,
showInfo.premiered?.Substring(0, 4),
providerId, model.SeasonList))
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
});
}
}
}
if (embySettings.Enable)
{
var embyContent = EmbyContentRepository.GetAll();
var embyMovies = EmbyChecker.GetEmbyTvShows(embyContent);
var providerId = showId.ToString();
if (episodeRequest)
{
var cachedEpisodesTask = await EmbyChecker.GetEpisodes();
var cachedEpisodes = cachedEpisodesTask.ToList();
foreach (var d in difference) // difference is from an existing request
{
if (
cachedEpisodes.Any(
x =>
x.SeasonNumber == d.SeasonNumber && x.EpisodeNumber == d.EpisodeNumber &&
x.ProviderId == providerId))
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message =
$"{fullShowName} {d.SeasonNumber} - {d.EpisodeNumber} {string.Format(Resources.UI.Search_AlreadyInPlex,GetMediaServerName())}"
});
}
}
var diff = await GetEpisodeRequestDifference(showId, model);
model.Episodes = diff.ToList();
}
else
{
if (embySettings.EnableEpisodeSearching)
{
foreach (var s in showInfo.Season)
{
var result = EmbyChecker.IsEpisodeAvailable(showId.ToString(), s.SeasonNumber,
s.EpisodeNumber);
if (result)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} is already in Emby!"
});
}
}
}
else if (EmbyChecker.IsTvShowAvailable(embyMovies.ToArray(), showInfo.name,
showInfo.premiered?.Substring(0, 4),
providerId, model.SeasonList))
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"{fullShowName} is already in Emby!"
});
}
}
}
}
@ -1112,7 +1345,7 @@ namespace Ombi.UI.Modules
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName)
Message = string.Format(Resources.UI.Search_CouldNotCheckPlex, fullShowName,GetMediaServerName())
});
}
@ -1187,9 +1420,7 @@ namespace Ombi.UI.Modules
private bool ShouldSendNotification(RequestType type, PlexRequestSettings prSettings)
{
var sendNotification = ShouldAutoApprove(type)
? !prSettings.IgnoreNotifyForAutoApprovedRequests
: true;
var sendNotification = !ShouldAutoApprove(type) || !prSettings.IgnoreNotifyForAutoApprovedRequests;
if (IsAdmin)
{
@ -1261,8 +1492,8 @@ namespace Ombi.UI.Modules
var content = PlexContentRepository.GetAll();
var albums = Checker.GetPlexAlbums(content);
var alreadyInPlex = Checker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"),
var albums = PlexChecker.GetPlexAlbums(content);
var alreadyInPlex = PlexChecker.IsAlbumAvailable(albums.ToArray(), albumInfo.title, release.ToString("yyyy"),
artist.name);
if (alreadyInPlex)
@ -1280,6 +1511,7 @@ namespace Ombi.UI.Modules
{
Title = albumInfo.title,
MusicBrainzId = albumInfo.id,
ReleaseId = releaseId,
Overview = albumInfo.disambiguation,
PosterPath = img,
Type = RequestType.Album,
@ -1348,7 +1580,7 @@ namespace Ombi.UI.Modules
return img;
}
private Response GetSeasons()
{
var seriesId = (int)Request.Query.tvId;
@ -1390,7 +1622,8 @@ namespace Ombi.UI.Modules
var existingRequest = requests.FirstOrDefault(x => x.Type == RequestType.TvShow && x.TvDbId == providerId.ToString());
var show = await Task.Run(() => TvApi.ShowLookupByTheTvDbId(providerId));
var tvMaxeEpisodes = await Task.Run(() => TvApi.EpisodeLookup(show.id));
var tvMazeEpisodesTask = await Task.Run(() => TvApi.EpisodeLookup(show.id));
var tvMazeEpisodes = tvMazeEpisodesTask.ToList();
var sonarrEpisodes = new List<SonarrEpisodes>();
if (sonarrEnabled)
@ -1400,26 +1633,59 @@ namespace Ombi.UI.Modules
sonarrEpisodes = sonarrEp?.ToList() ?? new List<SonarrEpisodes>();
}
var plexCacheTask = await Checker.GetEpisodes(providerId);
var plexCache = plexCacheTask.ToList();
foreach (var ep in tvMaxeEpisodes)
var plexSettings = await PlexService.GetSettingsAsync();
if (plexSettings.Enable)
{
var requested = existingRequest?.Episodes
.Any(episodesModel =>
ep.number == episodesModel.EpisodeNumber && ep.season == episodesModel.SeasonNumber) ?? false;
var alreadyInPlex = plexCache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
var inSonarr = sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
model.Add(new EpisodeListViewModel
var plexCacheTask = await PlexChecker.GetEpisodes(providerId);
var plexCache = plexCacheTask.ToList();
foreach (var ep in tvMazeEpisodes)
{
Id = show.id,
SeasonNumber = ep.season,
EpisodeNumber = ep.number,
Requested = requested || alreadyInPlex || inSonarr,
Name = ep.name,
EpisodeId = ep.id
});
var requested = existingRequest?.Episodes
.Any(episodesModel =>
ep.number == episodesModel.EpisodeNumber &&
ep.season == episodesModel.SeasonNumber) ?? false;
var alreadyInPlex = plexCache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
var inSonarr =
sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
model.Add(new EpisodeListViewModel
{
Id = show.id,
SeasonNumber = ep.season,
EpisodeNumber = ep.number,
Requested = requested || alreadyInPlex || inSonarr,
Name = ep.name,
EpisodeId = ep.id
});
}
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
var embyCacheTask = await EmbyChecker.GetEpisodes(providerId);
var cache = embyCacheTask.ToList();
foreach (var ep in tvMazeEpisodes)
{
var requested = existingRequest?.Episodes
.Any(episodesModel =>
ep.number == episodesModel.EpisodeNumber &&
ep.season == episodesModel.SeasonNumber) ?? false;
var alreadyInEmby = cache.Any(x => x.EpisodeNumber == ep.number && x.SeasonNumber == ep.season);
var inSonarr =
sonarrEpisodes.Any(x => x.seasonNumber == ep.season && x.episodeNumber == ep.number && x.hasFile);
model.Add(new EpisodeListViewModel
{
Id = show.id,
SeasonNumber = ep.season,
EpisodeNumber = ep.number,
Requested = requested || alreadyInEmby || inSonarr,
Name = ep.name,
EpisodeId = ep.id
});
}
}
return model;
@ -1649,5 +1915,12 @@ namespace Ombi.UI.Modules
return
Response.AsJson(new JsonResponseModel { Result = false, Message = Resources.UI.Search_TvNotSetUp });
}
private string GetMediaServerName()
{
var e = EmbySettings.GetSettings();
return e.Enable ? "Emby" : "Plex";
}
}
}

View file

@ -34,7 +34,9 @@ using Nancy;
using Nancy.Extensions;
using Nancy.Linker;
using NLog;
using Ombi.Api;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Emby;
using Ombi.Api.Models.Plex;
using Ombi.Core;
using Ombi.Core.SettingModels;
@ -44,6 +46,8 @@ using Ombi.Helpers.Analytics;
using Ombi.Helpers.Permissions;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Models.Emby;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
using Ombi.UI.Authentication;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
@ -54,59 +58,23 @@ namespace Ombi.UI.Modules
public class UserLoginModule : BaseModule
{
public UserLoginModule(ISettingsService<AuthenticationSettings> auth, IPlexApi api, ISettingsService<PlexSettings> plexSettings, ISettingsService<PlexRequestSettings> pr,
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IPlexUserRepository plexUsers, ICustomUserMapper custom,
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings)
ISettingsService<LandingPageSettings> lp, IAnalytics a, IResourceLinker linker, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexUsers, ICustomUserMapper custom,
ISecurityExtensions security, ISettingsService<UserManagementSettings> userManagementSettings, IEmbyApi embyApi, ISettingsService<EmbySettings> emby, IExternalUserRepository<EmbyUsers> embyU)
: base("userlogin", pr, security)
{
AuthService = auth;
LandingPageSettings = lp;
Analytics = a;
Api = api;
PlexApi = api;
PlexSettings = plexSettings;
Linker = linker;
UserLogins = userLogins;
PlexUserRepository = plexUsers;
CustomUserMapper = custom;
UserManagementSettings = userManagementSettings;
//Get["UserLoginIndex", "/", true] = async (x, ct) =>
//{
// if (Request.Query["landing"] == null)
// {
// var s = await LandingPageSettings.GetSettingsAsync();
// if (s.Enabled)
// {
// if (s.BeforeLogin) // Before login
// {
// if (string.IsNullOrEmpty(Username))
// {
// // They are not logged in
// return
// Context.GetRedirect(Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString());
// }
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "SearchIndex").ToString());
// }
// // After login
// if (string.IsNullOrEmpty(Username))
// {
// // Not logged in yet
// return Context.GetRedirect(Linker.BuildRelativeUri(Context, "UserLoginIndex").ToString() + "?landing");
// }
// // Send them to landing
// var landingUrl = Linker.BuildRelativeUri(Context, "LandingPageIndex").ToString();
// return Context.GetRedirect(landingUrl);
// }
// }
// if (!string.IsNullOrEmpty(Username) || IsAdmin)
// {
// var url = Linker.BuildRelativeUri(Context, "SearchIndex").ToString();
// return Response.AsRedirect(url);
// }
// var settings = await AuthService.GetSettingsAsync();
// return View["Index", settings];
//};
EmbySettings = emby;
EmbyApi = embyApi;
EmbyUserRepository = embyU;
Post["/", true] = async (x, ct) => await LoginUser();
Get["/logout"] = x => Logout();
@ -157,11 +125,14 @@ namespace Ombi.UI.Modules
private ISettingsService<AuthenticationSettings> AuthService { get; }
private ISettingsService<LandingPageSettings> LandingPageSettings { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private IPlexApi Api { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IPlexApi PlexApi { get; }
private IEmbyApi EmbyApi { get; }
private IResourceLinker Linker { get; }
private IAnalytics Analytics { get; }
private IRepository<UserLogins> UserLogins { get; }
private IPlexUserRepository PlexUserRepository { get; }
private IExternalUserRepository<PlexUsers> PlexUserRepository { get; }
private IExternalUserRepository<EmbyUsers> EmbyUserRepository { get; }
private ICustomUserMapper CustomUserMapper { get; }
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
@ -180,41 +151,77 @@ namespace Ombi.UI.Modules
}
var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
var authenticated = false;
var isOwner = false;
var userId = string.Empty;
EmbyUser embyUser = null;
if (settings.UserAuthentication) // Check against the users in Plex
if (plexSettings.Enable)
{
Log.Debug("Need to auth");
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
if (authenticated)
if (settings.UserAuthentication) // Check against the users in Plex
{
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
Log.Debug("Need to auth");
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
if (authenticated)
{
userId = GetUserIdIsInPlexFriends(username, plexSettings.PlexAuthToken);
}
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
}
UsersModel dbUser = await IsDbuser(username);
if (dbUser != null) // in the db?
{
var perms = (Permissions) dbUser.Permissions;
authenticated = true;
isOwner = perms.HasFlag(Permissions.Administrator);
userId = dbUser.UserGuid;
}
Log.Debug("Friends list result = {0}", authenticated);
}
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, username))
else if (!settings.UserAuthentication) // No auth, let them pass!
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
userId = GetOwnerId(plexSettings.PlexAuthToken, username);
}
UsersModel dbUser = await IsDbuser(username);
if (dbUser != null) // in the db?
{
var perms = (Permissions)dbUser.Permissions;
authenticated = true;
isOwner = perms.HasFlag(Permissions.Administrator);
userId = dbUser.UserGuid;
}
Log.Debug("Friends list result = {0}", authenticated);
}
else if (!settings.UserAuthentication) // No auth, let them pass!
if (embySettings.Enable)
{
authenticated = true;
if (settings.UserAuthentication) // Check against the users in Plex
{
Log.Debug("Need to auth");
authenticated = CheckIfEmbyUser(username, embySettings);
if (authenticated)
{
embyUser = GetEmbyUser(username, embySettings);
userId = embyUser?.Id;
}
if (embyUser?.Policy?.IsAdministrator ?? false)
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
}
UsersModel dbUser = await IsDbuser(username);
if (dbUser != null) // in the db?
{
var perms = (Permissions)dbUser.Permissions;
authenticated = true;
isOwner = perms.HasFlag(Permissions.Administrator);
userId = dbUser.UserGuid;
}
Log.Debug("Friends list result = {0}", authenticated);
}
else if (!settings.UserAuthentication) // No auth, let them pass!
{
authenticated = true;
}
}
if (settings.UsePassword || isOwner || Security.HasPermissions(username, Permissions.Administrator))
{
Session[SessionKeys.UserLoginName] = username;
@ -230,7 +237,7 @@ namespace Ombi.UI.Modules
{
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
}
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
var result = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
var landingSettings = await LandingPageSettings.GetSettingsAsync();
@ -292,36 +299,68 @@ namespace Ombi.UI.Modules
var userId = string.Empty;
var plexSettings = await PlexSettings.GetSettingsAsync();
var embySettings = await EmbySettings.GetSettingsAsync();
if (settings.UserAuthentication) // Authenticate with Plex
// attempt local login first as it has the least amount of overhead
userId = CustomUserMapper.ValidateUser(username, password)?.ToString();
if (userId != null)
{
Log.Debug("Need to auth and also provide pass");
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
if (signedIn.user?.authentication_token != null)
authenticated = true;
}
else if (userId == null && plexSettings.Enable)
{
if (settings.UserAuthentication) // Authenticate with Plex
{
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
Log.Debug("Need to auth and also provide pass");
var signedIn = (PlexAuthentication) PlexApi.SignIn(username, password);
if (signedIn.user?.authentication_token != null)
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
if (CheckIfUserIsOwner(plexSettings.PlexAuthToken, signedIn.user?.username))
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
}
else
{
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
Log.Debug("Friends list result = {0}", authenticated);
}
userId = signedIn.user.uuid;
}
else
{
authenticated = CheckIfUserIsInPlexFriends(username, plexSettings.PlexAuthToken);
Log.Debug("Friends list result = {0}", authenticated);
}
userId = signedIn.user.uuid;
}
}
if (string.IsNullOrEmpty(userId))
else if (userId == null && embySettings.Enable)
{
// Local user?
userId = CustomUserMapper.ValidateUser(username, password)?.ToString();
if (userId != null)
if (settings.UserAuthentication) // Authenticate with Emby
{
authenticated = true;
Log.Debug("Need to auth and also provide pass");
EmbyUser signedIn = null;
try
{
signedIn = (EmbyUser)EmbyApi.LogIn(username, password, embySettings.ApiKey, embySettings.FullUri);
}
catch (Exception e)
{
Log.Error(e);
}
if (signedIn != null)
{
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
if (signedIn?.Policy?.IsAdministrator ?? false)
{
Log.Debug("User is the account owner");
authenticated = true;
isOwner = true;
}
else
{
authenticated = CheckIfEmbyUser(username, embySettings);
Log.Debug("Friends list result = {0}", authenticated);
}
userId = signedIn?.Id;
}
}
}
@ -330,8 +369,7 @@ namespace Ombi.UI.Modules
return Response.AsJson(new { result = false, message = Resources.UI.UserLogin_IncorrectUserPass });
}
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner);
var m = await AuthenticationSetup(userId, username, dateTimeOffset, loginGuid, isOwner, plexSettings.Enable, embySettings.Enable);
var landingSettings = await LandingPageSettings.GetSettingsAsync();
@ -354,7 +392,6 @@ namespace Ombi.UI.Modules
return CustomModuleExtensions.LoginAndRedirect(this, m.LoginGuid, null, retVal.ToString());
}
return Response.AsJson(new { result = true, url = retVal.ToString() });
}
private async Task<Response> LoginUser()
@ -399,7 +436,7 @@ namespace Ombi.UI.Modules
if (settings.UserAuthentication && settings.UsePassword) // Authenticate with Plex
{
Log.Debug("Need to auth and also provide pass");
var signedIn = (PlexAuthentication)Api.SignIn(username, password);
var signedIn = (PlexAuthentication)PlexApi.SignIn(username, password);
if (signedIn.user?.authentication_token != null)
{
Log.Debug("Correct credentials, checking if the user is account owner or in the friends list");
@ -553,59 +590,47 @@ namespace Ombi.UI.Modules
public string UserId { get; set; }
}
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner)
private async Task<LoginModel> AuthenticationSetup(string userId, string username, int dateTimeOffset, Guid loginGuid, bool isOwner, bool plex, bool emby)
{
var m = new LoginModel();
var settings = await AuthService.GetSettingsAsync();
var localUsers = await CustomUserMapper.GetUsersAsync();
var plexLocalUsers = await PlexUserRepository.GetAllAsync();
var embyLocalUsers = await EmbyUserRepository.GetAllAsync();
var localUser = false;
UserLogins.Insert(new UserLogins { UserId = userId, Type = UserType.PlexUser, LastLoggedIn = DateTime.UtcNow });
Log.Debug("We are authenticated! Setting session.");
// Add to the session (Used in the BaseModules)
Session[SessionKeys.UsernameKey] = username;
Session[SessionKeys.ClientDateTimeOffsetKey] = dateTimeOffset;
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
if (plexLocal != null)
if (plex)
{
loginGuid = Guid.Parse(plexLocal.LoginId);
var plexLocal = plexLocalUsers.FirstOrDefault(x => x.Username == username);
if (plexLocal != null)
{
loginGuid = Guid.Parse(plexLocal.LoginId);
}
}
if (emby)
{
var embyLocal = embyLocalUsers.FirstOrDefault(x => x.Username == username);
if (embyLocal != null)
{
loginGuid = Guid.Parse(embyLocal.LoginId);
}
}
var dbUser = localUsers.FirstOrDefault(x => x.UserName == username);
if (dbUser != null)
{
loginGuid = Guid.Parse(dbUser.UserGuid);
localUser = true;
}
//if (loginGuid != Guid.Empty)
//{
// if (!settings.UserAuthentication)// Do not need to auth make admin use login screen for now TODO remove this
// {
// if (dbUser != null)
// {
// var perms = (Permissions)dbUser.Permissions;
// if (perms.HasFlag(Permissions.Administrator))
// {
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
// //return Response.AsRedirect(uri.ToString());
// }
// }
// if (plexLocal != null)
// {
// var perms = (Permissions)plexLocal.Permissions;
// if (perms.HasFlag(Permissions.Administrator))
// {
// var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
// Session["TempMessage"] = Resources.UI.UserLogin_AdminUsePassword;
// //return Response.AsRedirect(uri.ToString());
// }
// }
// }
//}
if (loginGuid == Guid.Empty && settings.UserAuthentication)
{
var defaultSettings = UserManagementSettings.GetSettings();
@ -620,21 +645,52 @@ namespace Ombi.UI.Modules
defaultPermissions += (int)Permissions.Administrator;
}
}
// Looks like we still don't have an entry, so this user does not exist
await PlexUserRepository.InsertAsync(new PlexUsers
if (plex)
{
PlexUserId = userId,
UserAlias = string.Empty,
Permissions = (int)defaultPermissions,
Features = UserManagementHelper.GetPermissions(defaultSettings),
Username = username,
EmailAddress = string.Empty, // We don't have it, we will get it on the next scheduled job run (in 30 mins)
LoginId = loginGuid.ToString()
});
// Looks like we still don't have an entry, so this user does not exist
await PlexUserRepository.InsertAsync(new PlexUsers
{
PlexUserId = userId,
UserAlias = string.Empty,
Permissions = (int) defaultPermissions,
Features = UserManagementHelper.GetPermissions(defaultSettings),
Username = username,
EmailAddress = string.Empty,
// We don't have it, we will get it on the next scheduled job run (in 30 mins)
LoginId = loginGuid.ToString()
});
}
if (emby)
{
await EmbyUserRepository.InsertAsync(new EmbyUsers
{
EmbyUserId = userId,
UserAlias = string.Empty,
Permissions = (int)defaultPermissions,
Features = UserManagementHelper.GetPermissions(defaultSettings),
Username = username,
EmailAddress = string.Empty,
LoginId = loginGuid.ToString()
});
}
}
m.LoginGuid = loginGuid;
m.UserId = userId;
var type = UserType.LocalUser;
if (localUser)
{
type = UserType.LocalUser;
}
else if (plex)
{
type = UserType.PlexUser;
}
else if (emby)
{
type = UserType.EmbyUser;;
}
UserLogins.Insert(new UserLogins { UserId = userId, Type = type, LastLoggedIn = DateTime.UtcNow });
return m;
}
@ -651,7 +707,7 @@ namespace Ombi.UI.Modules
private bool CheckIfUserIsOwner(string authToken, string userName)
{
var userAccount = Api.GetAccount(authToken);
var userAccount = PlexApi.GetAccount(authToken);
if (userAccount == null)
{
return false;
@ -661,7 +717,7 @@ namespace Ombi.UI.Modules
private string GetOwnerId(string authToken, string userName)
{
var userAccount = Api.GetAccount(authToken);
var userAccount = PlexApi.GetAccount(authToken);
if (userAccount == null)
{
return string.Empty;
@ -671,15 +727,45 @@ namespace Ombi.UI.Modules
private bool CheckIfUserIsInPlexFriends(string username, string authToken)
{
var users = Api.GetUsers(authToken);
var users = PlexApi.GetUsers(authToken);
var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title));
return allUsers != null && allUsers.Any(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase));
}
private bool CheckIfEmbyUser(string username, EmbySettings s)
{
try
{
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
return allUsers != null && allUsers.Any(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
}
catch (Exception e)
{
Log.Error(e);
return false;
}
}
private EmbyUser GetEmbyUser(string username, EmbySettings s)
{
try
{
var users = EmbyApi.GetUsers(s.FullUri, s.ApiKey);
var allUsers = users?.Where(x => !string.IsNullOrEmpty(x.Name));
return allUsers?.FirstOrDefault(x => x.Name.Equals(username, StringComparison.CurrentCultureIgnoreCase));
}
catch (Exception e)
{
Log.Error(e);
return null;
}
}
private string GetUserIdIsInPlexFriends(string username, string authToken)
{
var users = Api.GetUsers(authToken);
var users = PlexApi.GetUsers(authToken);
var allUsers = users?.User?.Where(x => !string.IsNullOrEmpty(x.Title));
return allUsers?.Where(x => x.Title.Equals(username, StringComparison.CurrentCultureIgnoreCase)).Select(x => x.Id).FirstOrDefault();
}

View file

@ -7,6 +7,7 @@ using Nancy.Extensions;
using Nancy.Responses.Negotiation;
using Newtonsoft.Json;
using Ombi.Api.Interfaces;
using Ombi.Api.Models.Emby;
using Ombi.Api.Models.Plex;
using Ombi.Core;
using Ombi.Core.Models;
@ -16,6 +17,8 @@ using Ombi.Helpers.Analytics;
using Ombi.Helpers.Permissions;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Models.Emby;
using Ombi.Store.Models.Plex;
using Ombi.Store.Repository;
using Ombi.UI.Models;
using Ombi.UI.Models.UserManagement;
@ -26,8 +29,8 @@ namespace Ombi.UI.Modules
{
public class UserManagementModule : BaseModule
{
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins, IPlexUserRepository plexRepo
, ISecurityExtensions security, IRequestService req, IAnalytics ana) : base("usermanagement", pr, security)
public UserManagementModule(ISettingsService<PlexRequestSettings> pr, ICustomUserMapper m, IPlexApi plexApi, ISettingsService<PlexSettings> plex, IRepository<UserLogins> userLogins, IExternalUserRepository<PlexUsers> plexRepo
, ISecurityExtensions security, IRequestService req, IAnalytics ana, ISettingsService<EmbySettings> embyService, IEmbyApi embyApi, IExternalUserRepository<EmbyUsers> embyRepo) : base("usermanagement", pr, security)
{
#if !DEBUG
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
@ -40,6 +43,9 @@ namespace Ombi.UI.Modules
PlexRequestSettings = pr;
RequestService = req;
Analytics = ana;
EmbySettings = embyService;
EmbyApi = embyApi;
EmbyRepository = embyRepo;
Get["/"] = x => Load();
@ -57,10 +63,13 @@ namespace Ombi.UI.Modules
private IPlexApi PlexApi { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
private IRepository<UserLogins> UserLoginsRepo { get; }
private IPlexUserRepository PlexUsersRepository { get; }
private IExternalUserRepository<PlexUsers> PlexUsersRepository { get; }
private IExternalUserRepository<EmbyUsers> EmbyRepository { get; }
private ISettingsService<PlexRequestSettings> PlexRequestSettings { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private IRequestService RequestService { get; }
private IAnalytics Analytics { get; }
private IEmbyApi EmbyApi { get; }
private Negotiator Load()
{
@ -69,48 +78,19 @@ namespace Ombi.UI.Modules
private async Task<Response> LoadUsers()
{
var localUsers = await UserMapper.GetUsersAsync();
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
var model = new List<UserManagementUsersViewModel>();
var userLogins = UserLoginsRepo.GetAll().ToList();
foreach (var user in localUsers)
{
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
var plexSettings = await PlexSettings.GetSettingsAsync();
if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken))
var embySettings = await EmbySettings.GetSettingsAsync();
if (plexSettings.Enable)
{
//Get Plex Users
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
if (plexUsers != null && plexUsers.User != null) {
foreach (var u in plexUsers.User) {
var dbUser = plexDbUsers.FirstOrDefault (x => x.PlexUserId == u.Id);
var userDb = userLogins.FirstOrDefault (x => x.UserId == u.Id);
// We don't have the user in the database yet
if (dbUser == null) {
model.Add (MapPlexUser (u, null, userDb?.LastLoggedIn ?? DateTime.MinValue));
} else {
// The Plex User is in the database
model.Add (MapPlexUser (u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
}
}
// Also get the server admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (account != null)
{
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == account.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == account.Id);
model.Add(MapPlexAdmin(account, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
return await LoadPlexUsers();
}
return Response.AsJson(model);
if (embySettings.Enable)
{
return await LoadEmbyUsers();
}
return null;
}
private async Task<Response> CreateUser()
@ -217,64 +197,95 @@ namespace Ombi.UI.Modules
}
var plexSettings = await PlexSettings.GetSettingsAsync();
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (plexDbUser != null && plexUser != null)
if (plexSettings.Enable)
{
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
plexDbUser.EmailAddress = model.EmailAddress;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// So it could actually be the admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (plexDbUser != null && account != null)
{
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// We have a Plex Account but he's not in the DB
if (plexUser != null)
{
var user = new PlexUsers
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
var plexDbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == model.Id);
var plexUser = plexUsers.User.FirstOrDefault(x => x.Id == model.Id);
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (plexDbUser != null && plexUser != null)
{
Permissions = permissionsValue,
Features = featuresValue,
UserAlias = model.Alias,
PlexUserId = plexUser.Id,
EmailAddress = plexUser.Email,
Username = plexUser.Title,
LoginId = Guid.NewGuid().ToString()
};
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await PlexUsersRepository.InsertAsync(user);
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
plexDbUser.EmailAddress = model.EmailAddress;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexUser(plexUser, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// So it could actually be the admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (plexDbUser != null && account != null)
{
// We have a user in the DB for this Plex Account
plexDbUser.Permissions = permissionsValue;
plexDbUser.Features = featuresValue;
await UpdateRequests(plexDbUser.Username, plexDbUser.UserAlias, model.Alias);
plexDbUser.UserAlias = model.Alias;
await PlexUsersRepository.UpdateAsync(plexDbUser);
var retUser = MapPlexAdmin(account, plexDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
// We have a Plex Account but he's not in the DB
if (plexUser != null)
{
var user = new PlexUsers
{
Permissions = permissionsValue,
Features = featuresValue,
UserAlias = model.Alias,
PlexUserId = plexUser.Id,
EmailAddress = plexUser.Email,
Username = plexUser.Title,
LoginId = Guid.NewGuid().ToString()
};
await PlexUsersRepository.InsertAsync(user);
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (embySettings.Enable)
{
var embyDbUsers = await EmbyRepository.GetAllAsync();
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
var selectedDbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == model.Id);
var embyUser = embyUsers.FirstOrDefault(x => x.Id == model.Id);
var userLogin = UserLoginsRepo.GetAll().FirstOrDefault(x => x.UserId == model.Id);
if (selectedDbUser != null && embyUser != null)
{
// We have a user in the DB for this Plex Account
selectedDbUser.Permissions = permissionsValue;
selectedDbUser.Features = featuresValue;
await UpdateRequests(selectedDbUser.Username, selectedDbUser.UserAlias, model.Alias);
selectedDbUser.UserAlias = model.Alias;
selectedDbUser.EmailAddress = model.EmailAddress;
await EmbyRepository.UpdateAsync(selectedDbUser);
var retUser = MapEmbyUser(embyUser, selectedDbUser, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
var retUser = MapPlexUser(plexUser, user, userLogin?.LastLoggedIn ?? DateTime.MinValue);
return Response.AsJson(retUser);
}
return null; // We should never end up here.
}
@ -416,7 +427,7 @@ namespace Ombi.UI.Modules
var m = new UserManagementUsersViewModel
{
Id = plexInfo.Id,
PermissionsFormattedString = newUser ? "Processing..." :( permissions == 0 ? "None" : permissions.ToString()),
PermissionsFormattedString = newUser ? "Processing..." : (permissions == 0 ? "None" : permissions.ToString()),
FeaturesFormattedString = newUser ? "Processing..." : features.ToString(),
Username = plexInfo.Title,
Type = UserType.PlexUser,
@ -436,6 +447,36 @@ namespace Ombi.UI.Modules
return m;
}
private UserManagementUsersViewModel MapEmbyUser(EmbyUser embyInfo, EmbyUsers dbUser, DateTime lastLoggedIn)
{
var newUser = false;
if (dbUser == null)
{
newUser = true;
dbUser = new EmbyUsers();
}
var features = (Features)dbUser?.Features;
var permissions = (Permissions)dbUser?.Permissions;
var m = new UserManagementUsersViewModel
{
Id = embyInfo.Id,
PermissionsFormattedString = newUser ? "Processing..." : (permissions == 0 ? "None" : permissions.ToString()),
FeaturesFormattedString = newUser ? "Processing..." : features.ToString(),
Username = embyInfo.Name,
Type = UserType.EmbyUser,
EmailAddress =dbUser.EmailAddress,
Alias = dbUser?.UserAlias ?? string.Empty,
LastLoggedIn = lastLoggedIn,
ManagedUser = false
};
m.Permissions.AddRange(GetPermissions(permissions));
m.Features.AddRange(GetFeatures(features));
return m;
}
private UserManagementUsersViewModel MapPlexAdmin(PlexAccount plexInfo, PlexUsers dbUser, DateTime lastLoggedIn)
{
var newUser = false;
@ -505,6 +546,93 @@ namespace Ombi.UI.Modules
}
return retVal;
}
private async Task<Response> LoadPlexUsers()
{
var localUsers = await UserMapper.GetUsersAsync();
var plexDbUsers = await PlexUsersRepository.GetAllAsync();
var model = new List<UserManagementUsersViewModel>();
var userLogins = UserLoginsRepo.GetAll().ToList();
foreach (var user in localUsers)
{
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
var plexSettings = await PlexSettings.GetSettingsAsync();
if (!string.IsNullOrEmpty(plexSettings.PlexAuthToken))
{
//Get Plex Users
var plexUsers = PlexApi.GetUsers(plexSettings.PlexAuthToken);
if (plexUsers?.User != null)
{
foreach (var u in plexUsers.User)
{
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == u.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id);
// We don't have the user in the database yet
if (dbUser == null)
{
model.Add(MapPlexUser(u, null, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
else
{
// The Plex User is in the database
model.Add(MapPlexUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
}
}
// Also get the server admin
var account = PlexApi.GetAccount(plexSettings.PlexAuthToken);
if (account != null)
{
var dbUser = plexDbUsers.FirstOrDefault(x => x.PlexUserId == account.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == account.Id);
model.Add(MapPlexAdmin(account, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
}
return Response.AsJson(model);
}
private async Task<Response> LoadEmbyUsers()
{
var localUsers = await UserMapper.GetUsersAsync();
var embyDbUsers = await EmbyRepository.GetAllAsync();
var model = new List<UserManagementUsersViewModel>();
var userLogins = UserLoginsRepo.GetAll().ToList();
foreach (var user in localUsers)
{
var userDb = userLogins.FirstOrDefault(x => x.UserId == user.UserGuid);
model.Add(MapLocalUser(user, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
var embySettings = await EmbySettings.GetSettingsAsync();
if (!string.IsNullOrEmpty(embySettings.ApiKey))
{
//Get Plex Users
var embyUsers = EmbyApi.GetUsers(embySettings.FullUri, embySettings.ApiKey);
if (embyUsers != null)
{
foreach (var u in embyUsers)
{
var dbUser = embyDbUsers.FirstOrDefault(x => x.EmbyUserId == u.Id);
var userDb = userLogins.FirstOrDefault(x => x.UserId == u.Id);
// We don't have the user in the database yet
model.Add(dbUser == null
? MapEmbyUser(u, null, userDb?.LastLoggedIn ?? DateTime.MinValue)
: MapEmbyUser(u, dbUser, userDb?.LastLoggedIn ?? DateTime.MinValue));
}
}
}
return Response.AsJson(model);
}
}
}

View file

@ -1,4 +1,5 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: UserWizardModule.cs
@ -23,6 +24,7 @@
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
@ -50,8 +52,11 @@ namespace Ombi.UI.Modules
{
public class UserWizardModule : BaseModule
{
public UserWizardModule(ISettingsService<PlexRequestSettings> pr, ISettingsService<PlexSettings> plex, IPlexApi plexApi,
ISettingsService<AuthenticationSettings> auth, ICustomUserMapper m, IAnalytics a, ISecurityExtensions security) : base("wizard", pr, security)
public UserWizardModule(ISettingsService<PlexRequestSettings> pr, ISettingsService<PlexSettings> plex,
IPlexApi plexApi,
ISettingsService<AuthenticationSettings> auth, ICustomUserMapper m, IAnalytics a,
ISecurityExtensions security, IEmbyApi embyApi,
ISettingsService<EmbySettings> embySettings) : base("wizard", pr, security)
{
PlexSettings = plex;
PlexApi = plexApi;
@ -59,10 +64,13 @@ namespace Ombi.UI.Modules
Auth = auth;
Mapper = m;
Analytics = a;
EmbySettings = embySettings;
EmbyApi = embyApi;
Get["/", true] = async (x, ct) =>
{
a.TrackEventAsync(Category.Wizard, Action.Start, "Started the wizard", Username, CookieHelper.GetAnalyticClientId(Cookies));
a.TrackEventAsync(Category.Wizard, Action.Start, "Started the wizard", Username,
CookieHelper.GetAnalyticClientId(Cookies));
var settings = await PlexRequestSettings.GetSettingsAsync();
@ -76,7 +84,10 @@ namespace Ombi.UI.Modules
Post["/plex", true] = async (x, ct) => await Plex();
Post["/plexrequest", true] = async (x, ct) => await PlexRequest();
Post["/auth", true] = async (x, ct) => await Authentication();
Post["/createuser",true] = async (x,ct) => await CreateUser();
Post["/createuser", true] = async (x, ct) => await CreateUser();
Post["/embyauth", true] = async (x, ct) => await EmbyAuth();
}
private ISettingsService<PlexSettings> PlexSettings { get; }
@ -85,6 +96,8 @@ namespace Ombi.UI.Modules
private ISettingsService<AuthenticationSettings> Auth { get; }
private ICustomUserMapper Mapper { get; }
private IAnalytics Analytics { get; }
private IEmbyApi EmbyApi { get; }
private ISettingsService<EmbySettings> EmbySettings { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
@ -95,23 +108,31 @@ namespace Ombi.UI.Modules
if (string.IsNullOrEmpty(user.username) || string.IsNullOrEmpty(user.password))
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Please provide a valid username and password" });
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Please provide a valid username and password"
});
}
var model = PlexApi.SignIn(user.username, user.password);
if (model?.user == null)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Incorrect username or password!" });
return
Response.AsJson(new JsonResponseModel { Result = false, Message = "Incorrect username or password!" });
}
// Set the auth token in the session so we can use it in the next form
Session[SessionKeys.UserWizardPlexAuth] = model.user.authentication_token;
var servers = PlexApi.GetServer(model.user.authentication_token);
var firstServer = servers.Server.FirstOrDefault();
return Response.AsJson(new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme });
return
Response.AsJson(
new { Result = true, firstServer?.Port, Ip = firstServer?.LocalAddresses, firstServer?.Scheme });
}
private async Task<Response> Plex()
@ -122,7 +143,8 @@ namespace Ombi.UI.Modules
{
return Response.AsJson(valid.SendJsonError());
}
form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString(); // Set the auth token from the previous form
form.PlexAuthToken = Session[SessionKeys.UserWizardPlexAuth].ToString();
// Set the auth token from the previous form
// Get the machine ID from the settings (This could have changed)
try
@ -131,6 +153,7 @@ namespace Ombi.UI.Modules
var firstServer = servers.Server.FirstOrDefault(x => x.AccessToken == form.PlexAuthToken);
Session[SessionKeys.UserWizardMachineId] = firstServer?.MachineIdentifier;
form.MachineIdentifier = firstServer?.MachineIdentifier;
}
catch (Exception e)
{
@ -143,7 +166,12 @@ namespace Ombi.UI.Modules
{
return Response.AsJson(new JsonResponseModel { Result = true });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Could not save the settings to the database, please try again."
});
}
private async Task<Response> PlexRequest()
@ -158,14 +186,19 @@ namespace Ombi.UI.Modules
currentSettings.SearchForMovies = form.SearchForMovies;
currentSettings.SearchForTvShows = form.SearchForTvShows;
currentSettings.SearchForMusic = form.SearchForMusic;
var result = await PlexRequestSettings.SaveSettingsAsync(currentSettings);
if (result)
{
return Response.AsJson(new { Result = true });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Could not save the settings to the database, please try again."
});
}
private async Task<Response> Authentication()
@ -177,14 +210,21 @@ namespace Ombi.UI.Modules
{
return Response.AsJson(new JsonResponseModel { Result = true });
}
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Could not save the settings to the database, please try again." });
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Could not save the settings to the database, please try again."
});
}
private async Task<Response> CreateUser()
{
var username = (string)Request.Form.Username;
var userId = Mapper.CreateUser(username, Request.Form.Password, EnumHelper<Permissions>.All() - (int)Permissions.ReadOnlyUser, 0);
Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username, CookieHelper.GetAnalyticClientId(Cookies));
var userId = Mapper.CreateUser(username, Request.Form.Password,
EnumHelper<Permissions>.All() - (int)Permissions.ReadOnlyUser, 0);
Analytics.TrackEventAsync(Category.Wizard, Action.Finish, "Finished the wizard", username,
CookieHelper.GetAnalyticClientId(Cookies));
Session[SessionKeys.UsernameKey] = username;
// Destroy the Plex Auth Token
@ -197,7 +237,55 @@ namespace Ombi.UI.Modules
var baseUrl = string.IsNullOrEmpty(settings.BaseUrl) ? string.Empty : $"/{settings.BaseUrl}";
return CustomModuleExtensions.LoginAndRedirect(this,(Guid)userId, fallbackRedirectUrl: $"{baseUrl}/search");
return CustomModuleExtensions.LoginAndRedirect(this, (Guid)userId, fallbackRedirectUrl: $"{baseUrl}/search");
}
private async Task<Response> EmbyAuth()
{
var ip = (string)Request.Form.Ip;
var port = (int)Request.Form.Port;
var apiKey = (string)Request.Form.ApiKey;
var ssl = (bool)Request.Form.Ssl;
var settings = new EmbySettings
{
ApiKey = apiKey,
Enable = true,
Ip = ip,
Port = port,
Ssl = ssl,
};
try
{
// Test that we can connect
var result = EmbyApi.GetUsers(settings.FullUri, apiKey);
if (result != null && result.Any())
{
settings.AdministratorId = result.FirstOrDefault(x => x.Policy.IsAdministrator)?.Id ?? string.Empty;
await EmbySettings.SaveSettingsAsync(settings);
return Response.AsJson(new JsonResponseModel
{
Result = true
});
}
}
catch (Exception e)
{
return Response.AsJson(new JsonResponseModel
{
Result = false,
Message = $"Could not connect to Emby, please check your settings. Error: {e.Message}"
});
}
return Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Could not connect to Emby, please check your settings."
});
}
}
}