pull/3400/head
Jamie Rees 4 years ago
commit 993510efdd

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -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>

@ -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>

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

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

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

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

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

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

@ -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" />

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

@ -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>

@ -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" />

@ -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
{

@ -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;

@ -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>

@ -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();
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}

@ -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;
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}
}

@ -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);
}
}
}
}
}

@ -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));
}
}
}

@ -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>

@ -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>

@ -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" />

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

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

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

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

@ -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>

@ -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>

@ -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;

@ -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);
}

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

@ -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

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

@ -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>

@ -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";
}
}

@ -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" />-->

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

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

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

@ -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" />

@ -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}

@ -7,4 +7,4 @@ wwwroot/dist
/connect.lock
/coverage/*
/Logs/**
**.db
**.db

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

@ -2,50 +2,57 @@
<wiki [url]="'https://github.com/tidusjar/Ombi/wiki/Ombi-Settings'"></wiki>
<fieldset *ngIf="form" class="container">
<legend>Ombi Configuration</legend>
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<legend>Ombi Configuration</legend>
<div class="col-12">
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
<mat-form-field>
<input matInput placeholder="Base Url" formControlName="baseUrl">
</mat-form-field>
<div class="col-12">
<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="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="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 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>
@ -62,4 +69,4 @@
</div>
</div>
</form>
</fieldset>
</fieldset>

@ -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;

@ -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;
}

@ -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>()

@ -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);
}
}
}
}

@ -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;
}
}
@ -62,7 +69,7 @@ namespace Ombi.Extensions
}
var databaseFileLocation = Path.Combine(i.StoragePath, "database.json");
var configuration = new DatabaseConfiguration(i.StoragePath);
if (File.Exists(databaseFileLocation))
{
@ -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);
}

@ -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;
}

@ -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') ">

@ -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>();

@ -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
});

Loading…
Cancel
Save