finished #646 and fixed #664

pull/687/head
Jamie.Rees 8 years ago
parent 05bdfcd550
commit 55f1309140

@ -23,37 +23,30 @@ namespace PlexRequests.Core.Migration
{
var con = Db.DbConnection();
var versions = GetMigrations();
var dbVersion = con.GetVersionInfo().OrderByDescending(x => x.Version).FirstOrDefault();
if (dbVersion == null)
{
dbVersion = new TableCreation.VersionInfo { Version = 0 };
}
var dbVersion = con.GetVersionInfo().OrderByDescending(x => x.Version).FirstOrDefault() ??
new TableCreation.VersionInfo { Version = 0 };
foreach (var v in versions)
{
#if !DEBUG
if (v.Value.Version > dbVersion.Version)
{
// Assuming only one constructor
var ctor = v.Key.GetConstructors().FirstOrDefault();
var dependencies = new List<object>();
foreach (var param in ctor.GetParameters())
{
var dep = Kernel.Get(param.ParameterType);
dependencies.Add(dep);
}
#endif
// Assuming only one constructor
var ctor = v.Key.GetConstructors().FirstOrDefault();
var dependencies = ctor.GetParameters().Select(param => Kernel.Get(param.ParameterType)).ToList();
var method = v.Key.GetMethod("Start");
if (method != null)
{
object result = null;
var classInstance = Activator.CreateInstance(v.Key, dependencies.Any() ? dependencies.ToArray() : null);
var parametersArray = new object[] { Db.DbConnection() };
var method = v.Key.GetMethod("Start");
if (method != null)
{
var classInstance = Activator.CreateInstance(v.Key, dependencies.Any() ? dependencies.ToArray() : null);
var parametersArray = new object[] { Db.DbConnection() };
method.Invoke(classInstance, parametersArray);
}
method.Invoke(classInstance, parametersArray);
}
#if !DEBUG
}
#endif
}
}

@ -27,7 +27,10 @@
using System;
using System.Data;
using NLog;
using System.Linq;
using PlexRequests.Core.SettingModels;
using PlexRequests.Helpers;
using PlexRequests.Helpers.Permissions;
using PlexRequests.Store;
using PlexRequests.Store.Repository;
@ -37,14 +40,16 @@ namespace PlexRequests.Core.Migration.Migrations
[Migration(11000, "v1.10.0.0")]
public class Version1100 : BaseMigration, IMigration
{
public Version1100(IUserRepository userRepo, IRequestService requestService)
public Version1100(IUserRepository userRepo, IRequestService requestService, ISettingsService<LogSettings> log)
{
UserRepo = userRepo;
RequestService = requestService;
Log = log;
}
public int Version => 11000;
private IUserRepository UserRepo { get; }
private IRequestService RequestService { get; }
private ISettingsService<LogSettings> Log { get; }
public void Start(IDbConnection con)
{
@ -52,9 +57,17 @@ namespace PlexRequests.Core.Migration.Migrations
// Update the current admin permissions set
UpdateAdmin();
ResetLogLevel();
UpdateSchema(con, Version);
}
private void ResetLogLevel()
{
var logSettings = Log.GetSettings();
logSettings.Level = LogLevel.Error.Ordinal;
Log.SaveSettings(logSettings);
UpdateSchema(con, Version);
LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level));
}
private void UpdateDb(IDbConnection con)
@ -63,11 +76,6 @@ namespace PlexRequests.Core.Migration.Migrations
con.AlterTable("Users", "ADD", "Permissions", true, "INTEGER");
con.AlterTable("Users", "ADD", "Features", true, "INTEGER");
// Add the new 'running' item into the scheduled jobs so we can check if the cachers are running
con.AlterTable("ScheduledJobs", "ADD", "Running", true, "INTEGER");
//https://image.tmdb.org/t/p/w150/https://image.tmdb.org/t/p/w150//aqhAqttDq7zgsTaBHtCD8wmTk6k.jpg
// UI = https://image.tmdb.org/t/p/w150/{{posterPath}}

@ -45,6 +45,10 @@
<Reference Include="Ninject">
<HintPath>..\packages\Ninject.3.2.0.0\lib\net45-full\Ninject.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=4.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.4.3.11\lib\net45\NLog.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Quartz, Version=2.3.3.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4, processorArchitecture=MSIL">
<HintPath>..\packages\Quartz.2.3.3\lib\net40\Quartz.dll</HintPath>
<Private>True</Private>

@ -2,5 +2,6 @@
<packages>
<package id="Common.Logging" version="3.0.0" targetFramework="net45" />
<package id="Common.Logging.Core" version="3.0.0" targetFramework="net45" />
<package id="NLog" version="4.3.11" targetFramework="net45" />
<package id="Quartz" version="2.3.3" targetFramework="net45" />
</packages>

