The move!

This commit is contained in:
Jamie.Rees 2017-05-16 08:31:44 +01:00
commit 25526cc4d9
1147 changed files with 85 additions and 8524 deletions

View file

@ -0,0 +1,225 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: AboutModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using Nancy;
using Nancy.Extensions;
using Nancy.Linker;
using Nancy.Responses.Negotiation;
using NLog;
using Octokit;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.Store;
using Ombi.UI.Models;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class AboutModule : BaseModule
{
public AboutModule(ISettingsService<PlexRequestSettings> settingsService,
ISettingsService<SystemSettings> systemService, ISecurityExtensions security,
IStatusChecker statusChecker, IResourceLinker linker, ISqliteConfiguration config) : base("admin", settingsService, security)
{
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
SettingsService = systemService;
StatusChecker = statusChecker;
Linker = linker;
SqlConfig = config;
Get["AboutPage","/about", true] = async (x,ct) => await Index();
Post["/about", true] = async (x,ct) => await ReportIssue();
Get["/OAuth", true] = async (x, ct) => await OAuth();
Get["/authorize", true] = async (x, ct) => await Authorize();
}
private ISettingsService<SystemSettings> SettingsService { get; }
private IStatusChecker StatusChecker { get; }
private IResourceLinker Linker { get; }
private ISqliteConfiguration SqlConfig { get; }
private async Task<Negotiator> Index()
{
var vm = await GetModel();
return View["About", vm];
}
private async Task<AboutAdminViewModel> GetModel()
{
var vm = new AboutAdminViewModel();
var oAuth = Session[SessionKeys.OAuthToken]?.ToString() ?? string.Empty;
if (!string.IsNullOrEmpty(oAuth))
{
vm.OAuthEnabled = true;
}
var systemSettings = await SettingsService.GetSettingsAsync();
var type = Type.GetType("Mono.Runtime");
if (type != null) // mono
{
vm.Os = "Mono";
var displayName = type.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
if (displayName != null)
{
vm.SystemVersion = displayName.Invoke(null, null).ToString();
}
}
else
{
// Windows
vm.Os = OperatingSystemHelper.GetOs();
vm.SystemVersion = Environment.Version.ToString();
}
vm.RunningDir = Environment.CurrentDirectory;
vm.DbLocation = SqlConfig.CurrentPath;
vm.ApplicationVersion = AssemblyHelper.GetFileVersion();
vm.Branch = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(systemSettings.Branch).DisplayName;
vm.LogLevel = LogManager.Configuration.LoggingRules.FirstOrDefault(x => x.NameMatches("database"))?.Levels?.FirstOrDefault()?.Name ?? "Unknown";
return vm;
}
private async Task<Response> ReportIssue()
{
var title = Request.Form["title"];
var body = Request.Form["body"];
if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(body))
{
return
Response.AsJson(
new
{
result = false,
message = "The title or issue body is empty! Please give me a bit more detail :)"
});
}
var model = await GetModel();
body = CreateReportBody(model, body);
var token = Session[SessionKeys.OAuthToken].ToString();
var result = await StatusChecker.ReportBug(title, body, token);
return Response.AsJson(new {result = true, url = result.HtmlUrl.ToString()});
}
private async Task<Response> OAuth()
{
var path = Request.Url.Path;
Request.Url.Path = path.Replace("oauth", "authorize");
var uri = await StatusChecker.OAuth(Request.Url.ToString(), Session);
return Response.AsJson(new { uri = uri.ToString()});
}
public async Task<Response> Authorize()
{
var code = Request.Query["code"].ToString();
var state = Request.Query["state"].ToString();
var expectedState = Session[SessionKeys.CSRF] as string;
if (state != expectedState)
{
throw new InvalidOperationException("SECURITY FAIL!");
}
Session[SessionKeys.CSRF] = null;
var token = await StatusChecker.OAuthAccessToken(code);
Session[SessionKeys.OAuthToken] = token.AccessToken;
return Context.GetRedirect(Linker.BuildRelativeUri(Context, "AboutPage").ToString());
}
private string CreateReportBody(AboutAdminViewModel model, string body)
{
var sb = new StringBuilder();
sb.AppendLine("#### Ombi Version");
sb.AppendLine($"V {model.ApplicationVersion}");
sb.AppendLine("#### Update Branch:");
sb.AppendLine(model.Branch);
sb.AppendLine("#### Operating System:");
sb.AppendLine(model.Os);
sb.AppendLine("#### Log Level:");
sb.AppendLine(model.LogLevel);
sb.AppendLine(body);
return sb.ToString();
// <!--- //!! Please use the Support / bug report template, otherwise we will close the Github issue !!
//(Pleas submit a feature request over here: http://feathub.com/tidusjar/Ombi) //--->
//#### Ombi Version:
//V 1.XX.XX
//#### Update Branch:
//Stable/Early Access Preview/development
//#### Operating System:
//(Place text here)
//#### Mono Version (only if your not on windows)
//(Place text here)
//#### Applicable Logs (from `/logs/` directory or the Admin page):
//```
//(Logs go here. Don't remove the ``` tags for showing your logs correctly. Please make sure you remove any personal information from the logs)
//```
//#### Problem Description:
//(Place text here)
//#### Reproduction Steps:
//Please include any steps to reproduce the issue, this the request that is causing the problem etc.
}
}
}

