Lots more work :(

pull/1425/head
Jamie.Rees 7 years ago
parent f706b36ae5
commit 396bc5588a

@ -1,16 +0,0 @@
using System;
using NUnit.Framework;
namespace Ombi.Core.Tests
{
[TestFixture]
public class MovieEngineTests
{
[Test]
public void Test()
{
Assert.IsTrue(true);
}
}
}

@ -1,21 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<OutputType>Library</OutputType>
</PropertyGroup>
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
<ApplicationIcon />
<OutputType>Exe</OutputType>
<OutputTypeEx>library</OutputTypeEx>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.TestPlatform.TestHost" Version="15.0.0" />
<PackageReference Include="NUnit" Version="3.6.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.7.0" />
</ItemGroup>
</Project>

@ -1,6 +1,5 @@
using System.Security.Principal;
using Ombi.Core.Claims;
using Ombi.Core.Settings.Models;
using Ombi.Store.Entities;
namespace Ombi.Core.Engine.Interfaces

@ -4,22 +4,27 @@ using System.Globalization;
using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks;
using Hangfire;
using Ombi.Api.TheMovieDb;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search;
using Ombi.Core.Requests.Models;
using Ombi.Store.Entities;
using Ombi.Helpers;
using Ombi.Notifications;
using Ombi.Notifications.Models;
namespace Ombi.Core.Engine
{
public class RequestEngine : BaseMediaEngine, IRequestEngine
{
public RequestEngine(IMovieDbApi movieApi, IRequestService requestService, IPrincipal user) : base(user, requestService)
public RequestEngine(IMovieDbApi movieApi, IRequestService requestService, IPrincipal user, INotificationService notificationService) : base(user, requestService)
{
MovieApi = movieApi;
NotificationService = notificationService;
}
private IMovieDbApi MovieApi { get; }
private INotificationService NotificationService { get; }
public async Task<RequestEngineResult> RequestMovie(SearchMovieViewModel model)
{
var movieInfo = await MovieApi.GetMovieInformation(model.Id);
@ -133,16 +138,16 @@ namespace Ombi.Core.Engine
{
//Log.Fatal(e);
//await FaultQueue.QueueItemAsync(model, movieInfo.Id.ToString(), RequestType.Movie, FaultType.RequestFault, e.Message);
//await NotificationService.Publish(new NotificationModel
//{
// DateTime = DateTime.Now,
// User = Username,
// RequestType = RequestType.Movie,
// Title = model.Title,
// NotificationType = NotificationType.ItemAddedToFaultQueue
//});
var notification = new NotificationModel
{
DateTime = DateTime.Now,
User = Username,
RequestType = RequestType.Movie,
Title = model.Title,
NotificationType = NotificationType.ItemAddedToFaultQueue
};
BackgroundJob.Enqueue(() => NotificationService.Publish(notification).Wait());
//return Response.AsJson(new JsonResponseModel
//{
// Result = true,
@ -160,16 +165,17 @@ namespace Ombi.Core.Engine
if (ShouldSendNotification(model.Type))
{
// var notificationModel = new NotificationModel
// {
// Title = model.Title,
// User = Username,
// DateTime = DateTime.Now,
// NotificationType = NotificationType.NewRequest,
// RequestType = model.Type,
// ImgSrc = model.Type == RequestType.Movie ? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}" : model.PosterPath
// };
// await NotificationService.Publish(notificationModel);
var notificationModel = new NotificationModel
{
Title = model.Title,
User = Username,
DateTime = DateTime.Now,
NotificationType = NotificationType.NewRequest,
RequestType = model.Type,
ImgSrc = model.Type == RequestType.Movie ? $"https://image.tmdb.org/t/p/w300/{model.PosterPath}" : model.PosterPath
};
BackgroundJob.Enqueue(() => NotificationService.Publish(notificationModel).Wait());
}
//var limit = await RequestLimitRepo.GetAllAsync();

@ -18,6 +18,8 @@
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.TvMaze\Ombi.Api.TvMaze.csproj" />
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.Notifications\Ombi.Notifications.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
</ItemGroup>

@ -17,7 +17,10 @@ using Ombi.Core.IdentityResolver;
using Ombi.Core.Models.Requests;
using Ombi.Core.Requests.Models;
using Ombi.Core.Settings;
using Ombi.Notifications;
using Ombi.Schedule;
using Ombi.Schedule.Jobs;
using Ombi.Settings.Settings;
using Ombi.Store.Context;
using Ombi.Store.Repository;
using Ombi.TheMovieDbApi;
@ -71,13 +74,15 @@ namespace Ombi.DependencyInjection
public static IServiceCollection RegisterServices(this IServiceCollection services)
{
services.AddTransient<IRequestService, JsonRequestService>();
services.AddSingleton<INotificationService, NotificationService>();
return services;
}
public static IServiceCollection RegisterJobs(this IServiceCollection services)
{
services.AddTransient<ITestJob, TestJob>();
services.AddTransient<IPlexContentCacher, PlexContentCacher>();
services.AddTransient<IJobSetup, JobSetup>();
return services;
}

@ -16,7 +16,9 @@
<ProjectReference Include="..\Ombi.Api.Sonarr\Ombi.Api.Sonarr.csproj" />
<ProjectReference Include="..\Ombi.Api.TvMaze\Ombi.Api.TvMaze.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.Notifications\Ombi.Notifications.csproj" />
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
</ItemGroup>
</Project>

@ -10,10 +10,4 @@
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<Reference Include="System.IdentityModel">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.IdentityModel.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

@ -0,0 +1,223 @@
using System;
using System.Threading.Tasks;
using MailKit.Net.Smtp;
using MimeKit;
using Ombi.Core.Models.Requests;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.Notifications;
using Ombi.Notifications.Models;
using Ombi.Notifications.Templates;
namespace Ombi.Notifications.Email
{
public class EmailNotification : BaseNotification<EmailNotificationSettings>
{
public EmailNotification(ISettingsService<EmailNotificationSettings> settings) : base(settings)
{
}
public override string NotificationName => nameof(EmailNotification);
protected override bool ValidateConfiguration(EmailNotificationSettings settings)
{
if (settings.Authentication)
{
if (string.IsNullOrEmpty(settings.EmailUsername) || string.IsNullOrEmpty(settings.EmailPassword))
{
return false;
}
}
if (string.IsNullOrEmpty(settings.EmailHost) || string.IsNullOrEmpty(settings.RecipientEmail) || string.IsNullOrEmpty(settings.EmailPort.ToString()))
{
return false;
}
return true;
}
protected override async Task NewRequest(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
$"Ombi: New {model.RequestType.GetString()?.ToLower()} request for {model.Title}!",
$"Hello! The user '{model.User}' has requested the {model.RequestType.GetString()?.ToLower()} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime:f}",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: New {model.RequestType.GetString()?.ToLower()} request for {model.Title}!",
To = settings.RecipientEmail,
};
message.Other.Add("PlainTextBody", $"Hello! The user '{model.User}' has requested the {model.RequestType.GetString()?.ToLower()} '{model.Title}'! Please log in to approve this request. Request Date: {model.DateTime:f}");
await Send(message, settings);
}
protected override async Task Issue(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
$"Ombi: New issue for {model.Title}!",
$"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: New issue for {model.Title}!",
To = settings.RecipientEmail,
};
message.Other.Add("PlainTextBody", $"Hello! The user '{model.User}' has reported a new issue {model.Body} for the title {model.Title}!");
await Send(message, settings);
}
protected override async Task AddedToRequestQueue(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
"Ombi: A request could not be added.",
$"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: A request could not be added",
To = settings.RecipientEmail,
};
message.Other.Add("PlainTextBody", $"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying");
await Send(message, settings);
}
protected override async Task RequestDeclined(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
"Ombi: Your request has been declined",
$"Hello! Your request for {model.Title} has been declined, Sorry!",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: Your request has been declined",
To = model.UserEmail,
};
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been declined, Sorry!");
await Send(message, settings);
}
protected override async Task RequestApproved(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
"Ombi: Your request has been approved!",
$"Hello! Your request for {model.Title} has been approved!",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: Your request has been approved!",
To = model.UserEmail,
};
message.Other.Add("PlainTextBody", $"Hello! Your request for {model.Title} has been approved!");
await Send(message, settings);
}
protected override async Task AvailableRequest(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
$"Ombi: {model.Title} is now available!",
$"Hello! You requested {model.Title} on Ombi! This is now available on Plex! :)",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: {model.Title} is now available!",
To = model.UserEmail,
};
message.Other.Add("PlainTextBody", $"Hello! You requested {model.Title} on Ombi! This is now available on Plex! :)");
await Send(message, settings);
}
protected override async Task Send(NotificationMessage model, EmailNotificationSettings settings)
{
try
{
var body = new BodyBuilder
{
HtmlBody = model.Message,
TextBody = model.Other["PlainTextBody"]
};
var message = new MimeMessage
{
Body = body.ToMessageBody(),
Subject = model.Subject
};
message.From.Add(new MailboxAddress(settings.EmailSender, settings.EmailSender));
message.To.Add(new MailboxAddress(model.To, model.To));
using (var client = new SmtpClient())
{
client.Connect(settings.EmailHost, settings.EmailPort); // Let MailKit figure out the correct SecureSocketOptions.
// Note: since we don't have an OAuth2 token, disable
// the XOAUTH2 authentication mechanism.
client.AuthenticationMechanisms.Remove("XOAUTH2");
if (settings.Authentication)
{
client.Authenticate(settings.EmailUsername, settings.EmailPassword);
}
//Log.Info("sending message to {0} \r\n from: {1}\r\n Are we authenticated: {2}", message.To, message.From, client.IsAuthenticated);
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
}
catch (Exception e)
{
//Log.Error(e);
throw new InvalidOperationException(e.Message);
}
}
protected override async Task Test(NotificationModel model, EmailNotificationSettings settings)
{
var email = new EmailBasicTemplate();
var html = email.LoadTemplate(
"Test Message",
"This is just a test! Success!",
model.ImgSrc);
var message = new NotificationMessage
{
Message = html,
Subject = $"Ombi: Test",
To = settings.RecipientEmail,
};
message.Other.Add("PlainTextBody", "This is just a test! Success!");
await Send(message, settings);
}
}
}

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MailKit" Version="1.16.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.Notifications.Templates\Ombi.Notifications.Templates.csproj" />
<ProjectReference Include="..\Ombi.Notifications\Ombi.Notifications.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,8 @@
using System;
namespace Ombi.Notifications.Emil
{
public class Class1
{
}
}

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

