This commit is contained in:
Jamie Rees 2020-02-18 22:26:42 +00:00
commit 993510efdd
75 changed files with 772 additions and 124 deletions

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,10 +6,11 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" />
</ItemGroup>
<ItemGroup>

View file

@ -8,10 +8,11 @@
<PackageVersion></PackageVersion>
<AssemblyName>Ombi.Api.Service</AssemblyName>
<RootNamespace>Ombi.Api.Service</RootNamespace>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Options" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.1" />
</ItemGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,10 +6,11 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Polly" Version="7.1.0" />
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>

View file

@ -226,12 +226,12 @@ namespace Ombi.Core.Engine
//var secondProp = TypeDescriptor.GetProperties(propType).Find(properties[1], true);
}
allRequests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.OrderBy(x => prop.GetValue(x))
: allRequests.OrderByDescending(x => prop.GetValue(x));
var total = await allRequests.CountAsync();
var requests = await allRequests.Skip(position).Take(count)
.ToListAsync();
// TODO fix this so we execute this on the server
var requests = sortOrder.Equals("asc", StringComparison.InvariantCultureIgnoreCase)
? allRequests.ToList().OrderBy(x => x.RequestedDate).ToList()
: allRequests.ToList().OrderByDescending(x => prop.GetValue(x)).ToList();
var total = requests.Count();
requests = requests.Skip(position).Take(count).ToList();
await CheckForSubscription(shouldHide, requests);
return new RequestsViewModel<MovieRequests>

View file

@ -6,13 +6,14 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="3.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.1" />
<PackageReference Include="MusicBrainzAPI" Version="2.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />

View file

@ -16,7 +16,6 @@ using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities;
using Ombi.Store.Entities.Requests;
using Ombi.Store.Repository;
using Remotion.Linq.Parsing.Structure.IntermediateModel;
namespace Ombi.Core.Senders
{

View file

@ -1,7 +1,6 @@
using System.Diagnostics.CodeAnalysis;
using System.Security.Principal;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.DependencyInjection;
using Ombi.Api.Discord;
@ -62,7 +61,6 @@ using Ombi.Schedule.Jobs.Lidarr;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.SickRage;
using Ombi.Schedule.Processor;
using Ombi.Store.Entities;
using Quartz.Spi;
using Ombi.Api.MusicBrainz;
using Ombi.Api.Twilio;

View file

@ -6,12 +6,13 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.2.2" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.1" />
</ItemGroup>
<ItemGroup>

View file

@ -0,0 +1,26 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public abstract class BaseHealthCheck : IHealthCheck
{
private readonly IServiceScopeFactory _serviceScopeFactory;
public BaseHealthCheck(IServiceScopeFactory serviceScopeFactory)
{
_serviceScopeFactory = serviceScopeFactory;
}
public abstract Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default);
protected IServiceScope CreateScope()
{
return _serviceScopeFactory.CreateScope();
}
}
}

View file

@ -0,0 +1,53 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.CouchPotato;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Settings.Settings.Models.External;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class CouchPotatoHealthCheck : BaseHealthCheck
{
public CouchPotatoHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<CouchPotatoSettings>>();
var api = scope.ServiceProvider.GetRequiredService<ICouchPotatoApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (!settings.Enabled)
{
return HealthCheckResult.Healthy("CouchPotato is not configured.");
}
try
{
var result = await api.Status(settings.ApiKey, settings.FullUri);
if (result != null)
{
return HealthCheckResult.Healthy();
}
return HealthCheckResult.Degraded("Couldn't get the status from CouchPotato");
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with CouchPotato", e);
}
}
}
}
}

View file

@ -0,0 +1,53 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class EmbyHealthCheck : BaseHealthCheck
{
public EmbyHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<EmbySettings>>();
var api = scope.ServiceProvider.GetRequiredService<IEmbyApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (settings == null)
{
return HealthCheckResult.Healthy("Emby is not configured.");
}
var taskResult = new List<Task<EmbySystemInfo>>();
foreach (var server in settings.Servers)
{
taskResult.Add(api.GetSystemInformation(server.ApiKey, server.FullUri));
}
try
{
var result = await Task.WhenAll(taskResult.ToArray());
return HealthCheckResult.Healthy();
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Emby", e);
}
}
}
}
}