@ -60,52 +60,13 @@ namespace PlexRequests.Core
// Shrink DB
TableCreation.Vacuum(Db.DbConnection());
}
// The below code is obsolete, we should use PlexRequests.Core.Migrations.MigrationRunner
var version = CheckSchema();
if (version > 0)
{
if (version > 1899 && version <= 1900)
{
MigrateToVersion1900();
}
if(version > 1899 && version <= 1910)
{
MigrateToVersion1910();
}
}
// Add the new 'running' item into the scheduled jobs so we can check if the cachers are running
Db.DbConnection().AlterTable("ScheduledJobs", "ADD", "Running", true, "INTEGER");
return Db.DbConnection().ConnectionString;
}
public static string ConnectionString => Db.DbConnection().ConnectionString;
private int CheckSchema()
{
var productVersion = AssemblyHelper.GetProductVersion();
var trimStatus = new Regex("[^0-9]", RegexOptions.Compiled).Replace(productVersion, string.Empty).PadRight(4, '0');
var version = int.Parse(trimStatus);
var connection = Db.DbConnection();
var schema = connection.GetSchemaVersion();
if (schema == null)
{
connection.CreateSchema(version); // Set the default.
schema = connection.GetSchemaVersion();
}
if (version > schema.SchemaVersion)
{
Db.DbConnection().UpdateSchemaVersion(version);
schema = connection.GetSchemaVersion();
}
version = schema.SchemaVersion;
return version;
}
private void CreateDefaultSettingsPage(string baseUrl)
{
var defaultSettings = new PlexRequestSettings
@ -148,7 +109,6 @@ namespace PlexRequests.Core
Task.Run(() => { CacheSonarrQualityProfiles(mc); });
Task.Run(() => { CacheCouchPotatoQualityProfiles(mc); });
// we don't need to cache sickrage profiles, those are static
// TODO: cache headphones profiles?
}
catch (Exception)
{
@ -156,12 +116,12 @@ namespace PlexRequests.Core
}
}
private void CacheSonarrQualityProfiles(MemoryCacheProvider cacheProvider)
private void CacheSonarrQualityProfiles(ICacheProvider cacheProvider)
{
try
{
Log.Info("Executing GetSettings call to Sonarr for quality profiles");
var sonarrSettingsService = new SettingsServiceV2<SonarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
var sonarrSettingsService = new SettingsServiceV2<SonarrSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
var sonarrSettings = sonarrSettingsService.GetSettings();
if (sonarrSettings.Enabled)
{
@ -178,12 +138,12 @@ namespace PlexRequests.Core
}
}
private void CacheCouchPotatoQualityProfiles(MemoryCacheProvider cacheProvider)
private void CacheCouchPotatoQualityProfiles(ICacheProvider cacheProvider)
{
try
{
Log.Info("Executing GetSettings call to CouchPotato for quality profiles");
var cpSettingsService = new SettingsServiceV2<CouchPotatoSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), new MemoryCacheProvider()));
var cpSettingsService = new SettingsServiceV2<CouchPotatoSettings>(new SettingsJsonRepository(new DbConfiguration(new SqliteFactory()), cacheProvider));
var cpSettings = cpSettingsService.GetSettings();
if (cpSettings.Enabled)
{
@ -199,102 +159,5 @@ namespace PlexRequests.Core
Log.Error(ex, "Failed to cache CouchPotato quality profiles!");
}
}
/// <summary>
/// Migrates to version 1.9.
/// Move the Plex auth token to the new field.
/// Reconfigure the log level
/// Set the wizard flag to true if we already have settings
/// </summary>
public void MigrateToVersion1900()
{
// Need to change the Plex Token location
var authSettings = new SettingsServiceV2<AuthenticationSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
var auth = authSettings.GetSettings();
var plexSettings = new SettingsServiceV2<PlexSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
if (auth != null)
{
//If we have an authToken we do not need to go through the setup
if (!string.IsNullOrEmpty(auth.OldPlexAuthToken))
{
var prServuce = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
var settings = prServuce.GetSettings();
settings.Wizard = true;
prServuce.SaveSettings(settings);
}
// Clear out the old token and save it to the new field
var currentSettings = plexSettings.GetSettings();
if (!string.IsNullOrEmpty(auth.OldPlexAuthToken))
{
currentSettings.PlexAuthToken = auth.OldPlexAuthToken;
plexSettings.SaveSettings(currentSettings);
// Clear out the old value
auth.OldPlexAuthToken = string.Empty;
authSettings.SaveSettings(auth);
}
}
// Set the log level
try
{
var settingsService = new SettingsServiceV2<LogSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
var logSettings = settingsService.GetSettings();
logSettings.Level = LogLevel.Error.Ordinal;
settingsService.SaveSettings(logSettings);
LoggingHelper.ReconfigureLogLevel(LogLevel.FromOrdinal(logSettings.Level));
}
catch (Exception e)
{
Log.Error(e);
}
// Enable analytics;
try
{
var prSettings = new SettingsServiceV2<PlexRequestSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
var settings = prSettings.GetSettings();
settings.CollectAnalyticData = true;
var updated = prSettings.SaveSettings(settings);
}
catch (Exception e)
{
Log.Error(e);
}
}
/// <summary>
/// Migrates to version1910.
/// </summary>
public void MigrateToVersion1910()
{
try
{
// Get the new machine Identifier
var settings = new SettingsServiceV2<PlexSettings>(new SettingsJsonRepository(Db, new MemoryCacheProvider()));
var plex = settings.GetSettings();
if (!string.IsNullOrEmpty(plex.PlexAuthToken))
{
var api = new PlexApi(new ApiRequest());
var server = api.GetServer(plex.PlexAuthToken); // Get the server info
plex.MachineIdentifier = server.Server.FirstOrDefault(x => x.AccessToken == plex.PlexAuthToken)?.MachineIdentifier;
settings.SaveSettings(plex); // Save the new settings
}
}
catch (Exception e)
{
Log.Error(e);
}
}
}
}