View file

@ -0,0 +1,129 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: CustomizationModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.UI.Models;
using Ombi.UI.Models.Admin;
using Ombi.UI.Models.UI;
using TMDbLib.Utilities;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class CustomizationModule : BaseModule
{
public CustomizationModule(ISettingsService<PlexRequestSettings> settingsService,
ISettingsService<CustomizationSettings> cust, ISecurityExtensions security)
: base("admin", settingsService, security)
{
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Settings = cust;
Get["/customization", true] = async (x, ct) => await Index();
Post["/customization", true] = async (x, ct) => await Save();
}
private ISettingsService<CustomizationSettings> Settings { get; }
private async Task<Negotiator> Index()
{
var model = await Settings.GetSettingsAsync();
var viewModel = new CustomizationViewModel
{
Settings = model,
SortOptions = new List<Dropdown<SortOptions>>()
};
foreach (var value in EnumHelper<SortOptions>.GetValues(SortOptions.LatestRelease))
{
viewModel.SortOptions.Add(new Dropdown<SortOptions>
{
Value = value,
Name = EnumHelper<SortOptions>.GetDisplayDescription(value),
Selected = model.DefaultSort == (int) value
});
}
foreach (var value in EnumHelper<FilterOptions>.GetValues(FilterOptions.Available))
{
viewModel.FilterOptions.Add(new Dropdown<FilterOptions>
{
Value = value,
Name = EnumHelper<FilterOptions>.GetDisplayDescription(value),
Selected = model.DefaultFilter == (int) value
});
}
foreach (var value in EnumHelper<Languages>.GetValues(Languages.en))
{
viewModel.LanguageDropdown.Add(new Dropdown<Languages>
{
Value = value,
Name = EnumHelper<Languages>.GetDisplayValue(value),
Selected = model.DefaultLang == (int) value
});
}
return View["customization", viewModel];
}
private async Task<Response> Save()
{
try
{
var model = this.Bind<CustomizationSettings>();
var result = await Settings.SaveSettingsAsync(model);
return Response.AsJson(result
? new JsonResponseModel { Result = true }
: new JsonResponseModel { Result = false, Message = "We could not save to the database, please try again" });
}
catch (Exception e)
{
throw e;
}
}
}
}

View file