View file

@ -0,0 +1,48 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Lidarr;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models.External;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class LidarrHealthCheck : BaseHealthCheck
{
public LidarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<LidarrSettings>>();
var api = scope.ServiceProvider.GetRequiredService<ILidarrApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (!settings.Enabled)
{
return HealthCheckResult.Healthy("Lidarr is not configured.");
}
try
{
var result = await api.Status(settings.ApiKey, settings.FullUri);
if (result != null)
{
return HealthCheckResult.Healthy();
}
return HealthCheckResult.Degraded("Couldn't get the status from Lidarr");
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Lidarr", e);
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using HealthChecks.Network;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class OmbiPingHealthCheck
: IHealthCheck
{
private readonly OmbiPingHealthCheckOptions _options;
public OmbiPingHealthCheck(OmbiPingHealthCheckOptions options)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
}
public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
var configuredHosts = _options.ConfiguredHosts.Values;
try
{
foreach (var (host, timeout, status) in configuredHosts)
{
using (var ping = new Ping())
{
var pingReply = await ping.SendPingAsync(host, timeout);
if (pingReply.Status != IPStatus.Success)
{
return new HealthCheckResult(status, description: $"Ping check for host {host} is failed with status reply:{pingReply.Status}");
}
}
}
return HealthCheckResult.Healthy();
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
}
}
}
}

View file

@ -0,0 +1,16 @@
using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.Collections.Generic;
namespace Ombi.HealthChecks.Checks
{
public class OmbiPingHealthCheckOptions
{
internal Dictionary<string, (string Host, int TimeOut, HealthStatus status)> ConfiguredHosts { get; } = new Dictionary<string, (string, int, HealthStatus)>();
public OmbiPingHealthCheckOptions AddHost(string host, int timeout, HealthStatus status)
{
ConfiguredHosts.Add(host, (host, timeout, status));
return this;
}
}
}

View file

@ -0,0 +1,51 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class PlexHealthCheck : BaseHealthCheck
{
public PlexHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<PlexSettings>>();
var api = scope.ServiceProvider.GetRequiredService<IPlexApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (settings == null)
{
return HealthCheckResult.Healthy("Plex is not confiured.");
}
var taskResult = new List<Task<PlexStatus>>();
foreach (var server in settings.Servers)
{
taskResult.Add(api.GetStatus(server.PlexAuthToken, server.FullUri));
}
try
{
var result = await Task.WhenAll(taskResult.ToArray());
return HealthCheckResult.Healthy();
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Plex", e);
}
}
}
}
}

View file

@ -0,0 +1,47 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Radarr;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models.External;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class RadarrHealthCheck : BaseHealthCheck, IHealthCheck
{
public RadarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<RadarrSettings>>();
var api = scope.ServiceProvider.GetRequiredService<IRadarrApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (!settings.Enabled)
{
return HealthCheckResult.Healthy("Radarr is not configured.");
}
try
{
var result = await api.SystemStatus(settings.ApiKey, settings.FullUri);
if (result != null)
{
return HealthCheckResult.Healthy();
}
return HealthCheckResult.Degraded("Couldn't get the status from Radarr");
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Radarr", e);
}
}
}
}
}

View file

@ -0,0 +1,54 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.CouchPotato;
using Ombi.Api.Emby;
using Ombi.Api.Emby.Models;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models.Status;
using Ombi.Api.SickRage;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Settings.Settings.Models.External;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class SickrageHealthCheck : BaseHealthCheck
{
public SickrageHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<SickRageSettings>>();
var api = scope.ServiceProvider.GetRequiredService<ISickRageApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (!settings.Enabled)
{
return HealthCheckResult.Healthy("SickRage is not configured.");
}
try
{
var result = await api.Ping(settings.ApiKey, settings.FullUri);
if (result != null)
{
return HealthCheckResult.Healthy();
}
return HealthCheckResult.Degraded("Couldn't get the status from SickRage");
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with SickRage", e);
}
}
}
}
}