@ -0,0 +1,34 @@
using System;
using System.IO;
using System.Text;
namespace Ombi.Notifications.Templates
{
public class EmailBasicTemplate : IEmailBasicTemplate
{
public string TemplateLocation => Path.Combine(Directory.GetCurrentDirectory(), "Templates","BasicTemplate.html");
private const string SubjectKey = "{@SUBJECT}";
private const string BodyKey = "{@BODY}";
private const string ImgSrc = "{@IMGSRC}";
private const string DateKey = "{@DATENOW}";
public string LoadTemplate(string subject, string body, string imgSrc)
{
try
{
var sb = new StringBuilder(File.ReadAllText(TemplateLocation));
sb.Replace(SubjectKey, subject);
sb.Replace(BodyKey, body);
sb.Replace(ImgSrc, imgSrc);
sb.Replace(DateKey, DateTime.Now.ToString("f"));
return sb.ToString();
}
catch (Exception e)
{
return string.Empty;
}
}
}
}

@ -0,0 +1,8 @@
namespace Ombi.Notifications.Templates
{
public interface IEmailBasicTemplate
{
string LoadTemplate(string subject, string body, string imgSrc);
string TemplateLocation { get; }
}
}

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

@ -0,0 +1,189 @@
<!doctype html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Ombi</title>
<style media="all" type="text/css">
@media all {
.btn-primary table td:hover {
background-color: #34495e !important;
}
.btn-primary a:hover {
background-color: #34495e !important;
border-color: #34495e !important;
}
}
@media all {
.btn-secondary a:hover {
border-color: #34495e !important;
color: #34495e !important;
}
}
@media only screen and (max-width: 620px) {
table[class=body] h1 {
font-size: 28px !important;
margin-bottom: 10px !important;
}
table[class=body] h2 {
font-size: 22px !important;
margin-bottom: 10px !important;
}
table[class=body] h3 {
font-size: 16px !important;
margin-bottom: 10px !important;
}
table[class=body] p,
table[class=body] ul,
table[class=body] ol,
table[class=body] td,
table[class=body] span,
table[class=body] a {
font-size: 16px !important;
}
table[class=body] .wrapper,
table[class=body] .article {
padding: 10px !important;
}
table[class=body] .content {
padding: 0 !important;
}
table[class=body] .container {
padding: 0 !important;
width: 100% !important;
}
table[class=body] .header {
margin-bottom: 10px !important;
}
table[class=body] .main {
border-left-width: 0 !important;
border-radius: 0 !important;
border-right-width: 0 !important;
}
table[class=body] .btn table {
width: 100% !important;
}
table[class=body] .btn a {
width: 100% !important;
}
table[class=body] .img-responsive {
height: auto !important;
max-width: 100% !important;
width: auto !important;
}
table[class=body] .alert td {
border-radius: 0 !important;
padding: 10px !important;
}
table[class=body] .span-2,
table[class=body] .span-3 {
max-width: none !important;
width: 100% !important;
}
table[class=body] .receipt {
width: 100% !important;
}
}
@media all {
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
.apple-link a {
color: inherit !important;
font-family: inherit !important;
font-size: inherit !important;
font-weight: inherit !important;
line-height: inherit !important;
text-decoration: none !important;
}
}
</style>
</head>
<body class="" style="font-family: sans-serif; -webkit-font-smoothing: antialiased; font-size: 14px; line-height: 1.4; -ms-text-size-adjust: 100%; -webkit-text-size-adjust: 100%; background-color: #f6f6f6; margin: 0; padding: 0;">
<table border="0" cellpadding="0" cellspacing="0" class="body" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background-color: #f6f6f6;" width="100%" bgcolor="#f6f6f6">
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
<td class="container" style="font-family: sans-serif; font-size: 14px; vertical-align: top; display: block; Margin: 0 auto !important; max-width: 580px; padding: 10px; width: 580px;" width="580" valign="top">
<div class="content" style="box-sizing: border-box; display: block; Margin: 0 auto; max-width: 580px; padding: 10px;">
<!-- START CENTERED WHITE CONTAINER -->
<span class="preheader" style="color: transparent; display: none; height: 0; max-height: 0; max-width: 0; opacity: 0; overflow: hidden; mso-hide: all; visibility: hidden; width: 0;">Ombi</span>
<table class="main" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; background: #fff; border-radius: 3px;" width="100%">
<!-- START MAIN CONTENT AREA -->
<tr>
<td class="wrapper" style="font-family: sans-serif; font-size: 14px; vertical-align: top; box-sizing: border-box; padding: 20px;" valign="top">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td align="center">
<img src="http://i.imgur.com/qQsN78U.png" width="400px" text-align="center" />
</td>
</tr>
<tr>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">Hi there!</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">{@SUBJECT}</p>
<p style="font-family: sans-serif; font-size: 14px; font-weight: normal; margin: 0; Margin-bottom: 15px;">{@BODY}</p>
</td>
</tr>
<tr>
<td align="center">
<img src="{@IMGSRC}" width="400px" text-align="center" />
</td>
</tr>
</table>
</td>
</tr>
<!-- END MAIN CONTENT AREA -->
</table>
<!-- START FOOTER -->
<div class="footer" style="clear: both; padding-top: 10px; text-align: center; width: 100%;">
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%;" width="100%">
<tr>
<td class="content-block powered-by" style="font-family: sans-serif; vertical-align: top; padding-top: 10px; padding-bottom: 10px; font-size: 12px; color: #999999; text-align: center;" valign="top" align="center">
Powered by <a href="https://github.com/tidusjar/Ombi" style="color: #999999; font-size: 12px; text-align: center; text-decoration: underline;">Ombi</a>
</td>
</tr>
</table>
</div>
<!-- END FOOTER -->
<!-- END CENTERED WHITE CONTAINER -->
</div>
</td>
<td style="font-family: sans-serif; font-size: 14px; vertical-align: top;" valign="top">&nbsp;</td>
</tr>
</table>
</body>
</html>