@ -65,6 +65,7 @@ namespace PlexRequests.Services.Jobs
var settings = CpSettings.GetSettings();
if (settings.Enabled)
{
Job.SetRunning(true, JobNames.CpCacher);
Log.Trace("Getting all movies from CouchPotato");
try
{
@ -109,7 +110,6 @@ namespace PlexRequests.Services.Jobs
public void Execute(IJobExecutionContext context)
{
Job.SetRunning(true, JobNames.CpCacher);
Queued();
}
}

@ -87,7 +87,6 @@ namespace PlexRequests.Services.Jobs
Log.Debug("Validation of the plex settings failed.");
return;
}
var libraries = CachedLibraries(plexSettings, true); //force setting the cache (10 min intervals via scheduler)
if (libraries == null || !libraries.Any())
@ -156,9 +155,6 @@ namespace PlexRequests.Services.Jobs
NotificationEngine.NotifyUsers(modifiedModel, plexSettings.PlexAuthToken, NotificationType.RequestAvailable);
RequestService.BatchUpdate(modifiedModel);
}
Job.Record(JobNames.PlexChecker);
Job.SetRunning(false, JobNames.CpCacher);
}
public List<PlexMovie> GetPlexMovies()
@ -504,7 +500,7 @@ namespace PlexRequests.Services.Jobs
public void Execute(IJobExecutionContext context)
{
Job.SetRunning(true, JobNames.CpCacher);
Job.SetRunning(true, JobNames.PlexChecker);
try
{
CheckAndUpdateAll();
@ -513,6 +509,11 @@ namespace PlexRequests.Services.Jobs
{
Log.Error(e);
}
finally
{
Job.Record(JobNames.PlexChecker);
Job.SetRunning(false, JobNames.PlexChecker);
}
}
}
}

@ -145,7 +145,7 @@ namespace PlexRequests.Services.Jobs
public void Execute(IJobExecutionContext context)
{
Job.SetRunning(true, JobNames.CpCacher);
try
{
var s = Plex.GetSettings();
@ -163,6 +163,7 @@ namespace PlexRequests.Services.Jobs
return;
}
}
Job.SetRunning(true, JobNames.EpisodeCacher);
CacheEpisodes(s);
}
catch (Exception e)
@ -172,7 +173,7 @@ namespace PlexRequests.Services.Jobs
finally
{
Job.Record(JobNames.EpisodeCacher);
Job.SetRunning(false, JobNames.CpCacher);
Job.SetRunning(false, JobNames.EpisodeCacher);
}
}
}

@ -78,8 +78,6 @@ namespace PlexRequests.Services.Jobs
public void Execute(IJobExecutionContext context)
{
JobRecord.SetRunning(true, JobNames.CpCacher);
try
{
var settings = NewsletterSettings.GetSettings();
@ -87,7 +85,7 @@ namespace PlexRequests.Services.Jobs
{
return;
}
JobRecord.SetRunning(true, JobNames.RecentlyAddedEmail);
Start(settings);
}
catch (Exception e)
@ -97,7 +95,7 @@ namespace PlexRequests.Services.Jobs
finally
{
JobRecord.Record(JobNames.RecentlyAddedEmail);
JobRecord.SetRunning(false, JobNames.CpCacher);
JobRecord.SetRunning(false, JobNames.RecentlyAddedEmail);
}
}
@ -264,7 +262,8 @@ namespace PlexRequests.Services.Jobs
{
foreach (var user in users.User)
{
message.Bcc.Add(new MailboxAddress(user.Username, user.Email));
if (user.Email != null)
message.Bcc.Add(new MailboxAddress(user.Username, user.Email));
}
}
}