View file

@ -0,0 +1,48 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.Api.Sonarr;
using Ombi.Core.Settings;
using Ombi.Settings.Settings.Models.External;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Ombi.HealthChecks.Checks
{
public class SonarrHealthCheck : BaseHealthCheck
{
public SonarrHealthCheck(IServiceScopeFactory serviceScopeFactory) : base(serviceScopeFactory)
{
}
public override async Task<HealthCheckResult> CheckHealthAsync(
HealthCheckContext context,
CancellationToken cancellationToken = default)
{
using (var scope = CreateScope())
{
var settingsProvider = scope.ServiceProvider.GetRequiredService<ISettingsService<SonarrSettings>>();
var api = scope.ServiceProvider.GetRequiredService<ISonarrApi>();
var settings = await settingsProvider.GetSettingsAsync();
if (!settings.Enabled)
{
return HealthCheckResult.Healthy("Sonarr is not configured.");
}
try
{
var result = await api.SystemStatus(settings.ApiKey, settings.FullUri);
if (result != null)
{
return HealthCheckResult.Healthy();
}
return HealthCheckResult.Degraded("Couldn't get the status from Sonarr");
}
catch (Exception e)
{
return HealthCheckResult.Unhealthy("Could not communicate with Sonarr", e);
}
}
}
}
}

View file

@ -0,0 +1,55 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Ombi.HealthChecks.Checks;
using System;
using System.Collections.Generic;
namespace Ombi.HealthChecks
{
public static class HealthCheckExtensions
{
public static IHealthChecksBuilder AddOmbiHealthChecks(this IHealthChecksBuilder builder)
{
builder.AddCheck<PlexHealthCheck>("Plex", tags: new string[] { "MediaServer" });
builder.AddCheck<EmbyHealthCheck>("Emby", tags: new string[] { "MediaServer" });
builder.AddCheck<LidarrHealthCheck>("Lidarr", tags: new string[] { "DVR" });
builder.AddCheck<SonarrHealthCheck>("Sonarr", tags: new string[] { "DVR" });
builder.AddCheck<RadarrHealthCheck>("Radarr", tags: new string[] { "DVR" });
builder.AddCheck<CouchPotatoHealthCheck>("CouchPotato", tags: new string[] { "DVR" });
builder.AddCheck<SickrageHealthCheck>("SickRage", tags: new string[] { "DVR" });
builder.AddOmbiPingHealthCheck(options =>
{
options.AddHost("www.google.co.uk", 5000, HealthStatus.Unhealthy);
options.AddHost("www.google.com", 3000, HealthStatus.Degraded);
}, "External Ping", tags: new string[] { "System" });
return builder;
}
/// <summary>
/// Add a health check for network ping.
/// </summary>
/// <param name="builder">The <see cref="IHealthChecksBuilder"/>.</param>
/// <param name="setup">The action to configure the ping parameters.</param>
/// <param name="name">The health check name. Optional. If <c>null</c> the type name 'ping' will be used for the name.</param>
/// <param name="failureStatus">
/// The <see cref="HealthStatus"/> that should be reported when the health check fails. Optional. If <c>null</c> then
/// the default status of <see cref="HealthStatus.Unhealthy"/> will be reported.
/// </param>
/// <param name="tags">A list of tags that can be used to filter sets of health checks. Optional.</param>
/// <param name="timeout">An optional System.TimeSpan representing the timeout of the check.</param>
/// <returns>The <see cref="IHealthChecksBuilder"/>.</returns></param>
public static IHealthChecksBuilder AddOmbiPingHealthCheck(this IHealthChecksBuilder builder, Action<OmbiPingHealthCheckOptions> setup, string name = default, HealthStatus? failureStatus = default, IEnumerable<string> tags = default, TimeSpan? timeout = default)
{
var options = new OmbiPingHealthCheckOptions();
setup?.Invoke(options);
return builder.Add(new HealthCheckRegistration(
name,
sp => new OmbiPingHealthCheck(options),
failureStatus,
tags,
timeout));
}
}
}