@ -0,0 +1,91 @@
using System;
using System.Threading.Tasks;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models;
using Ombi.Notifications.Models;
namespace Ombi.Notifications
{
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
{
protected BaseNotification(ISettingsService<T> settings)
{
Settings = settings;
}
protected ISettingsService<T> Settings { get; }
public abstract string NotificationName { get; }
public async Task NotifyAsync(NotificationModel model)
{
var configuration = GetConfiguration();
await NotifyAsync(model, configuration);
}
public async Task NotifyAsync(NotificationModel model, Settings.Settings.Models.Settings settings)
{
if (settings == null) await NotifyAsync(model);
var notificationSettings = (T)settings;
if (!ValidateConfiguration(notificationSettings))
{
return;
}
try
{
switch (model.NotificationType)
{
case NotificationType.NewRequest:
await NewRequest(model, notificationSettings);
break;
case NotificationType.Issue:
await Issue(model, notificationSettings);
break;
case NotificationType.RequestAvailable:
await AvailableRequest(model, notificationSettings);
break;
case NotificationType.RequestApproved:
await RequestApproved(model, notificationSettings);
break;
case NotificationType.AdminNote:
throw new NotImplementedException();
case NotificationType.Test:
await Test(model, notificationSettings);
break;
case NotificationType.RequestDeclined:
await RequestDeclined(model, notificationSettings);
break;
case NotificationType.ItemAddedToFaultQueue:
await AddedToRequestQueue(model, notificationSettings);
break;
default:
throw new ArgumentOutOfRangeException();
}
}
catch (NotImplementedException)
{
// Do nothing, it's not implimented meaning it might not be ready or even used
}
}
private T GetConfiguration()
{
var settings = Settings.GetSettings();
return settings;
}
protected abstract bool ValidateConfiguration(T settings);
protected abstract Task NewRequest(NotificationModel model, T settings);
protected abstract Task Issue(NotificationModel model, T settings);
protected abstract Task AddedToRequestQueue(NotificationModel model, T settings);
protected abstract Task RequestDeclined(NotificationModel model, T settings);
protected abstract Task RequestApproved(NotificationModel model, T settings);
protected abstract Task AvailableRequest(NotificationModel model, T settings);
protected abstract Task Send(NotificationMessage model, T settings);
protected abstract Task Test(NotificationModel model, T settings);
}
}