@ -58,12 +58,14 @@ namespace PlexRequests.Services.Jobs
public void Queued()
{
Job.SetRunning(true, JobNames.CpCacher);
Log.Trace("Getting the settings");
var settings = SrSettings.GetSettings();
if (settings.Enabled)
{
Job.SetRunning(true, JobNames.SrCacher);
Log.Trace("Getting all shows from SickRage");
try
{
@ -80,7 +82,7 @@ namespace PlexRequests.Services.Jobs
finally
{
Job.Record(JobNames.SrCacher);
Job.SetRunning(false, JobNames.CpCacher);
Job.SetRunning(false, JobNames.SrCacher);
}
}
}

@ -62,10 +62,10 @@ namespace PlexRequests.Services.Jobs
public void Queued()
{
Job.SetRunning(true, JobNames.CpCacher);
var settings = SonarrSettings.GetSettings();
if (settings.Enabled)
{
Job.SetRunning(true, JobNames.SonarrCacher);
try
{
var series = SonarrApi.GetSeries(settings.ApiKey, settings.FullUri);
@ -81,7 +81,7 @@ namespace PlexRequests.Services.Jobs
finally
{
Job.Record(JobNames.SonarrCacher);
Job.SetRunning(false, JobNames.CpCacher);
Job.SetRunning(false, JobNames.SonarrCacher);
}
}
}

@ -182,3 +182,9 @@ button.list-group-item:focus {
#sidebar-wrapper {
background: #252424; }
#cacherRunning {
background-color: #333333;
text-align: center;
font-size: 15px;
padding: 3px 0; }

@ -1 +1 @@
.form-control-custom{background-color:#333 !important;}.form-control-custom-disabled{background-color:#252424 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}.scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:300;color:#ebebeb;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#333;border-radius:10px;}.bootstrap-datetimepicker-widget.dropdown-menu{background-color:#333;}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-bottom:6px solid #333 !important;}#sidebar-wrapper{background:#252424;}
.form-control-custom{background-color:#333 !important;}.form-control-custom-disabled{background-color:#252424 !important;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background:#df691a;}.scroll-top-wrapper{background-color:#333;}.scroll-top-wrapper:hover{background-color:#df691a;}body{font-family:Open Sans Regular,Helvetica Neue,Helvetica,Arial,sans-serif;color:#eee;background-color:#1f1f1f;}.table-striped>tbody>tr:nth-of-type(odd){background-color:#333;}.table-hover>tbody>tr:hover{background-color:#282828;}fieldset{padding:15px;}legend{border-bottom:1px solid #333;}.form-control{color:#fefefe;background-color:#333;}.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{margin-left:-0;}.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:-15px;}.dropdown-menu{background-color:#282828;}.dropdown-menu .divider{background-color:#333;}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-color:#333;}.input-group-addon{background-color:#333;}.nav>li>a:hover,.nav>li>a:focus{background-color:#df691a;}.nav-tabs>li>a:hover{border-color:#df691a #df691a transparent;}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{background-color:#df691a;border:1px solid #df691a;}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #df691a;}.navbar-default{background-color:#0a0a0a;}.navbar-default .navbar-brand{color:#df691a;}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#f0ad4e;background-color:#282828;}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{background-color:#282828;}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#df691a;color:#fff;}.pagination>li>a,.pagination>li>span{background-color:#282828;}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{background-color:#333;}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#fefefe;background-color:#333;}.list-group-item{background-color:#282828;}a.list-group-item:hover,button.list-group-item:hover,a.list-group-item:focus,button.list-group-item:focus{background-color:#333;}.input-addon,.input-group-addon{color:#df691a;}.modal-header,.modal-footer{background-color:#282828;}.modal-content{position:relative;background-color:#282828;border:1px solid transparent;border-radius:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box;outline:0;}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:300;color:#ebebeb;line-height:1;vertical-align:middle;white-space:nowrap;text-align:center;background-color:#333;border-radius:10px;}.bootstrap-datetimepicker-widget.dropdown-menu{background-color:#333;}.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after{border-bottom:6px solid #333 !important;}#sidebar-wrapper{background:#252424;}#cacherRunning{background-color:#333;text-align:center;font-size:15px;padding:3px 0;}

@ -228,3 +228,10 @@ button.list-group-item:focus {
#sidebar-wrapper {
background: $bg-colour-disabled;
}
#cacherRunning {
background-color: $bg-colour;
text-align: center;
font-size: 15px;
padding: 3px 0;
}

@ -257,6 +257,12 @@ label {
font-size: 15px;
padding: 3px 0; }
#cacherRunning {
background-color: #4e5d6c;
text-align: center;
font-size: 15px;
padding: 3px 0; }
.checkbox label {
display: inline-block;
cursor: pointer;

File diff suppressed because one or more lines are too long

@ -327,6 +327,13 @@ $border-radius: 10px;
padding: 3px 0;
}
#cacherRunning {
background-color: $form-color;
text-align: center;
font-size: 15px;
padding: 3px 0;
}
.checkbox label {
display: inline-block;
cursor: pointer;

@ -25,6 +25,8 @@
// ************************************************************************/
#endregion
using Nancy;
using Nancy.Linker;
using Nancy.Security;
using Nancy.ViewEngines.Razor;
using Ninject;
@ -41,22 +43,37 @@ namespace PlexRequests.UI.Helpers
get
{
var userRepo = ServiceLocator.Instance.Resolve<IUserRepository>();
return _security ?? (_security = new SecurityExtensions(userRepo, null));
var linker = ServiceLocator.Instance.Resolve<IResourceLinker>();
return _security ?? (_security = new SecurityExtensions(userRepo, null, linker));
}
}
private static SecurityExtensions _security;
public static bool HasAnyPermission(this HtmlHelpers helper, int permission)
public static bool HasAnyPermission(this HtmlHelpers helper, int permission, bool authenticated = true)
{
return helper.CurrentUser.IsAuthenticated()
&& Security.HasPermissions(helper.CurrentUser, (Permissions) permission);
if (authenticated)
{
return helper.CurrentUser.IsAuthenticated()
&& Security.HasPermissions(helper.CurrentUser, (Permissions) permission);
}
return Security.HasPermissions(helper.CurrentUser, (Permissions)permission);
}
public static bool DoesNotHavePermission(this HtmlHelpers helper, int permission)
{
return Security.DoesNotHavePermissions(permission, helper.CurrentUser);
}
public static bool IsAdmin(this HtmlHelpers helper, bool isAuthenticated = true)
{
return HasAnyPermission(helper, (int) Permissions.Administrator, isAuthenticated);
}
public static bool IsLoggedIn(this HtmlHelpers helper, NancyContext context)
{
return Security.IsLoggedIn(context);
}
}
}