@ -0,0 +1,107 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SystemStatusModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using Nancy;
using Nancy.Responses.Negotiation;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Helpers;
using Ombi.Helpers.Permissions;
using Ombi.Store;
using Ombi.Store.Models;
using Ombi.Store.Repository;
using Ombi.UI.Models;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class FaultQueueModule : BaseModule
{
public FaultQueueModule(ISettingsService<PlexRequestSettings> settingsService, IRepository<RequestQueue> requestQueue, ISecurityExtensions security) : base("admin", settingsService, security)
{
RequestQueue = requestQueue;
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; }
private Negotiator Index()
{
var requests = RequestQueue.GetAll();
var model = requests.Select(r => new FaultedRequestsViewModel
{
FaultType = (FaultTypeViewModel)(int)r.FaultType,
Type = (RequestTypeViewModel)(int)r.Type,
Title = ByteConverterHelper.ReturnObject<RequestedModel>(r.Content).Title,
Id = r.Id,
PrimaryIdentifier = r.PrimaryIdentifier,
LastRetry = r.LastRetry,
Message = r.Description
}).ToList();
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

@ -0,0 +1,222 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SystemStatusModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using MarkdownSharp;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
using Nancy.Validation;
using Ombi.Api.Interfaces;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Core.StatusChecker;
using Ombi.Helpers;
using Ombi.Helpers.Analytics;
using Ombi.Helpers.Permissions;
using Ombi.UI.Helpers;
using Ombi.UI.Models;
using Action = Ombi.Helpers.Analytics.Action;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class IntegrationModule : BaseModule
{
public IntegrationModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<WatcherSettings> watcher,
ISettingsService<CouchPotatoSettings> cp,ISecurityExtensions security, IAnalytics a, ISettingsService<RadarrSettings> radarrSettings,
ICacheProvider cache, IRadarrApi radarrApi, ISonarrApi sonarrApi) : base("admin", settingsService, security)
{
WatcherSettings = watcher;
Analytics = a;
CpSettings = cp;
Cache = cache;
RadarrApi = radarrApi;
RadarrSettings = radarrSettings;
SonarrApi = sonarrApi;
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Post["/sonarrrootfolders"] = _ => GetSonarrRootFolders();
Post["/radarrrootfolders"] = _ => GetSonarrRootFolders();
Get["/watcher", true] = async (x, ct) => await Watcher();
Post["/watcher", true] = async (x, ct) => await SaveWatcher();
Get["/radarr", true] = async (x, ct) => await Radarr();
Post["/radarr", true] = async (x, ct) => await SaveRadarr();
Post["/radarrprofiles"] = _ => GetRadarrQualityProfiles();
}
private ISettingsService<WatcherSettings> WatcherSettings { get; }
private ISettingsService<CouchPotatoSettings> CpSettings { get; }
private ISettingsService<RadarrSettings> RadarrSettings { get; }
private IRadarrApi RadarrApi { get; }
private ICacheProvider Cache { get; }
private IAnalytics Analytics { get; }
private ISonarrApi SonarrApi { get; }
private async Task<Negotiator> Watcher()
{
var settings = await WatcherSettings.GetSettingsAsync();
return View["Watcher", settings];
}
private async Task<Response> SaveWatcher()
{
var settings = this.Bind<WatcherSettings>();
var valid = this.Validate(settings);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
var cpSettings = await CpSettings.GetSettingsAsync().ConfigureAwait(false);
if (cpSettings.Enabled)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Cannot have Watcher and CouchPotato both enabled."
});
}
var radarrSettings = await RadarrSettings.GetSettingsAsync();
if (radarrSettings.Enabled)
{
return
Response.AsJson(new JsonResponseModel
{
Result = false,
Message = "Cannot have Radarr and CouchPotato both enabled."
});
}
settings.ApiKey = settings.ApiKey.Trim();
var result = await WatcherSettings.SaveSettingsAsync(settings);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Watcher!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private async Task<Negotiator> Radarr()
{
var settings = await RadarrSettings.GetSettingsAsync();
return View["Radarr", settings];
}
private async Task<Response> SaveRadarr()
{
var radarrSettings = this.Bind<RadarrSettings>();
//Check Watcher and CP make sure they are not enabled
var watcher = await WatcherSettings.GetSettingsAsync();
if (watcher.Enabled)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "Watcher is enabled, we cannot enable Watcher and Radarr" });
}
var cp = await CpSettings.GetSettingsAsync();
if (cp.Enabled)
{
return Response.AsJson(new JsonResponseModel { Result = false, Message = "CouchPotato is enabled, we cannot enable Radarr and CouchPotato" });
}
var valid = this.Validate(radarrSettings);
if (!valid.IsValid)
{
return Response.AsJson(valid.SendJsonError());
}
radarrSettings.ApiKey = radarrSettings.ApiKey.Trim();
var result = await RadarrSettings.SaveSettingsAsync(radarrSettings);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Radarr!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
private Response GetRadarrQualityProfiles()
{
var settings = this.Bind<RadarrSettings>();
var profiles = RadarrApi.GetProfiles(settings.ApiKey, settings.FullUri);
// set the cache
if (profiles != null)
{
Cache.Set(CacheKeys.RadarrQualityProfiles, profiles);
}
return Response.AsJson(profiles);
}
private Response GetSonarrRootFolders()
{
var settings = this.Bind<SonarrSettings>();
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)
{
Cache.Set(CacheKeys.SonarrRootFolders, rootFolders);
}
return Response.AsJson(rootFolders);
}
}
}