@ -0,0 +1,21 @@
using System.Threading.Tasks;
using Ombi.Core.Settings.Models;
using Ombi.Notifications.Models;
namespace Ombi.Notifications
{
public interface INotification
{
string NotificationName { get; }
Task NotifyAsync(NotificationModel model);
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
Task NotifyAsync(NotificationModel model, Settings.Settings.Models.Settings settings);
}
}

@ -0,0 +1,18 @@
using System.Collections.Concurrent;
using System.Threading.Tasks;
using Ombi.Core.Settings.Models;
using Ombi.Notifications.Models;
namespace Ombi.Notifications
{
public interface INotificationService
{
ConcurrentDictionary<string, INotification> Observers { get; }
Task Publish(NotificationModel model);
Task Publish(NotificationModel model, Settings.Settings.Models.Settings settings);
Task PublishTest(NotificationModel model, Settings.Settings.Models.Settings settings, INotification type);
void Subscribe(INotification notification);
void UnSubscribe(INotification notification);
}
}

@ -0,0 +1,13 @@
using System.Collections.Generic;
namespace Ombi.Notifications.Models
{
public class NotificationMessage
{
public string Subject { get; set; }
public string Message { get; set; }
public string To { get; set; }
public Dictionary<string, string> Other { get; set; } = new Dictionary<string, string>();
}
}