@ -30,6 +30,8 @@ using System.Collections.Generic;
using System.Linq;
using Nancy;
using Nancy.Extensions;
using Nancy.Linker;
using Nancy.Responses;
using Nancy.Security;
using Ninject;
using PlexRequests.Helpers.Permissions;
@ -40,14 +42,16 @@ namespace PlexRequests.UI.Helpers
{
public class SecurityExtensions
{
public SecurityExtensions(IUserRepository userRepository, NancyModule context)
public SecurityExtensions(IUserRepository userRepository, NancyModule context, IResourceLinker linker)
{
UserRepository = userRepository;
Module = context;
Linker = linker;
}
private IUserRepository UserRepository { get; }
private NancyModule Module { get; }
private IResourceLinker Linker { get; }
public bool IsLoggedIn(NancyContext context)
{
@ -117,7 +121,7 @@ namespace PlexRequests.UI.Helpers
if (dbUser == null) return false;
var permissions = (Permissions)dbUser.Permissions;
var result = permissions.HasFlag((Permissions)perm);
var result = permissions.HasFlag(perm);
return !result;
}
@ -134,10 +138,11 @@ namespace PlexRequests.UI.Helpers
return result;
}
public void HasPermissionsResponse(Permissions perm)
public Response HasPermissionsRedirect(Permissions perm, NancyContext context, string routeName, HttpStatusCode code)
{
Module.AddBeforeHookOrExecute(
ForbiddenIfNot(ctx =>
var url = Linker.BuildRelativeUri(context, routeName);
var response = ForbiddenIfNot(ctx =>
{
if (ctx.CurrentUser == null) return false;
@ -145,13 +150,24 @@ namespace PlexRequests.UI.Helpers
if (dbUser == null) return false;
var permissions = (Permissions)dbUser.Permissions;
var permissions = (Permissions) dbUser.Permissions;
var result = permissions.HasFlag(perm);
return result;
}), "Requires Claims");
});
var r = response(context);
return r.StatusCode == code
? new RedirectResponse(url.ToString())
: null;
}
public Response AdminLoginRedirect(Permissions perm, NancyContext context)
{
// This will redirect us to the Login Page if we don't have the correct permission passed in (e.g. Admin with Http 403 status code).
return HasPermissionsRedirect(perm, context, "LocalLogin", HttpStatusCode.Forbidden);
}
// BELOW IS A COPY FROM THE SecurityHooks CLASS!
/// <summary>

@ -66,6 +66,7 @@ using PlexRequests.UI.Helpers;
using PlexRequests.UI.Models;
using Quartz;
using Action = PlexRequests.Helpers.Analytics.Action;
using HttpStatusCode = Nancy.HttpStatusCode;
namespace PlexRequests.UI.Modules
{
@ -154,8 +155,8 @@ namespace PlexRequests.UI.Modules
NotifySettings = notifyService;
RecentlyAdded = recentlyAdded;
Security.HasPermissionsResponse(Permissions.Administrator);
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["/"] = _ => Admin();
Get["/authentication", true] = async (x, ct) => await Authentication();
@ -826,13 +827,11 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(result
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Newsletter!" }
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
}
}
private Response CreateApiKey()
{
Security.HasPermissionsResponse(Permissions.Administrator);
Analytics.TrackEventAsync(Category.Admin, Action.Create, "Created API Key", Username, CookieHelper.GetAnalyticClientId(Cookies));
var apiKey = Guid.NewGuid().ToString("N");
var settings = PrService.GetSettings();
@ -978,11 +977,11 @@ namespace PlexRequests.UI.Modules
if (!isValid)
{
return Response.AsJson(new JsonResponseModel
{
Result = false,
Message =
{
Result = false,
Message =
$"CRON {settings.RecentlyAddedCron} is not valid. Please ensure you are using a valid CRON."
});
});
}
}
var result = await ScheduledJobSettings.SaveSettingsAsync(settings);

@ -46,7 +46,7 @@ namespace PlexRequests.UI.Modules.Admin
Cache = cache;
RequestQueue = requestQueue;
Security.HasPermissionsResponse(Permissions.Administrator);
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["Index", "/faultqueue"] = x => Index();
}

@ -49,8 +49,8 @@ namespace PlexRequests.UI.Modules.Admin
Cache = cache;
SystemSettings = ss;
Security.HasPermissionsResponse(Permissions.Administrator);
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
Get["/status", true] = async (x, ct) => await Status();
Post["/save", true] = async (x, ct) => await Save();

@ -30,6 +30,7 @@ using System.Linq;
using System.Threading;
using Nancy;
using Nancy.Linker;
using Nancy.Security;
using Ninject;
using PlexRequests.Core;
@ -151,14 +152,14 @@ namespace PlexRequests.UI.Modules
get
{
var userRepo = ServiceLocator.Instance.Resolve<IUserRepository>();
return _security ?? (_security = new SecurityExtensions(userRepo, this));
var linker = ServiceLocator.Instance.Resolve<IResourceLinker>();
return _security ?? (_security = new SecurityExtensions(userRepo, this, linker));
}
}
private SecurityExtensions _security;
protected bool LoggedIn => Context?.CurrentUser != null;
protected string Culture { get; set; }