View file

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.Network" Version="3.0.1" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.HealthChecks" Version="2.2.0" />
<PackageReference Include="System.Collections" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.CouchPotato\Ombi.Api.CouchPotato.csproj" />
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
<ProjectReference Include="..\Ombi.Api.Lidarr\Ombi.Api.Lidarr.csproj" />
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
<ProjectReference Include="..\Ombi.Api.SickRage\Ombi.Api.SickRage.csproj" />
<ProjectReference Include="..\Ombi.Api.Sonarr\Ombi.Api.Sonarr.csproj" />
</ItemGroup>
</Project>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View file

@ -6,12 +6,13 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EasyCrypto" Version="3.3.2" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" />
<PackageReference Include="Quartz" Version="3.0.7" />

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>

View file

@ -6,11 +6,12 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ensure.That" Version="7.0.0-pre32" />
<PackageReference Include="MailKit" Version="2.1.3" />
<PackageReference Include="MailKit" Version="2.5.0" />
</ItemGroup>
<ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
@ -18,10 +18,4 @@
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.SignalR.Core">
<HintPath>..\..\..\..\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.signalr.core\1.1.0\lib\netstandard2.0\Microsoft.AspNetCore.SignalR.Core.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View file

@ -19,7 +19,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
{
public class LidarrAvailabilityChecker : ILidarrAvailabilityChecker
{
public LidarrAvailabilityChecker(IMusicRequestRepository requests, IRepository<LidarrAlbumCache> albums, ILogger<LidarrAvailabilityChecker> log,
public LidarrAvailabilityChecker(IMusicRequestRepository requests, IExternalRepository<LidarrAlbumCache> albums, ILogger<LidarrAvailabilityChecker> log,
INotificationHelper notification, IHubContext<NotificationHub> notificationHub)
{
_cachedAlbums = albums;
@ -30,7 +30,7 @@ namespace Ombi.Schedule.Jobs.Lidarr
}
private readonly IMusicRequestRepository _requestRepository;
private readonly IRepository<LidarrAlbumCache> _cachedAlbums;
private readonly IExternalRepository<LidarrAlbumCache> _cachedAlbums;
private readonly ILogger _logger;
private readonly INotificationHelper _notificationService;
private readonly IHubContext<NotificationHub> _notification;

View file

@ -83,12 +83,12 @@ namespace Ombi.Schedule.Jobs.Ombi
{
// Ensure we check that we have not linked this item to a request
var allMovies = _plexRepo.GetAll().Where(x =>
x.Type == PlexMediaTypeEntity.Movie && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue()));
x.Type == PlexMediaTypeEntity.Movie && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null));
await StartPlexMovies(allMovies);
// Now Tv
var allTv = _plexRepo.GetAll().Where(x =>
x.Type == PlexMediaTypeEntity.Show && !x.RequestId.HasValue && (!x.TheMovieDbId.HasValue() || !x.ImdbId.HasValue() || !x.TvDbId.HasValue()));
x.Type == PlexMediaTypeEntity.Show && x.RequestId == null && (x.TheMovieDbId == null || x.ImdbId == null || x.TvDbId == null));
await StartPlexTv(allTv);
}

View file

@ -6,6 +6,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Ombi.Core.Notifications;
using Ombi.Core.Settings;
using Ombi.Helpers;
@ -16,7 +15,6 @@ using Ombi.Schedule.Jobs.Radarr;
using Ombi.Schedule.Jobs.SickRage;
using Ombi.Schedule.Jobs.Sonarr;
using Ombi.Settings.Settings.Models;
using Quartz;
using Quartz.Spi;
namespace Ombi.Schedule

View file

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFramework>netcoreapp3.0</TargetFramework>
<PropertyGroup><TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View file

@ -6,10 +6,11 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.1" />
<PackageReference Include="Quartz" Version="3.0.7" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>

View file