@ -0,0 +1,17 @@
using System;
using Ombi.Store.Entities;
namespace Ombi.Notifications.Models
{
public class NotificationModel
{
public string Title { get; set; }
public string Body { get; set; }
public DateTime DateTime { get; set; }
public NotificationType NotificationType { get; set; }
public string User { get; set; }
public string UserEmail { get; set; }
public RequestType RequestType { get; set; }
public string ImgSrc { get; set; }
}
}

@ -0,0 +1,78 @@
using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Core.Settings.Models;
using Ombi.Notifications.Models;
namespace Ombi.Notifications
{
public class NotificationService : INotificationService
{
public ConcurrentDictionary<string, INotification> Observers { get; } = new ConcurrentDictionary<string, INotification>();
/// <summary>
/// Sends a notification to the user. This one is used in normal notification scenarios
/// </summary>
/// <param name="model">The model.</param>
/// <returns></returns>
public async Task Publish(NotificationModel model)
{
var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model));
await Task.WhenAll(notificationTasks).ConfigureAwait(false);
}
/// <summary>
/// Sends a notification to the user, this is usually for testing the settings.
/// </summary>
/// <param name="model">The model.</param>
/// <param name="settings">The settings.</param>
/// <returns></returns>
public async Task Publish(NotificationModel model, Settings.Settings.Models.Settings settings)
{
var notificationTasks = Observers.Values.Select(notification => NotifyAsync(notification, model, settings));
await Task.WhenAll(notificationTasks).ConfigureAwait(false);
}
public void Subscribe(INotification notification)
{
Observers.TryAdd(notification.NotificationName, notification);
}
public void UnSubscribe(INotification notification)
{
Observers.TryRemove(notification.NotificationName, out notification);
}
private async Task NotifyAsync(INotification notification, NotificationModel model)
{
try
{
await notification.NotifyAsync(model).ConfigureAwait(false);
}
catch (Exception ex)
{
}
}
private async Task NotifyAsync(INotification notification, NotificationModel model, Settings.Settings.Models.Settings settings)
{
try
{
await notification.NotifyAsync(model, settings).ConfigureAwait(false);
}
catch (Exception ex)
{
throw new InvalidOperationException(ex.Message);
}
}
public async Task PublishTest(NotificationModel model, Settings.Settings.Models.Settings settings, INotification type)
{
await type.NotifyAsync(model, settings);
}
}
}

@ -0,0 +1,16 @@
using System;
namespace Ombi.Notifications
{
public enum NotificationType
{
NewRequest,
Issue,
RequestAvailable,
RequestApproved,
AdminNote,
Test,
RequestDeclined,
ItemAddedToFaultQueue
}
}

@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,7 @@
namespace Ombi.Schedule
{
public interface IJobSetup
{
void Setup();
}
}

@ -1,11 +0,0 @@
using Hangfire.RecurringJobExtensions;
using Hangfire.Server;
namespace Ombi.Schedule
{
public interface ITestJob
{
[RecurringJob("*/1 * * * *")]
void Test(PerformContext context);
}
}

@ -0,0 +1,20 @@
using System;
using Hangfire;
using Ombi.Schedule.Jobs;
namespace Ombi.Schedule
{
public class JobSetup : IJobSetup
{
public JobSetup(IPlexContentCacher cacher)
{
Cacher = cacher;
}
private IPlexContentCacher Cacher { get; }
public void Setup()
{
RecurringJob.AddOrUpdate(() => Cacher.CacheContent(), Cron.Hourly, TimeZoneInfo.Utc, "Cacher");
}
}
}

@ -0,0 +1,7 @@
namespace Ombi.Schedule.Jobs
{
public interface IPlexContentCacher
{
void CacheContent();
}
}