@ -1,7 +1,7 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: UpdateCheckerModule.cs
// File: LayoutModule.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
@ -25,6 +25,7 @@
// ************************************************************************/
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using Nancy;
@ -35,24 +36,29 @@ using PlexRequests.Core;
using PlexRequests.Core.SettingModels;
using PlexRequests.Core.StatusChecker;
using PlexRequests.Helpers;
using PlexRequests.Services.Interfaces;
using PlexRequests.Services.Jobs;
using PlexRequests.UI.Models;
namespace PlexRequests.UI.Modules
{
public class UpdateCheckerModule : BaseAuthModule
public class LayoutModule : BaseAuthModule
{
public UpdateCheckerModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings) : base("updatechecker", pr)
public LayoutModule(ICacheProvider provider, ISettingsService<PlexRequestSettings> pr, ISettingsService<SystemSettings> settings, IJobRecord rec) : base("layout", pr)
{
Cache = provider;
SystemSettings = settings;
Job = rec;
Get["/", true] = async (x,ct) => await CheckLatestVersion();
Get["/cacher", true] = async (x,ct) => await CacherRunning();
}
private ICacheProvider Cache { get; }
private static Logger Log = LogManager.GetCurrentClassLogger();
private ISettingsService<SystemSettings> SystemSettings { get; }
private IJobRecord Job { get; }
private async Task<Response> CheckLatestVersion()
{
@ -79,5 +85,35 @@ namespace PlexRequests.UI.Modules
return Response.AsJson(new JsonUpdateAvailableModel { UpdateAvailable = false });
}
}
private async Task<Response> CacherRunning()
{
try
{
var jobs = await Job.GetJobsAsync();
// Check to see if any are running
var runningJobs = jobs.Where(x => x.Running);
// We only want the cachers
var cacherJobs = runningJobs.Where(x =>
x.Name.Equals(JobNames.CpCacher)
|| x.Name.Equals(JobNames.EpisodeCacher)
|| x.Name.Equals(JobNames.PlexChecker)
|| x.Name.Equals(JobNames.SonarrCacher)
|| x.Name.Equals(JobNames.SrCacher));
return Response.AsJson(cacherJobs.Any()
? new { CurrentlyRunning = true, IsAdmin}
: new { CurrentlyRunning = false, IsAdmin });
}
catch (Exception e)
{
Log.Warn("Exception Thrown when attempting to check the status");
Log.Warn(e);
return Response.AsJson(new { CurrentlyRunning = false, IsAdmin });
}
}
}
}

@ -52,7 +52,7 @@ namespace PlexRequests.UI.Modules
: base(pr)
{
UserMapper = m;
Get["/login"] = _ =>
Get["LocalLogin","/login"] = _ =>
{
if (LoggedIn)
{

@ -99,7 +99,7 @@ namespace PlexRequests.UI.Modules
{
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
return Response.AsRedirect(uri.ToString()); // TODO Check this
return Response.AsRedirect(uri.ToString());
}
var authenticated = false;
@ -112,7 +112,7 @@ namespace PlexRequests.UI.Modules
Log.Debug("User is in denied list, not allowing them to authenticate");
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
return Response.AsRedirect(uri.ToString()); // TODO Check this
return Response.AsRedirect(uri.ToString());
}
var password = string.Empty;
@ -178,7 +178,7 @@ namespace PlexRequests.UI.Modules
{
var uri = Linker.BuildRelativeUri(Context, "UserLoginIndex");
Session["TempMessage"] = Resources.UI.UserLogin_IncorrectUserPass;
return Response.AsRedirect(uri.ToString()); // TODO Check this
return Response.AsRedirect(uri.ToString());
}
var landingSettings = await LandingPageSettings.GetSettingsAsync();
@ -192,7 +192,7 @@ namespace PlexRequests.UI.Modules
}
}
var retVal = Linker.BuildRelativeUri(Context, "SearchIndex");
return Response.AsRedirect(retVal.ToString()); // TODO Check this
return Response.AsRedirect(retVal.ToString());
}

@ -258,7 +258,7 @@
<Compile Include="Modules\IssuesModule.cs" />
<Compile Include="Modules\LandingPageModule.cs" />
<Compile Include="Modules\RequestsBetaModule.cs" />
<Compile Include="Modules\UpdateCheckerModule.cs" />
<Compile Include="Modules\LayoutModule.cs" />
<Compile Include="Modules\UserWizardModule.cs" />
<Compile Include="NinjectModules\ApiModule.cs" />
<Compile Include="NinjectModules\ConfigurationModule.cs" />
@ -747,6 +747,7 @@
<EmbeddedResource Include="Resources\UI.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>UI1.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Resources\UI.sv.resx" />
</ItemGroup>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Der er ingen oplysninger om udgivelsesdatoen</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Udsigt I Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Doner til Bibliotek vedligeholder</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Tilgængelig på</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>Movie status</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Ikke anmodet endnu</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>Afventer godkendelse</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Behandler forespørgsel</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Anmodning afvist!</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>Tv-show status!</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>En baggrund proces kører i øjeblikket, så der kan være nogle uventede problemer. Dette bør ikke tage for lang tid.</value>
</data>
</root>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Es gibt noch keine Informationen für diesen Release-Termin</value>
</data>
</root>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Ansicht In Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Spenden zur Bibliothek Maintainer</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Verfügbar auf Plex</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>Film-Status!</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Noch nicht heraus!</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>Genehmigung ausstehend</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Die Verarbeitung Anfrage</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Anfrage verweigert.</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>TV-Show-Status</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>Ein Hintergrundprozess gerade läuft, so könnte es einige unerwartete Verhalten sein. Dies sollte nicht zu lange dauern.</value>
</data>
</root>

@ -459,4 +459,31 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>No hay información disponible para la fecha de lanzamiento</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Donar a la biblioteca Mantenedor</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Disponible en Plex</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>estado de película</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>No solicitado</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>PENDIENTES DE APROBACIÓN</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>solicitud de procesamiento</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Solicitud denegada</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>estado de programa de televisión</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>Un proceso en segundo plano se está ejecutando actualmente, por lo que podría ser un comportamiento inesperado. Esto no debería tomar mucho tiempo.</value>
</data>
</root>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Il n'y a pas d'information disponible pour la date de sortie</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Voir Dans Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Faire un don à la bibliothèque mainteneur!</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Disponible sur Plex</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>le statut de film</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Pas encore demandé</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>En attente de validation</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Traitement de la demande</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Requête refusée</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>TV show status</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>Un processus d'arrière-plan est en cours d'exécution, de sorte qu'il pourrait y avoir des comportements inattendus. Cela ne devrait pas prendre trop de temps.</value>
</data>
</root>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Non ci sono informazioni disponibili per la data di uscita</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Guarda In Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Donare alla libreria Maintainer</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Disponibile su Plex</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>lo stato di film</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Non ancora richiesto</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>Approvazione in sospeso</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Elaborazione richiesta</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Richiesta negata</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>Show televisivo di stato</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>Un processo in background è in esecuzione, quindi ci potrebbero essere alcuni comportamenti imprevisti. Questo non dovrebbe richiedere troppo tempo.</value>
</data>
</root>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Er is geen informatie beschikbaar voor de release datum</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Bekijk In Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Doneer aan Library Maintainer</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Beschikbaar vanaf</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>Movie-status!</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Nog niet gevraagd</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>Wacht op goedkeuring</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Verwerking verzoek...</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Aanvraag afgewezen</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>TV-show-status</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>Een achtergrond taak is momenteel actief, dus er misschien een onverwachte gedrag. Dit moet niet te lang duren.</value>
</data>
</root>