@ -10,6 +10,7 @@
public bool IgnoreCertificateErrors { get; set; }
public bool DoNotSendNotificationsForAutoApprove { get; set; }
public bool HideRequestsUsers { get; set; }
public bool DisableHealthChecks { get; set; }
public string DefaultLanguageCode { get; set; } = "en";
}
}

View file

@ -7,15 +7,18 @@
<Version></Version>
<PackageVersion></PackageVersion>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.4" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.1.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.1" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.6" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
<PackageReference Include="Nito.AsyncEx" Version="5.0.0-pre-05" />
<PackageReference Include="Polly" Version="7.1.0" />
<!--<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="1.1.9" />-->

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>8.0</LangVersion>
</PropertyGroup>
<ItemGroup>

View file

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>

View file

@ -7,6 +7,7 @@
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup>

View file

@ -3,7 +3,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<RuntimeIdentifiers>win10-x64;win10-x86;osx-x64;ubuntu-x64;debian.8-x64;centos.7-x64;linux-x64;linux-arm;linux-arm64;</RuntimeIdentifiers>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
@ -12,14 +12,14 @@
<ItemGroup>
<PackageReference Include="CommandLineParser" Version="2.6.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />

View file

@ -110,7 +110,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.GroupMe", "Ombi.Ap
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.MusicBrainz", "Ombi.Api.MusicBrainz\Ombi.Api.MusicBrainz.csproj", "{C5C1769B-4197-4410-A160-0EEF39EDDC98}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Twilio", "Ombi.Api.Twilio\Ombi.Api.Twilio.csproj", "{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.HealthChecks", "Ombi.HealthChecks\Ombi.HealthChecks.csproj", "{59D19538-0496-44EE-936E-EBBC22CF7B27}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Webhook", "Ombi.Api.Webhook\Ombi.Api.Webhook.csproj", "{E2186FDA-D827-4781-8663-130AC382F12C}"
EndProject
@ -300,6 +302,10 @@ Global
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3}.Release|Any CPU.Build.0 = Release|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Debug|Any CPU.Build.0 = Debug|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.ActiveCfg = Release|Any CPU
{59D19538-0496-44EE-936E-EBBC22CF7B27}.Release|Any CPU.Build.0 = Release|Any CPU
{E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E2186FDA-D827-4781-8663-130AC382F12C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E2186FDA-D827-4781-8663-130AC382F12C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -348,6 +354,7 @@ Global
{9266403C-B04D-4C0F-AC39-82F12C781949} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{C5C1769B-4197-4410-A160-0EEF39EDDC98} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{34E5DD1A-6A90-448B-9E71-64D1ACD6C1A3} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{59D19538-0496-44EE-936E-EBBC22CF7B27} = {410F36CF-9C60-428A-B191-6FD90610991A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}

View file

@ -16,6 +16,7 @@ export interface IOmbiSettings extends ISettings {
doNotSendNotificationsForAutoApprove: boolean;
hideRequestsUsers: boolean;
defaultLanguageCode: string;
disableHealthChecks: boolean;
}
export interface IUpdateSettings extends ISettings {

View file

@ -2,50 +2,57 @@
<wiki [url]="'https://github.com/tidusjar/Ombi/wiki/Ombi-Settings'"></wiki>
<fieldset *ngIf="form" class="container">
<legend>Ombi Configuration</legend>
<legend>Ombi Configuration</legend>
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<div class="col-12">
<div class="col-12">
<mat-form-field>
<input matInput placeholder="Base Url" formControlName="baseUrl">
</mat-form-field>
<mat-form-field>
<input matInput placeholder="Base Url" formControlName="baseUrl">
</mat-form-field>
<div class="form-group">
<label for="ApiKey" class="control-label">Api Key</label>
<div class="input-group">
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey"
readonly="readonly" #apiKey>
<div class="form-group">
<label for="ApiKey" class="control-label">Api Key</label>
<div class="input-group">
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey" readonly="readonly" #apiKey>
<div class="input-group-addon">
<div (click)="refreshApiKey()" id="refreshKey" class="fa fa-refresh" title="Reset API Key" pTooltip="This will invalidate the old API key"></div>
</div>
<div class="input-group-addon">
<div (click)="refreshApiKey()" id="refreshKey" class="fa fa-refresh" title="Reset API Key" pTooltip="This will invalidate the old API key"></div>
</div>
<div class="input-group-addon">
<div ngxClipboard [ngxClipboard]="apiKey" class="fa fa-clipboard" (cbOnSuccess)="successfullyCopied()"></div>
</div>
<div class="input-group-addon">
<div ngxClipboard [ngxClipboard]="apiKey" class="fa fa-clipboard" (cbOnSuccess)="successfullyCopied()"></div>
</div>
</div>
</div>
<br />
<div>
<mat-checkbox formControlName="doNotSendNotificationsForAutoApprove">
Do not send Notifications if a User has the Auto Approve permission</mat-checkbox>
</div>
<div>
<mat-checkbox formControlName="hideRequestsUsers">
Hide requests from other users
</mat-checkbox>
</div>
<div>
<mat-checkbox formControlName="ignoreCertificateErrors" matTooltip="Enable if you are having connectivity problems over SSL">
Ignore any certificate errors
</mat-checkbox>
</div>
<div>
<mat-checkbox formControlName="collectAnalyticData" matTooltip="This will allow us to have a better understanding of the userbase so we know what we should be supporting">
Allow us to collect anonymous analytical data e.g. browser used
</mat-checkbox>
</div>
<div>
<mat-checkbox formControlName="disableHealthChecks">
Disable the health checks page <a href="/healthchecks-ui" target="_blank">/healthchecks-ui</href></mat-checkbox>
</div>
</div>
<br />
<div>
<mat-checkbox formControlName="doNotSendNotificationsForAutoApprove">
Do not send Notifications if a User has the Auto Approve permission</mat-checkbox>
</div><div>
<mat-checkbox formControlName="hideRequestsUsers">
Hide requests from other users
</mat-checkbox>
</div><div>
<mat-checkbox formControlName="ignoreCertificateErrors" matTooltip="Enable if you are having connectivity problems over SSL">
Ignore any certificate errors
</mat-checkbox>
</div><div>
<mat-checkbox formControlName="collectAnalyticData" matTooltip="This will allow us to have a better understanding of the userbase so we know what we should be supporting">
Allow us to collect anonymous analytical data e.g. browser used
</mat-checkbox>
</div><div>
<div>
<mat-form-field *ngIf="langauges">
<mat-select placeholder="Language" formControlName="defaultLanguageCode">
<mat-option>--</mat-option>

View file

@ -29,6 +29,7 @@ export class OmbiComponent implements OnInit {
doNotSendNotificationsForAutoApprove: [x.doNotSendNotificationsForAutoApprove],
hideRequestsUsers: [x.hideRequestsUsers],
defaultLanguageCode: [x.defaultLanguageCode],
disableHealthChecks: [x.disableHealthChecks]
});
});
this.langauges = <ILanguageRefine[]><any>languageData;