@ -32,11 +32,10 @@ using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
namespace Ombi.Schedule.Jobs
{
public partial class PlexContentCacher
public partial class PlexContentCacher : IPlexContentCacher
{
public PlexContentCacher(ISettingsService<PlexSettings> plex, IPlexApi plexApi)
{
@ -132,7 +131,7 @@ namespace Ombi.Schedule.Jobs
{
if (plex.Enable)
{
if (plex?.Ip == null || plex?.PlexAuthToken == null)
if (string.IsNullOrEmpty(plex?.Ip) || string.IsNullOrEmpty(plex?.PlexAuthToken))
{
return false;
}

@ -14,6 +14,7 @@
<ItemGroup>
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
</ItemGroup>
</Project>

@ -1,17 +0,0 @@
using System;
using System.Diagnostics;
using Hangfire;
using Hangfire.RecurringJobExtensions;
using Hangfire.Server;
namespace Ombi.Schedule
{
public class TestJob : ITestJob
{
[RecurringJob("*/1 * * * *")]
public void Test(PerformContext context)
{
Debug.WriteLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss} TestJob1 Running ...");
}
}
}

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
</ItemGroup>
</Project>

@ -4,7 +4,7 @@ using Ombi.Helpers;
namespace Ombi.Core.Settings.Models.External
{
public abstract class ExternalSettings : Settings
public abstract class ExternalSettings : Ombi.Settings.Settings.Models.Settings
{
public bool Ssl { get; set; }
public string SubDir { get; set; }

@ -3,7 +3,7 @@ using Newtonsoft.Json;
namespace Ombi.Core.Settings.Models
{
public class LandingPageSettings : Settings
public class LandingPageSettings : Ombi.Settings.Settings.Models.Settings
{
public bool Enabled { get; set; }
public bool BeforeLogin { get; set; }

@ -0,0 +1,14 @@
namespace Ombi.Core.Settings.Models.Notifications
{
public sealed class EmailNotificationSettings : Ombi.Settings.Settings.Models.Settings
{
public bool Enabled { get; set; }
public string EmailHost { get; set; }
public string EmailPassword { get; set; }
public int EmailPort { get; set; }
public string EmailSender { get; set; }
public string EmailUsername { get; set; }
public bool Authentication { get; set; }
public string RecipientEmail { get; set; }
}
}

@ -1,6 +1,6 @@
namespace Ombi.Core.Settings.Models
{
public class OmbiSettings : Settings
public class OmbiSettings : Ombi.Settings.Settings.Models.Settings
{
public int Port { get; set; }
//public string BaseUrl { get; set; }

@ -1,4 +1,4 @@
namespace Ombi.Core.Settings.Models
namespace Ombi.Settings.Settings.Models
{
public class Settings
{

@ -1,13 +1,14 @@
using System.Threading.Tasks;
using Newtonsoft.Json;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
namespace Ombi.Core.Settings
namespace Ombi.Settings.Settings
{
public class SettingsServiceV2<T> : ISettingsService<T>
where T : Models.Settings, new()
where T : Ombi.Settings.Settings.Models.Settings, new()
{
public SettingsServiceV2(ISettingsRepository repo)

@ -2,6 +2,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Ombi.Store.Entities;
namespace Ombi.Store.Context
@ -13,5 +14,6 @@ namespace Ombi.Store.Context
DbSet<RequestBlobs> Requests { get; set; }
DbSet<GlobalSettings> Settings { get; set; }
DbSet<User> Users { get; set; }
EntityEntry<GlobalSettings> Entry(GlobalSettings settings);
}
}

@ -1,4 +1,5 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Ombi.Store.Entities;
namespace Ombi.Store.Context
@ -13,10 +14,16 @@ namespace Ombi.Store.Context
_created = true;
Database.EnsureCreated();
Database.Migrate();
}
public DbSet<RequestBlobs> Requests { get; set; }
public DbSet<GlobalSettings> Settings { get; set; }
public DbSet<User> Users { get; set; }
public EntityEntry<GlobalSettings> Entry(GlobalSettings settings)
{
return Entry(settings);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{

@ -76,6 +76,7 @@ namespace Ombi.Store.Repository
public void Update(GlobalSettings entity)
{
Db.Entry(entity).State = EntityState.Modified;
Db.SaveChanges();
}
}

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
<PackageReference Include="Moq" Version="4.7.8" />
<PackageReference Include="xunit" Version="2.2.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
</ItemGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
</Project>

@ -0,0 +1,32 @@
using System;
using System.Threading.Tasks;
using AutoMapper;
using Moq;
using Ombi.Core.IdentityResolver;
using Ombi.Core.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Xunit;
namespace Ombi.Tests.Core
{
public class UserIdentityManagerTests
{
public UserIdentityManagerTests()
{
UserRepo = new Mock<IUserRepository>();
var mapper = new Mock<IMapper>();
Manager = new UserIdentityManager(UserRepo.Object, mapper.Object);
}
private Mock<IUserRepository> UserRepo { get; }
private IUserIdentityManager Manager { get; }
[Fact]
public async Task CredentialsValid()
{
UserRepo.Setup(x => x.GetUser("ABC")).ReturnsAsync(() => new User{Password = "4tDKIbNCZ0pMxNzSSjVbT6mG88o52x9jOixPEwQS9rg=", Salt = new byte[]{30,80,214,127,185,134,75,86,80,177,0,242,202,161,219,246}});
Assert.True(await Manager.CredentialsValid("ABC", "ABC"));
}
}
}

@ -44,6 +44,18 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{6F42AB98
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.TvMaze", "Ombi.Api.TvMaze\Ombi.Api.TvMaze.csproj", "{0E8EF835-E4F0-4EE5-A2B6-678DEE973721}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Notifications", "Ombi.Notifications\Ombi.Notifications.csproj", "{E6EE2830-E4AC-4F2E-AD93-2C9305605761}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Notifications", "Notifications", "{EA30DD15-6280-4687-B370-2956EC2E54E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Notifications.Email", "Ombi.Notifications.Email\Ombi.Notifications.Email.csproj", "{72DB97D7-2D60-4B96-8C57-6C0E20E892EB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Notifications.Templates", "Ombi.Notifications.Templates\Ombi.Notifications.Templates.csproj", "{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Tests.Core", "Ombi.Tests.Core\Ombi.Tests.Core.csproj", "{627A27A7-8879-4851-8140-38F8F5ADD6CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Settings", "Ombi.Settings\Ombi.Settings.csproj", "{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -102,6 +114,26 @@ Global
{0E8EF835-E4F0-4EE5-A2B6-678DEE973721}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0E8EF835-E4F0-4EE5-A2B6-678DEE973721}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0E8EF835-E4F0-4EE5-A2B6-678DEE973721}.Release|Any CPU.Build.0 = Release|Any CPU
{E6EE2830-E4AC-4F2E-AD93-2C9305605761}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E6EE2830-E4AC-4F2E-AD93-2C9305605761}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E6EE2830-E4AC-4F2E-AD93-2C9305605761}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E6EE2830-E4AC-4F2E-AD93-2C9305605761}.Release|Any CPU.Build.0 = Release|Any CPU
{72DB97D7-2D60-4B96-8C57-6C0E20E892EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72DB97D7-2D60-4B96-8C57-6C0E20E892EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72DB97D7-2D60-4B96-8C57-6C0E20E892EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{72DB97D7-2D60-4B96-8C57-6C0E20E892EB}.Release|Any CPU.Build.0 = Release|Any CPU
{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6EE01B17-0966-4E11-8BC1-A5318A92AB1D}.Release|Any CPU.Build.0 = Release|Any CPU
{627A27A7-8879-4851-8140-38F8F5ADD6CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{627A27A7-8879-4851-8140-38F8F5ADD6CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{627A27A7-8879-4851-8140-38F8F5ADD6CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{627A27A7-8879-4851-8140-38F8F5ADD6CD}.Release|Any CPU.Build.0 = Release|Any CPU
{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AE3AA23D-5B66-42AF-B44E-B9B4D8856C6F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -115,5 +147,9 @@ Global
{08FF107D-31E1-470D-AF86-E09B015CEE06} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{CFB5E008-D0D0-43C0-AA06-89E49D17F384} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{0E8EF835-E4F0-4EE5-A2B6-678DEE973721} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{E6EE2830-E4AC-4F2E-AD93-2C9305605761} = {EA30DD15-6280-4687-B370-2956EC2E54E5}
{72DB97D7-2D60-4B96-8C57-6C0E20E892EB} = {EA30DD15-6280-4687-B370-2956EC2E54E5}
{6EE01B17-0966-4E11-8BC1-A5318A92AB1D} = {EA30DD15-6280-4687-B370-2956EC2E54E5}
{627A27A7-8879-4851-8140-38F8F5ADD6CD} = {6F42AB98-9196-44C4-B888-D5E409F415A1}
EndGlobalSection
EndGlobal

@ -56,6 +56,7 @@ namespace Ombi.Controllers
}
[HttpGet("landingpage")]
[AllowAnonymous]
public async Task<LandingPageSettings> LandingPageSettings()
{
return await Get<LandingPageSettings>();

@ -42,6 +42,7 @@
<ProjectReference Include="..\Ombi.DependencyInjection\Ombi.DependencyInjection.csproj" />
<ProjectReference Include="..\Ombi.Mapping\Ombi.Mapping.csproj" />
<ProjectReference Include="..\Ombi.Schedule\Ombi.Schedule.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
</ItemGroup>
@ -57,6 +58,9 @@
</ItemGroup>
<ItemGroup>
<Content Update="wwwroot\app\landingpage\landingpage.component.html">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="wwwroot\app\services\request - Copy.service.js.map">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>

@ -47,17 +47,15 @@ namespace Ombi
services.RegisterDependencies(); // Ioc and EF
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
//services.AddTransient<IPrincipal>(new InjectionFactory(u => HttpContext.Current.User));
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
services.AddHangfire(x =>
{
x.UseMemoryStorage(new MemoryStorageOptions());
//using RecurringJobAttribute to build RecurringJob automatically.
x.UseRecurringJob(typeof(ITestJob));
//x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
@ -79,6 +77,11 @@ namespace Ombi
app.UseHangfireServer();
app.UseHangfireDashboard();
// Setup the scheduler
var jobSetup = (IJobSetup)app.ApplicationServices.GetService(typeof(IJobSetup));
jobSetup.Setup();
ConfigureAuth(app);
var provider = new FileExtensionContentTypeProvider();

@ -14,6 +14,7 @@ import { SearchComponent } from './search/search.component';
import { MovieSearchComponent } from './search/moviesearch.component';
import { RequestComponent } from './requests/request.component';
import { LoginComponent } from './login/login.component';
import { LandingPageComponent } from './landingpage/landingpage.component';
import { PageNotFoundComponent } from './errors/not-found.component';
// Services
@ -42,6 +43,7 @@ const routes: Routes = [
{ path: 'search', component: SearchComponent, canActivate: [AuthGuard] },
{ path: 'requests', component: RequestComponent, canActivate: [AuthGuard] },
{ path: 'login', component: LoginComponent },
{ path: 'landingpage', component: LandingPageComponent },
];
@NgModule({
@ -66,7 +68,8 @@ const routes: Routes = [
SearchComponent,
RequestComponent,
LoginComponent,
MovieSearchComponent
MovieSearchComponent,
LandingPageComponent
],
providers: [
SearchService,

@ -42,6 +42,7 @@ export interface ILandingPageSettings extends ISettings {
enabled: boolean,
beforeLogin: boolean,
afterLogin: boolean,
noticeEnabled: boolean,
noticeText: string,
noticeBackgroundColor: string,
timeLimit: boolean,

@ -0,0 +1,5 @@
.landing-box {
height: 150px;
background: #333333 !important;
border-radius: 2%
}

@ -0,0 +1,26 @@
<div *ngIf="landingPageSettings">
<h1>Hey! Welcome back to {{websiteName}}</h1>
<h3 *ngIf="settings.noticeEnabled" style="background-color: {{settings.noticeBackgroundColor}}">{{settings.noticeText}}</h3>
<div class="col-md-3 landing-box">
<div>
Request Something
</div>
</div>
<div class="col-md-3 col-md-offset-1 landing-box">
<div>
View all your requests
</div>
</div>
<div class="col-md-3 col-md-offset-1 landing-box">
<div>
Report an issue
</div>
</div>
</div>

@ -0,0 +1,27 @@
import { Component, OnInit } from '@angular/core';
import { SettingsService } from '../services/settings.service';
import { ILandingPageSettings } from '../interfaces/ISettings';
@Component({
selector: 'ombi',
moduleId: module.id,
templateUrl: './landingpage.component.html',
styleUrls: ['./landingpage.component.css']
})
export class LandingPageComponent implements OnInit {
constructor(private settingsService: SettingsService) { }
websiteName: string;
landingPageSettings: ILandingPageSettings;
ngOnInit(): void {
this.settingsService.getLandingPage().subscribe(x => {
this.landingPageSettings = x;
console.log(x);
});
this.websiteName = "Ombi";
}
}

@ -1,5 +1,6 @@
import { Injectable } from '@angular/core';
import { AuthHttp } from 'angular2-jwt';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { ServiceAuthHelpers } from './service.helpers';
@ -7,47 +8,49 @@ import { IOmbiSettings, IEmbySettings, IPlexSettings, ISonarrSettings,ILandingPa
@Injectable()
export class SettingsService extends ServiceAuthHelpers {
constructor(http: AuthHttp) {
super(http, '/api/v1/Settings/');
constructor(public httpAuth: AuthHttp, private nonAuthHttp: Http) {
super(httpAuth, '/api/v1/Settings/');
}
getOmbi(): Observable<IOmbiSettings> {
return this.http.get(`${this.url}/Ombi/`).map(this.extractData);
return this.httpAuth.get(`${this.url}/Ombi/`).map(this.extractData);
}
saveOmbi(settings: IOmbiSettings): Observable<boolean> {
return this.http.post(`${this.url}/Ombi/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
return this.httpAuth.post(`${this.url}/Ombi/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
getEmby(): Observable<IEmbySettings> {
return this.http.get(`${this.url}/Emby/`).map(this.extractData);
return this.httpAuth.get(`${this.url}/Emby/`).map(this.extractData);
}
saveEmby(settings: IEmbySettings): Observable<boolean> {
return this.http.post(`${this.url}/Emby/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
return this.httpAuth.post(`${this.url}/Emby/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
getPlex(): Observable<IPlexSettings> {
return this.http.get(`${this.url}/Plex/`).map(this.extractData);
return this.httpAuth.get(`${this.url}/Plex/`).map(this.extractData);
}
savePlex(settings: IPlexSettings): Observable<boolean> {
return this.http.post(`${this.url}/Plex/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
return this.httpAuth.post(`${this.url}/Plex/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
getSonarr(): Observable<ISonarrSettings> {
return this.http.get(`${this.url}/Sonarr`).map(this.extractData);
return this.httpAuth.get(`${this.url}/Sonarr`).map(this.extractData);
}
saveSonarr(settings: ISonarrSettings): Observable<boolean> {
return this.http.post(`${this.url}/Sonarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
return this.httpAuth.post(`${this.url}/Sonarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
// Using http since we need it not to be authenticated to get the landing page settings
getLandingPage(): Observable<ILandingPageSettings> {
return this.http.get(`${this.url}/LandingPage`).map(this.extractData);
return this.nonAuthHttp.get(`${this.url}/LandingPage`).map(this.extractData);
}
saveLandingPage(settings: ILandingPageSettings): Observable<boolean> {
return this.http.post(`${this.url}/LandingPage`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
return this.httpAuth.post(`${this.url}/LandingPage`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
}
}

@ -1,11 +1,11 @@
<div class="col-sm-8 col-sm-push-1">
<div class="col-sm-8 col-sm-push-1" *ngIf="settings">
<fieldset>
<legend>Landing Page Configuration</legend>
<div class="form-group">
<div class="checkbox">
<input type="checkbox" id="enable" name="enable" [(ngModel)]="settings.enable" ng-checked="settings.enable">
<input type="checkbox" id="enable" name="enable" [(ngModel)]="settings.enabled" ng-checked="settings.enabled">
<label for="enable">Enable</label>
</div>
</div>

@ -14,12 +14,12 @@ before_build:
- appveyor-retry dotnet restore
- appveyor-retry npm install bower -g
- appveyor-retry npm install -g gulp
#- appveyor-retry npm install -g typescript
- appveyor-retry npm install
- appveyor-retry bower install
- gulp publish
build_script:
- dotnet build
- dotnet xunit
after_build:
- dotnet publish -c Release -r win10-x64
- dotnet publish -c Release -r osx.10.12-x64

Loading…
Cancel
Save