@ -459,4 +459,31 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Não há informações disponíveis para a data de lançamento</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Ver Em Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Doações para Biblioteca Mantenedor</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Disponível em Plex</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>status de filme</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Não solicitada ainda</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>B P/ Aprovação</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Processando solicitação...</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Solicitação negada.</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>Programa de TV status</value>
</data>
</root>

@ -467,4 +467,7 @@
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>TV show status</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>A background process is currently running, so there might be some unexpected behavior. This shouldn't take too long.</value>
</data>
</root>

@ -459,4 +459,34 @@
<data name="Requests_ReleaseDate_Unavailable" xml:space="preserve">
<value>Det finns ingen information tillgänglig för release datum</value>
</data>
<data name="Search_ViewInPlex" xml:space="preserve">
<value>Vy I Plex</value>
</data>
<data name="Custom_Donation_Default" xml:space="preserve">
<value>Donera till bibliotek Ansvarig</value>
</data>
<data name="Search_Available_on_plex" xml:space="preserve">
<value>Tillgänglig den</value>
</data>
<data name="Search_Movie_Status" xml:space="preserve">
<value>Film status</value>
</data>
<data name="Search_Not_Requested_Yet" xml:space="preserve">
<value>Inte Begärd ännu</value>
</data>
<data name="Search_Pending_approval" xml:space="preserve">
<value>Väntar på godkännande</value>
</data>
<data name="Search_Processing_Request" xml:space="preserve">
<value>Bearbetning förfrågan</value>
</data>
<data name="Search_Request_denied" xml:space="preserve">
<value>Förfrågan nekad</value>
</data>
<data name="Search_TV_Show_Status" xml:space="preserve">
<value>Visa status</value>
</data>
<data name="Layout_CacherRunning" xml:space="preserve">
<value>En bakgrundsprocess är igång, så det kan finnas några oväntade beteende. Detta bör inte ta alltför lång tid.</value>
</data>
</root>