View file

@ -67,11 +67,14 @@ namespace Ombi.Controllers.V1
var val = await _memCache.GetOrAdd(CacheKeys.Update, async () =>
{
var productArray = _updater.GetVersion();
var version = productArray[0];
var branch = productArray[1];
var updateAvailable = await _updater.UpdateAvailable(branch, version);
if (productArray.Length > 1)
{
var version = productArray[0];
var branch = productArray[1];
var updateAvailable = await _updater.UpdateAvailable(branch, version);
}
return updateAvailable;
return true;
});
return val;
}

View file

@ -1145,7 +1145,8 @@ namespace Ombi.Controllers.V1
// Make sure we do not display the newsletter
templates = templates.Where(x => x.NotificationType != NotificationType.Newsletter);
}
return templates.OrderBy(x => x.NotificationType.ToString()).ToList();
var tem = templates.ToList();
return tem.OrderBy(x => x.NotificationType.ToString()).ToList();
}
private async Task<T> Get<T>()

View file

@ -33,18 +33,22 @@ namespace Ombi.Controllers.V2
public async Task<IActionResult> ReadLogFile(string logFileName, CancellationToken token)
{
var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName);
await using var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader reader = new StreamReader(fs);
return Ok(await reader.ReadToEndAsync());
using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader reader = new StreamReader(fs))
{
return Ok(await reader.ReadToEndAsync());
}
}
[HttpGet("logs/download/{logFileName}")]
public IActionResult Download(string logFileName, CancellationToken token)
{
var logFile = Path.Combine(_hosting.ContentRootPath, "Logs", logFileName);
using var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
using StreamReader reader = new StreamReader(fs);
return File(reader.BaseStream, "application/octet-stream", logFileName);
using (var fs = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (StreamReader reader = new StreamReader(fs))
{
return File(reader.BaseStream, "application/octet-stream", logFileName);
}
}
}
}