View file

@ -0,0 +1,178 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: AboutModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Threading.Tasks;
using Nancy;
using Ombi.Core;
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;
namespace Ombi.UI.Modules.Admin
{
public class ScheduledJobsRunnerModule : BaseModule
{
public ScheduledJobsRunnerModule(ISettingsService<PlexRequestSettings> settingsService,
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, IEmbyAvailabilityChecker embyAvailabilityChecker, IEmbyEpisodeCacher embyEpisode,
IEmbyContentCacher embyContentCacher, IEmbyUserChecker embyUser) : base("admin", settingsService, security)
{
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
PlexContentCacher = contentCacher;
SonarrCacher = sonarrCacher;
RadarrCacher = radarrCacher;
WatcherCacher = watcherCacher;
CpCacher = cpCacher;
StoreBackup = store;
SrCacher = srCacher;
AvailabilityChecker = plexChceker;
StoreCleanup = cleanup;
RequestLimit = requestLimit;
EpisodeCacher = episodeCacher;
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);
}
private IPlexContentCacher PlexContentCacher { get; }
private IRadarrCacher RadarrCacher { get; }
private ISonarrCacher SonarrCacher { get; }
private IWatcherCacher WatcherCacher { get; }
private ICouchPotatoCacher CpCacher { get; }
private IStoreBackup StoreBackup { get; }
private ISickRageCacher SrCacher { get; }
private IAvailabilityChecker AvailabilityChecker { get; }
private IStoreCleanup StoreCleanup { get; }
private IUserRequestLimitResetter RequestLimit { get; }
private IPlexEpisodeCacher EpisodeCacher { get; }
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();
}
if (key.Equals(JobNames.WatcherCacher, StringComparison.CurrentCultureIgnoreCase))
{
WatcherCacher.Queued();
}
if (key.Equals(JobNames.SonarrCacher, StringComparison.CurrentCultureIgnoreCase))
{
SonarrCacher.Queued();
}
if (key.Equals(JobNames.RadarrCacher, StringComparison.CurrentCultureIgnoreCase))
{
RadarrCacher.Queued();
}
if (key.Equals(JobNames.CpCacher, StringComparison.CurrentCultureIgnoreCase))
{
CpCacher.Queued();
}
if (key.Equals(JobNames.StoreBackup, StringComparison.CurrentCultureIgnoreCase))
{
StoreBackup.Start();
}
if (key.Equals(JobNames.SrCacher, StringComparison.CurrentCultureIgnoreCase))
{
SrCacher.Queued();
}
if (key.Equals(JobNames.PlexChecker, StringComparison.CurrentCultureIgnoreCase))
{
AvailabilityChecker.Start();
}
if (key.Equals(JobNames.StoreCleanup, StringComparison.CurrentCultureIgnoreCase))
{
StoreCleanup.Start();
}
if (key.Equals(JobNames.RequestLimitReset, StringComparison.CurrentCultureIgnoreCase))
{
RequestLimit.Start();
}
if (key.Equals(JobNames.EpisodeCacher, StringComparison.CurrentCultureIgnoreCase))
{
EpisodeCacher.Start();
}
if (key.Equals(JobNames.RecentlyAddedEmail, StringComparison.CurrentCultureIgnoreCase))
{
RecentlyAdded.StartNewsLetter();
}
if (key.Equals(JobNames.FaultQueueHandler, StringComparison.CurrentCultureIgnoreCase))
{
FaultQueueHandler.Start();
}
if (key.Equals(JobNames.PlexUserChecker, StringComparison.CurrentCultureIgnoreCase))
{
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

@ -0,0 +1,184 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SystemStatusModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
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;
using Ombi.Helpers.Analytics;
using Ombi.Helpers.Permissions;
using Ombi.UI.Models;
using Action = Ombi.Helpers.Analytics.Action;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class SystemStatusModule : BaseModule
{
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);
Get["/status", true] = async (x, ct) => await Status();
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()
{
var settings = await SystemSettings.GetSettingsAsync();
var checker = new StatusChecker(SystemSettings);
var status = await Cache.GetOrSetAsync(CacheKeys.LastestProductVersion, async () => await checker.GetStatus(), 30);
var md = new Markdown(new MarkdownOptions { AutoNewLines = true, AutoHyperlink = true });
status.ReleaseNotes = md.Transform(status.ReleaseNotes);
settings.Status = status;
settings.BranchDropdown = new List<BranchDropdown>
{
new BranchDropdown
{
Name =EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Stable).DisplayName,
Value = Branches.Stable,
Selected = settings.Branch == Branches.Stable
},
new BranchDropdown
{
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.EarlyAccessPreview).DisplayName,
Value = Branches.EarlyAccessPreview,
Selected = settings.Branch == Branches.EarlyAccessPreview
},
new BranchDropdown
{
Name = EnumHelper<Branches>.GetBranchValue<BranchAttribute>(Branches.Dev).DisplayName,
Value = Branches.Dev,
Selected = settings.Branch == Branches.Dev
},
};
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()
{
var settings = this.Bind<SystemSettings>();
Analytics.TrackEventAsync(Category.Admin, Action.Update, $"Updated Branch {EnumHelper<Branches>.GetBranchValue<BranchAttribute>(settings.Branch).DisplayName}", Username, CookieHelper.GetAnalyticClientId(Cookies));
await SystemSettings.SaveSettingsAsync(settings);
// Clear the cache
Cache.Remove(CacheKeys.LastestProductVersion);
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Successfully Saved your settings"});
}
private Response AutoUpdate()
{
Analytics.TrackEventAsync(Category.Admin, Action.Update, "AutoUpdate", Username, CookieHelper.GetAnalyticClientId(Cookies));
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, Path.Combine("UpdateService", "Ombi.Updater.exe"));
if (!string.IsNullOrEmpty(lowered))
{
if (lowered.Contains("ombi.exe"))
{
lowered = lowered.Replace("ombi.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}", }
: new ProcessStartInfo(startArgs) { Arguments = $"{url} {lowered}" };
Process.Start(startInfo);
//Environment.Exit(0);
return Nancy.Response.NoBody;
}
}
}