@ -222,6 +222,15 @@ namespace PlexRequests.UI.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to A background process is currently running, so there might be some unexpected behavior. This shouldn&apos;t take too long..
/// </summary>
public static string Layout_CacherRunning {
get {
return ResourceManager.GetString("Layout_CacherRunning", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Change Password.
/// </summary>

@ -44,7 +44,7 @@ namespace PlexRequests.UI.Validators
RuleFor(x => x.BaseUrl).NotEqual("login", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'login' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("test", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'test' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("approval", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'approval' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("updatechecker", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'updatechecker' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("layout", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'layout' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("usermanagement", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'usermanagement' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("api", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'api' as this is reserved by the application.");
RuleFor(x => x.BaseUrl).NotEqual("landing", StringComparer.CurrentCultureIgnoreCase).WithMessage("You cannot use 'landing' as this is reserved by the application.");

@ -10,7 +10,7 @@
$(function () {
// Check for update
var url = createBaseUrl(urlBase, '/updatechecker');
var url = createBaseUrl(urlBase, '/layout');
$.ajax({
type: "GET",
url: url,
@ -20,7 +20,7 @@
var status = createBaseUrl(urlBase, '/admin/status');
$('#updateAvailable').html("<i class='fa fa-cloud-download' aria-hidden='true'></i> @UI.Layout_UpdateAvailablePart1 <a style='color: white' href='" + status + "'>@UI.Layout_UpdateAvailablePart2</a>");
$('#updateAvailable').removeAttr("hidden");
$('body').addClass('update-available');
//$('body').addClass('update-available');
}
},
error: function (e) {
@ -29,6 +29,7 @@
});
// End Check for update
checkCacheInProgress();
// Scroller
$(document).on('scroll', function () {
@ -43,9 +44,6 @@
$('.scroll-top-wrapper').on('click', scrollToTop);
// End Scroller
// Get Issue count
var issueUrl = createBaseUrl(urlBase, '/issues/issuecount');
$.ajax({
@ -66,6 +64,8 @@
// End issue count
$('#donate').click(function () {
ga('send', 'event', 'Navbar', 'Donate', 'Donate Clicked');
});
@ -80,4 +80,23 @@
offsetTop = offset.top;
$('html, body').animate({ scrollTop: offsetTop }, 500, 'linear');
}
function checkCacheInProgress() {
var url = createBaseUrl(urlBase, '/layout/cacher');
$.ajax({
type: "GET",
url: url,
dataType: "json",
success: function (response) {
if (response.currentlyRunning) {
$('#cacherRunning').html("@UI.Layout_CacherRunning");
$('#cacherRunning').removeAttr("hidden");
}
},
error: function (e) {
console.log(e);
}
});
}
</script>

@ -35,21 +35,21 @@
@Html.GetNavbarUrl(Context, "/search", UI.Layout_Search, "search")
@Html.GetNavbarUrl(Context, "/requests", UI.Layout_Requests, "plus-circle")
@Html.GetNavbarUrl(Context, "/issues", UI.Layout_Issues, "exclamation", "<span id=\"issueCount\"></span>")
@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin
@*@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin*@
@if (Html.IsAdmin())
{
<li><a id="donate" href="https://www.paypal.me/PlexRequestsNet" target="_blank"><i class="fa fa-heart" style="color: red"></i> @UI.Layout_Donate</a></li>
}
<li id="customDonate" style="display: none"><a id="customDonateHref" href="https://www.paypal.me/PlexRequestsNet" target="_blank"><i class="fa fa-heart" style="color: yellow;"></i> <span id="donationText">@UI.Custom_Donation_Default</span></a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
@if (!Context.CurrentUser.IsAuthenticated() && Context.Request.Session[SessionKeys.UsernameKey] == null) // TODO replace with IsAdmin
@*@if (!Context.CurrentUser.IsAuthenticated() && Context.Request.Session[SessionKeys.UsernameKey] == null) // TODO replace with IsAdmin*@
@if (!Html.IsLoggedIn(Context))
{
<li><a href="@url/login?redirect=@Context.Request.Path"><i class="fa fa-user"></i> @UI.Layout_Admin</a></li>
}
@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin
@*@if (Context.CurrentUser.IsAuthenticated()) // TODO replace with IsAdmin*@
@if (Html.IsAdmin())
{
<li><a>@UI.Layout_Welcome @Context.Request.Session[SessionKeys.UsernameKey]</a></li>
<li class="dropdown">
@ -63,7 +63,8 @@
</ul>
</li>
}
@if (Context.Request.Session[SessionKeys.UsernameKey] != null && !Context.CurrentUser.IsAuthenticated())
@*@if (Context.Request.Session[SessionKeys.UsernameKey] != null && !Context.CurrentUser.IsAuthenticated())*@
else if (Html.IsLoggedIn(Context)) // Logged in but not admin
{
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-user"></i> @UI.Layout_Welcome @Context.Request.Session[SessionKeys.UsernameKey] <span class="caret"></span></a>
@ -77,19 +78,19 @@
}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-language" aria-hidden="true"><span class="caret"></span></i></a>
<ul class="dropdown-menu" role="menu">
<li><a href="@url/culture?l=en&u=@Context.Request.Path">@UI.Layout_English</a></li>
<li><a href="@url/culture?l=fr&u=@Context.Request.Path">@UI.Layout_French</a></li>
<li><a href="@url/culture?l=nl&u=@Context.Request.Path">@UI.Layout_Dutch</a></li>
<li><a href="@url/culture?l=es&u=@Context.Request.Path">@UI.Layout_Spanish</a></li>
<li><a href="@url/culture?l=de&u=@Context.Request.Path">@UI.Layout_German</a></li>
<li><a href="@url/culture?l=da&u=@Context.Request.Path">@UI.Layout_Danish</a></li>
<li><a href="@url/culture?l=pt&u=@Context.Request.Path">@UI.Layout_Portuguese</a></li>
<li><a href="@url/culture?l=sv&u=@Context.Request.Path">@UI.Layout_Swedish</a></li>
<li><a href="@url/culture?l=it&u=@Context.Request.Path">@UI.Layout_Italian</a></li>
</ul>
<li/>
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><i class="fa fa-language" aria-hidden="true"><span class="caret"></span></i></a>
<ul class="dropdown-menu" role="menu">
<li><a href="@url/culture?l=en&u=@Context.Request.Path">@UI.Layout_English</a></li>
<li><a href="@url/culture?l=fr&u=@Context.Request.Path">@UI.Layout_French</a></li>
<li><a href="@url/culture?l=nl&u=@Context.Request.Path">@UI.Layout_Dutch</a></li>
<li><a href="@url/culture?l=es&u=@Context.Request.Path">@UI.Layout_Spanish</a></li>
<li><a href="@url/culture?l=de&u=@Context.Request.Path">@UI.Layout_German</a></li>
<li><a href="@url/culture?l=da&u=@Context.Request.Path">@UI.Layout_Danish</a></li>
<li><a href="@url/culture?l=pt&u=@Context.Request.Path">@UI.Layout_Portuguese</a></li>
<li><a href="@url/culture?l=sv&u=@Context.Request.Path">@UI.Layout_Swedish</a></li>
<li><a href="@url/culture?l=it&u=@Context.Request.Path">@UI.Layout_Italian</a></li>
</ul>
<li />
</ul>
</div>
</div>
@ -104,16 +105,17 @@
var donateLink = $("#customDonateHref");
var donationText = $("#donationText");
donateLink.attr("href", result.url);
if(result.message) {
if (result.message) {
donationText.text(result.message);
}
}
},
error: function(xhr, status, error) {
error: function (xhr, status, error) {
console.log("error " + error);
$("#customDonate").hide();
}
});
</script>
<div id="updateAvailable" hidden="hidden"></div>
<div id="cacherRunning" hidden="hidden"></div>
</nav>

@ -16,8 +16,6 @@
<i class="fa fa-2x fa-arrow-circle-up"></i>
</span>
</div>
@*@MiniProfiler.RenderIncludes()*@
</body>
@Html.GetInformationalVersion()

Loading…
Cancel
Save