View file

@ -2,6 +2,7 @@
using System.IO;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Newtonsoft.Json;
using Ombi.Helpers;
using Ombi.Store.Context;
@ -17,7 +18,7 @@ namespace Ombi.Extensions
public const string SqliteDatabase = "Sqlite";
public const string MySqlDatabase = "MySQL";
public static void ConfigureDatabases(this IServiceCollection services)
public static void ConfigureDatabases(this IServiceCollection services, IHealthChecksBuilder hcBuilder)
{
var configuration = GetDatabaseConfiguration();
@ -26,9 +27,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<OmbiContext, OmbiSqliteContext>(x => ConfigureSqlite(x, configuration.OmbiDatabase));
AddSqliteHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<OmbiContext, OmbiMySqlContext>(x => ConfigureMySql(x, configuration.OmbiDatabase));
AddMySqlHealthCheck(hcBuilder, "Ombi Database", configuration.OmbiDatabase);
break;
}
@ -36,9 +39,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<ExternalContext, ExternalSqliteContext>(x => ConfigureSqlite(x, configuration.ExternalDatabase));
AddSqliteHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<ExternalContext, ExternalMySqlContext>(x => ConfigureMySql(x, configuration.ExternalDatabase));
AddMySqlHealthCheck(hcBuilder, "External Database", configuration.ExternalDatabase);
break;
}
@ -46,9 +51,11 @@ namespace Ombi.Extensions
{
case var type when type.Equals(SqliteDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<SettingsContext, SettingsSqliteContext>(x => ConfigureSqlite(x, configuration.SettingsDatabase));
AddSqliteHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase);
break;
case var type when type.Equals(MySqlDatabase, StringComparison.InvariantCultureIgnoreCase):
services.AddDbContext<SettingsContext, SettingsMySqlContext>(x => ConfigureMySql(x, configuration.SettingsDatabase));
AddMySqlHealthCheck(hcBuilder, "Settings Database", configuration.SettingsDatabase);
break;
}
}
@ -78,11 +85,36 @@ namespace Ombi.Extensions
return configuration;
}
private static void AddSqliteHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config)
{
if (builder != null)
{
builder.AddSqlite(
sqliteConnectionString: config.ConnectionString,
name: dbName,
failureStatus: HealthStatus.Unhealthy,
tags: new string[] { "db" });
}
}
private static void AddMySqlHealthCheck(IHealthChecksBuilder builder, string dbName, PerDatabaseConfiguration config)
{
if (builder != null)
{
builder.AddMySql(
connectionString: config.ConnectionString,
name: dbName,
failureStatus: HealthStatus.Unhealthy,
tags: new string[] { "db" }
);
}
}
public static void ConfigureSqlite(DbContextOptionsBuilder options, PerDatabaseConfiguration config)
{
SQLitePCL.Batteries.Init();
SQLitePCL.raw.sqlite3_config(raw.SQLITE_CONFIG_MULTITHREAD);
options.UseSqlite(config.ConnectionString);
}

14
src/Ombi/HealthCheck.css Normal file
View file