View file

@ -0,0 +1,83 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: SystemStatusModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Threading.Tasks;
using Nancy;
using Nancy.ModelBinding;
using Nancy.Responses.Negotiation;
using Nancy.Validation;
using NLog;
using Ombi.Core;
using Ombi.Core.SettingModels;
using Ombi.Helpers.Permissions;
using Ombi.UI.Helpers;
using Ombi.UI.Models;
using ISecurityExtensions = Ombi.Core.ISecurityExtensions;
namespace Ombi.UI.Modules.Admin
{
public class UserManagementSettingsModule : BaseModule
{
public UserManagementSettingsModule(ISettingsService<PlexRequestSettings> settingsService, ISettingsService<UserManagementSettings> umSettings, ISecurityExtensions security) : base("admin", settingsService, security)
{
UserManagementSettings = umSettings;
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["UserManagementSettings","/usermanagementsettings", true] = async(x,ct) => await Index();
Post["/usermanagementsettings", true] = async(x,ct) => await Update();
}
private ISettingsService<UserManagementSettings> UserManagementSettings { get; }
private static readonly Logger Log = LogManager.GetCurrentClassLogger();
private async Task<Negotiator> Index()
{
var model = await UserManagementSettings.GetSettingsAsync();
return View["UserManagementSettings", model];
}
private async Task<Response> Update()
{
var settings = this.Bind<UserManagementSettings>();
var valid = this.Validate(settings);
if (!valid.IsValid)
{
var error = valid.SendJsonError();
Log.Info("Error validating User Management settings, message: {0}", error.Message);
return Response.AsJson(error);
}
var result = await UserManagementSettings.SaveSettingsAsync(settings);
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for User Management!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
}
}