@ -0,0 +1,14 @@
:root {
--primaryColor: #424242;
--secondaryColor: #f9dc43;
--bgMenuActive: #f9dc43;
--bgButton: #f9dc43;
--logoImageUrl: url('https://ombi.io/img/logo-orange-small.png');
--bgAside: var(--primaryColor);
}
#outer-container > aside > nav > a:nth-child(2) {
display: none;
}

View file

@ -1,6 +1,6 @@
<Project ToolsVersion="15.0" Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifiers>win10-x64;win10-x86;osx-x64;linux-x64;linux-arm;linux-arm64;</RuntimeIdentifiers>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<TypeScriptToolsVersion>Latest</TypeScriptToolsVersion>
@ -56,24 +56,29 @@
<ItemGroup>
<PackageReference Include="AspNetCore.HealthChecks.MySql" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.Sqlite" Version="3.0.0" />
<PackageReference Include="AspNetCore.HealthChecks.UI" Version="3.0.9" />
<PackageReference Include="AspNetCore.HealthChecks.UI.Client" Version="3.0.2" />
<PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="CommandLineParser" Version="2.6.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="2.2.0" />
<PackageReference Include="ncrontab" Version="3.3.0" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.6" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.1.1" />
<PackageReference Include="Serilog" Version="2.9.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.RollingFile" Version="3.3.1-dev-00771" />
<PackageReference Include="Serilog.Sinks.SQLite" Version="4.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
<PackageReference Include="System.Security.Cryptography.Csp" Version="4.3.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
@ -84,6 +89,7 @@
<ProjectReference Include="..\Ombi.Api.Twilio\Ombi.Api.Twilio.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.DependencyInjection\Ombi.DependencyInjection.csproj" />
<ProjectReference Include="..\Ombi.HealthChecks\Ombi.HealthChecks.csproj" />
<ProjectReference Include="..\Ombi.Hubs\Ombi.Hubs.csproj" />
<ProjectReference Include="..\Ombi.Mapping\Ombi.Mapping.csproj" />
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />
@ -92,6 +98,12 @@
<ProjectReference Include="..\Ombi.Updater\Ombi.Updater.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="HealthCheck.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">

View file

@ -59,7 +59,7 @@ namespace Ombi
//CheckAndMigrate();
var services = new ServiceCollection();
services.ConfigureDatabases();
services.ConfigureDatabases(null);
using (var provider = services.BuildServiceProvider())
{
var settingsDb = provider.GetRequiredService<SettingsContext>();

View file

@ -28,6 +28,9 @@ using Microsoft.AspNetCore.StaticFiles.Infrastructure;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using ILogger = Serilog.ILogger;
using HealthChecks.UI.Client;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Ombi.HealthChecks;
namespace Ombi
{
@ -73,8 +76,14 @@ namespace Ombi
options.User.AllowedUserNameCharacters = string.Empty;
});
services.ConfigureDatabases();
services.AddHealthChecks();
var hcBuilder = services.AddHealthChecks();
hcBuilder.AddOmbiHealthChecks();
services.ConfigureDatabases(hcBuilder);
// Need to wait until https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/410 is resolved
//services.AddHealthChecksUI(setupSettings: setup =>
//{
// setup.AddHealthCheckEndpoint("Ombi", "/health");
//});
services.AddMemoryCache();
services.AddJwtAuthentication(Configuration);
@ -107,7 +116,7 @@ namespace Ombi
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
{
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
@ -204,17 +213,25 @@ namespace Ombi
{
endpoints.MapControllers();
endpoints.MapHub<NotificationHub>("/hubs/notification");
endpoints.MapHealthChecks("/health");
if (!settings.DisableHealthChecks)
{
endpoints.MapHealthChecks("/health", new HealthCheckOptions
{
Predicate = _ => true,
ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse
});
endpoints.MapHealthChecksUI(opts =>
{
opts.AddCustomStylesheet("HealthCheck.css");
});
}
});
app.UseSpa(spa =>
{
#if DEBUG
//if (env.IsDevelopment())
//{
spa.Options.SourcePath = "ClientApp";
spa.UseProxyToSpaDevelopmentServer("http://localhost:3578");
//}
#endif
});