More work on Wizard and Plex API #865

pull/1389/head
tidusjar 8 years ago
parent dd5e1c5232
commit d2915df36e

@ -0,0 +1,14 @@
using System.Threading.Tasks;
using Ombi.Api.Plex.Models;
using Ombi.Api.Plex.Models.Server;
using Ombi.Api.Plex.Models.Status;
namespace Ombi.Api.Plex
{
public interface IPlexApi
{
Task<PlexStatus> GetStatus(string authToken, string uri);
Task<PlexAuthentication> SignIn(UserRequest user);
Task<PlexServer> GetServer(string authToken);
}
}

@ -0,0 +1,10 @@
using System;
using System.Text;
namespace Ombi.Api.Plex.Models
{
public class PlexAuthentication
{
public User user { get; set; }
}
}

@ -0,0 +1,33 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexUserRequest.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
namespace Ombi.Api.Plex.Models
{
public class PlexUserRequest
{
public UserRequest user { get; set; }
}
}

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Ombi.Api.Plex.Models
{
public class Roles
{
public List<object> roles { get; set; }
}
}

@ -0,0 +1,47 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexServer.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System.Collections.Generic;
using System.Xml.Serialization;
namespace Ombi.Api.Plex.Models.Server
{
[XmlRoot(ElementName = "MediaContainer")]
public class PlexServer
{
[XmlElement(ElementName = "Server")]
public List<ServerInfo> Server { get; set; }
[XmlAttribute(AttributeName = "friendlyName")]
public string FriendlyName { get; set; }
[XmlAttribute(AttributeName = "identifier")]
public string Identifier { get; set; }
[XmlAttribute(AttributeName = "machineIdentifier")]
public string MachineIdentifier { get; set; }
[XmlAttribute(AttributeName = "size")]
public string Size { get; set; }
}
}

@ -0,0 +1,41 @@
using System.Xml.Serialization;
namespace Ombi.Api.Plex.Models.Server
{
[XmlRoot(ElementName = "Server")]
public class ServerInfo
{
[XmlAttribute(AttributeName = "accessToken")]
public string AccessToken { get; set; }
[XmlAttribute(AttributeName = "name")]
public string Name { get; set; }
[XmlAttribute(AttributeName = "address")]
public string Address { get; set; }
[XmlAttribute(AttributeName = "port")]
public string Port { get; set; }
[XmlAttribute(AttributeName = "version")]
public string Version { get; set; }
[XmlAttribute(AttributeName = "scheme")]
public string Scheme { get; set; }
[XmlAttribute(AttributeName = "host")]
public string Host { get; set; }
[XmlAttribute(AttributeName = "localAddresses")]
public string LocalAddresses { get; set; }
[XmlAttribute(AttributeName = "machineIdentifier")]
public string MachineIdentifier { get; set; }
[XmlAttribute(AttributeName = "createdAt")]
public string CreatedAt { get; set; }
[XmlAttribute(AttributeName = "updatedAt")]
public string UpdatedAt { get; set; }
[XmlAttribute(AttributeName = "owned")]
public string Owned { get; set; }
[XmlAttribute(AttributeName = "synced")]
public string Synced { get; set; }
[XmlAttribute(AttributeName = "sourceTitle")]
public string SourceTitle { get; set; }
[XmlAttribute(AttributeName = "ownerId")]
public string OwnerId { get; set; }
[XmlAttribute(AttributeName = "home")]
public string Home { get; set; }
}
}

@ -0,0 +1,9 @@
namespace Ombi.Api.Plex.Models.Status
{
public class Directory
{
public int count { get; set; }
public string key { get; set; }
public string title { get; set; }
}
}

@ -0,0 +1,51 @@
namespace Ombi.Api.Plex.Models.Status
{
public class Mediacontainer
{
public int size { get; set; }
public bool allowCameraUpload { get; set; }
public bool allowChannelAccess { get; set; }
public bool allowMediaDeletion { get; set; }
public bool allowSharing { get; set; }
public bool allowSync { get; set; }
public bool backgroundProcessing { get; set; }
public bool certificate { get; set; }
public bool companionProxy { get; set; }
public string countryCode { get; set; }
public string diagnostics { get; set; }
public bool eventStream { get; set; }
public string friendlyName { get; set; }
public bool hubSearch { get; set; }
public bool itemClusters { get; set; }
public string machineIdentifier { get; set; }
public bool mediaProviders { get; set; }
public bool multiuser { get; set; }
public bool myPlex { get; set; }
public string myPlexMappingState { get; set; }
public string myPlexSigninState { get; set; }
public bool myPlexSubscription { get; set; }
public string myPlexUsername { get; set; }
public bool photoAutoTag { get; set; }
public string platform { get; set; }
public string platformVersion { get; set; }
public bool pluginHost { get; set; }
public bool readOnlyLibraries { get; set; }
public bool requestParametersInCookie { get; set; }
public int streamingBrainVersion { get; set; }
public bool sync { get; set; }
public int transcoderActiveVideoSessions { get; set; }
public bool transcoderAudio { get; set; }
public bool transcoderLyrics { get; set; }
public bool transcoderPhoto { get; set; }
public bool transcoderSubtitles { get; set; }
public bool transcoderVideo { get; set; }
public string transcoderVideoBitrates { get; set; }
public string transcoderVideoQualities { get; set; }
public string transcoderVideoResolutions { get; set; }
public int updatedAt { get; set; }
public bool updater { get; set; }
public string version { get; set; }
public bool voiceSearch { get; set; }
public Directory[] Directory { get; set; }
}
}

@ -0,0 +1,34 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2017 Jamie Rees
// File: PlexStatus.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
namespace Ombi.Api.Plex.Models.Status
{
public class PlexStatus
{
public Mediacontainer MediaContainer { get; set; }
}
}

@ -0,0 +1,10 @@
namespace Ombi.Api.Plex.Models
{
public class Subscription
{
public bool active { get; set; }
public string status { get; set; }
public object plan { get; set; }
public object features { get; set; }
}
}

@ -0,0 +1,19 @@
using System.Collections.Generic;
namespace Ombi.Api.Plex.Models
{
public class User
{
public string email { get; set; }
public string uuid { get; set; }
public string joined_at { get; set; }
public string username { get; set; }
public string title { get; set; }
public string authentication_token { get; set; }
public Subscription subscription { get; set; }
public Roles roles { get; set; }
public List<string> entitlements { get; set; }
public object confirmed_at { get; set; }
public int forum_id { get; set; }
}
}

@ -0,0 +1,8 @@
namespace Ombi.Api.Plex.Models
{
public class UserRequest
{
public string login { get; set; }
public string password { get; set; }
}
}

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,88 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Ombi.Api.Plex.Models;
using Ombi.Api.Plex.Models.Server;
using Ombi.Api.Plex.Models.Status;
namespace Ombi.Api.Plex
{
public class PlexApi : IPlexApi
{
public PlexApi()
{
Api = new Api();
}
private Api Api { get; }
private const string SignInUri = "https://plex.tv/users/sign_in.json";
private const string FriendsUri = "https://plex.tv/pms/friends/all";
private const string GetAccountUri = "https://plex.tv/users/account";
private const string ServerUri = "https://plex.tv/pms/servers.xml";
/// <summary>
/// Sign into the Plex API
/// This is for authenticating users credentials with Plex
/// <para>NOTE: Plex "Managed" users do not work</para>
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <returns></returns>
public async Task<PlexAuthentication> SignIn(UserRequest user)
{
var userModel = new PlexUserRequest
{
user = user
};
var request = new Request(SignInUri, string.Empty, HttpMethod.Post);
AddHeaders(request);
request.AddJsonBody(userModel);
var obj = await Api.Request<PlexAuthentication>(request);
return obj;
}
public async Task<PlexStatus> GetStatus(string authToken, string uri)
{
var request = new Request(uri, string.Empty, HttpMethod.Get);
AddHeaders(request, authToken);
return await Api.Request<PlexStatus>(request);
}
public async Task<PlexServer> GetServer(string authToken)
{
var request = new Request(ServerUri, string.Empty, HttpMethod.Get, ContentType.Xml);
AddHeaders(request, authToken);
return await Api.Request<PlexServer>(request);
}
/// <summary>
/// Adds the required headers and also the authorization header
/// </summary>
/// <param name="request"></param>
/// <param name="authToken"></param>
private void AddHeaders(Request request, string authToken)
{
request.AddHeader("X-Plex-Token", authToken);
AddHeaders(request);
}
/// <summary>
/// Adds the main required headers to the Plex Request
/// </summary>
/// <param name="request"></param>
private void AddHeaders(Request request)
{
request.AddHeader("X-Plex-Client-Identifier", $"OmbiV3");
request.AddHeader("X-Plex-Product", "Ombi");
request.AddHeader("X-Plex-Version", "3");
request.AddContentHeader("Content-Type", "application/json" );
request.AddHeader("Accept","application/json");
}
}
}

@ -1,6 +1,8 @@
using System; using System;
using System.IO;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Xml.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
namespace Ombi.Api namespace Ombi.Api
@ -41,6 +43,7 @@ namespace Ombi.Api
foreach (var header in request.Headers) foreach (var header in request.Headers)
{ {
httpRequestMessage.Headers.Add(header.Key, header.Value); httpRequestMessage.Headers.Add(header.Key, header.Value);
} }
using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage)) using (var httpResponseMessage = await httpClient.SendAsync(httpRequestMessage))
{ {
@ -53,10 +56,23 @@ namespace Ombi.Api
var receivedString = await data.ReadAsStringAsync(); var receivedString = await data.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(receivedString, Settings); if (request.ContentType == ContentType.Json)
{
return JsonConvert.DeserializeObject<T>(receivedString, Settings);
}
else
{
// XML
XmlSerializer serializer = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(receivedString);
var value = (T)serializer.Deserialize(reader);
return value;
}
} }
} }
} }
} }
} }
} }

@ -0,0 +1,8 @@
namespace Ombi.Api
{
public enum ContentType
{
Json,
Xml
}
}

@ -7,6 +7,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -9,13 +9,15 @@ namespace Ombi.Api
{ {
public class Request public class Request
{ {
public Request(string endpoint, string baseUrl, HttpMethod http) public Request(string endpoint, string baseUrl, HttpMethod http, ContentType contentType = ContentType.Json)
{ {
Endpoint = endpoint; Endpoint = endpoint;
BaseUrl = baseUrl; BaseUrl = baseUrl;
HttpMethod = http; HttpMethod = http;
ContentType = contentType;
} }
public ContentType ContentType { get; }
public string Endpoint { get; } public string Endpoint { get; }
public string BaseUrl { get; } public string BaseUrl { get; }
public HttpMethod HttpMethod { get; } public HttpMethod HttpMethod { get; }
@ -25,7 +27,10 @@ namespace Ombi.Api
get get
{ {
var sb = new StringBuilder(); var sb = new StringBuilder();
sb.Append(!BaseUrl.EndsWith("/") ? string.Format("{0}/", BaseUrl) : BaseUrl); if (!string.IsNullOrEmpty(BaseUrl))
{
sb.Append(!BaseUrl.EndsWith("/") ? string.Format("{0}/", BaseUrl) : BaseUrl);
}
sb.Append(Endpoint.StartsWith("/") ? Endpoint.Remove(0, 1) : Endpoint); sb.Append(Endpoint.StartsWith("/") ? Endpoint.Remove(0, 1) : Endpoint);
return sb.ToString(); return sb.ToString();
} }
@ -40,6 +45,7 @@ namespace Ombi.Api
} }
public List<KeyValuePair<string, string>> Headers { get; } = new List<KeyValuePair<string, string>>(); public List<KeyValuePair<string, string>> Headers { get; } = new List<KeyValuePair<string, string>>();
public List<KeyValuePair<string, string>> ContentHeaders { get; } = new List<KeyValuePair<string, string>>();
public object JsonBody { get; set; } public object JsonBody { get; set; }
@ -64,10 +70,15 @@ namespace Ombi.Api
{ {
Headers.Add(new KeyValuePair<string, string>(key, value)); Headers.Add(new KeyValuePair<string, string>(key, value));
} }
public void AddContentHeader(string key, string value)
{
ContentHeaders.Add(new KeyValuePair<string, string>(key, value));
}
public void AddJsonBody(object obj) public void AddJsonBody(object obj)
{ {
JsonBody = obj; JsonBody = obj;
} }
} }
} }

@ -17,7 +17,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" /> <ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" /> <ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" /> <ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Ombi.Api.Plex;
using Ombi.Core; using Ombi.Core;
using Ombi.Core.Engine; using Ombi.Core.Engine;
using Ombi.Core.IdentityResolver; using Ombi.Core.IdentityResolver;
@ -40,6 +41,7 @@ namespace Ombi.DependencyInjection
public static IServiceCollection RegisterApi(this IServiceCollection services) public static IServiceCollection RegisterApi(this IServiceCollection services)
{ {
services.AddTransient<IMovieDbApi, TheMovieDbApi.TheMovieDbApi>(); services.AddTransient<IMovieDbApi, TheMovieDbApi.TheMovieDbApi>();
services.AddTransient<IPlexApi, PlexApi>();
return services; return services;
} }

@ -6,19 +6,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" /> <ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Authorization">
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.aspnetcore.authorization\1.1.1\lib\netstandard1.3\Microsoft.AspNetCore.Authorization.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions">
<HintPath>..\..\..\..\..\.nuget\packages\microsoft.extensions.dependencyinjection.abstractions\1.1.0\lib\netstandard1.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
</ItemGroup>
</Project> </Project>

@ -7,15 +7,13 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="EasyCrypto" Version="3.3.2" /> <PackageReference Include="EasyCrypto" Version="3.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="10.0.2" />
<PackageReference Include="System.Security.Claims" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System.IdentityModel"> <Reference Include="System.IdentityModel">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.IdentityModel.dll</HintPath> <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.IdentityModel.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Security.Claims">
<HintPath>..\..\..\..\..\.nuget\packages\system.security.claims\4.3.0\ref\netstandard1.3\System.Security.Claims.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard1.6</TargetFramework> <TargetFramework>netstandard1.6</TargetFramework>
<AssemblyName>Ombi.Api.TheMovieDb</AssemblyName>
<!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>--> <!--<NetStandardImplicitPackageVersion>1.6.1</NetStandardImplicitPackageVersion>-->
</PropertyGroup> </PropertyGroup>

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio 15
VisualStudioVersion = 15.0.26403.0 VisualStudioVersion = 15.0.26228.9
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}"
EndProject EndProject
@ -16,7 +16,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Core", "Ombi.Core\Ombi
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{9293CA11-360A-4C20-A674-B9E794431BF5}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Api", "Api", "{9293CA11-360A-4C20-A674-B9E794431BF5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.TheMovieDbApi", "Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj", "{132DA282-5894-4570-8916-D8C18ED2CE84}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.TheMovieDb", "Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj", "{132DA282-5894-4570-8916-D8C18ED2CE84}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api", "Ombi.Api\Ombi.Api.csproj", "{EA31F915-31F9-4318-B521-1500CDF40DDF}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api", "Ombi.Api\Ombi.Api.csproj", "{EA31F915-31F9-4318-B521-1500CDF40DDF}"
EndProject EndProject
@ -32,6 +32,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mappers", "Mappers", "{025F
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DI", "DI", "{410F36CF-9C60-428A-B191-6FD90610991A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "DI", "DI", "{410F36CF-9C60-428A-B191-6FD90610991A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Plex", "Ombi.Api.Plex\Ombi.Api.Plex.csproj", "{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@ -70,6 +72,10 @@ Global
{63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Release|Any CPU.Build.0 = Release|Any CPU {63E63511-1C7F-4162-8F92-8F7391B3C8A3}.Release|Any CPU.Build.0 = Release|Any CPU
{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -79,5 +85,6 @@ Global
{EA31F915-31F9-4318-B521-1500CDF40DDF} = {9293CA11-360A-4C20-A674-B9E794431BF5} {EA31F915-31F9-4318-B521-1500CDF40DDF} = {9293CA11-360A-4C20-A674-B9E794431BF5}
{B39E4558-C557-48E7-AA74-19C5CD809617} = {410F36CF-9C60-428A-B191-6FD90610991A} {B39E4558-C557-48E7-AA74-19C5CD809617} = {410F36CF-9C60-428A-B191-6FD90610991A}
{63E63511-1C7F-4162-8F92-8F7391B3C8A3} = {025FB189-2FFB-4F43-A64B-6F1B5A0D2065} {63E63511-1C7F-4162-8F92-8F7391B3C8A3} = {025FB189-2FFB-4F43-A64B-6F1B5A0D2065}
{2E1A7B91-F29B-42BC-8F1E-1CF2DCC389BA} = {9293CA11-360A-4C20-A674-B9E794431BF5}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

@ -0,0 +1,50 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Core.Engine;
using Ombi.Core.Models.Requests;
using Ombi.Core.Models.Search;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
namespace Ombi.Controllers
{
public class PlexController : BaseV1ApiController
{
public PlexController(IPlexApi plexApi, ISettingsService<PlexSettings> plexSettings)
{
PlexApi = plexApi;
PlexSettings = plexSettings;
}
private IPlexApi PlexApi { get; }
private ISettingsService<PlexSettings> PlexSettings { get; }
[HttpPost]
public async Task<PlexAuthentication> SignIn([FromBody] UserRequest request)
{
var result = await PlexApi.SignIn(request);
if (!string.IsNullOrEmpty(result.user?.authentication_token))
{
var server = await PlexApi.GetServer(result.user.authentication_token);
var firstServer = server.Server.FirstOrDefault();
await PlexSettings.SaveSettingsAsync(new PlexSettings
{
Enable = true,
PlexAuthToken = result.user.authentication_token,
Ip = firstServer.LocalAddresses,
MachineIdentifier = firstServer.MachineIdentifier,
Port = int.Parse(firstServer.Port),
Ssl = firstServer.Scheme != "http",
});
}
return result;
}
}
}

@ -7,6 +7,10 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Content Remove="wwwroot/app\wizard\plex\plex.component.ts" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="wwwroot\app\auth\auth.guard.ts"> <Content Include="wwwroot\app\auth\auth.guard.ts">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
@ -16,6 +20,11 @@
<Content Include="wwwroot\app\auth\IUserLogin.ts" /> <Content Include="wwwroot\app\auth\IUserLogin.ts" />
<Content Include="wwwroot\app\login\login.component.html" /> <Content Include="wwwroot\app\login\login.component.html" />
<Content Include="wwwroot\app\login\login.component.ts" /> <Content Include="wwwroot\app\login\login.component.ts" />
<Content Include="wwwroot\app\services\plex.service.js" />
<Content Include="wwwroot\app\services\plex.service.js.map" />
<Content Include="wwwroot\app\services\plex.service.ts">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\services\settings.service.js" /> <Content Include="wwwroot\app\services\settings.service.js" />
<Content Include="wwwroot\app\services\settings.service.js.map" /> <Content Include="wwwroot\app\services\settings.service.js.map" />
<Content Include="wwwroot\app\services\settings.service.ts" /> <Content Include="wwwroot\app\services\settings.service.ts" />
@ -52,39 +61,13 @@
<Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.js" /> <Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.js" />
<Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.js.map" /> <Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.js.map" />
<Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.ts" /> <Content Include="wwwroot\app\wizard\mediaserver\mediaserver.component.ts" />
<Content Include="wwwroot\app\wizard\mediaserver\welcome.component.js"> <Content Include="wwwroot\app\wizard\plex\plex.component.html" />
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Content Include="wwwroot\app\wizard\plex\plex - Copy.component.js" />
</Content> <Content Include="wwwroot\app\wizard\plex\plex - Copy.component.js.map" />
<Content Include="wwwroot\app\wizard\mediaserver\welcome.component.js.map"> <Content Include="wwwroot\app\wizard\plex\plex - Copy.component.ts" />
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> <Content Include="wwwroot\app\wizard\plex\plex.component.js" />
</Content> <Content Include="wwwroot\app\wizard\plex\plex.component.js.map" />
<Content Include="wwwroot\app\wizard\mediaserver\welcome.component.ts"> <Content Include="wwwroot\app\wizard\plex\plex.component.ts" />
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\settings.module.js">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\settings.module.js.map">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\settings.module.ts">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\welcome\weclome.component.html">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\welcome\emby.component.js">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\welcome\emby.component.js.map">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\welcome\emby.component.ts">
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Include="wwwroot\app\wizard\welcome\weclome.component.js" />
<Content Include="wwwroot\app\wizard\welcome\weclome.component.js.map" />
<Content Include="wwwroot\app\wizard\welcome\weclome.component.ts" />
<Content Include="wwwroot\app\wizard\welcome\welcome.component.html" /> <Content Include="wwwroot\app\wizard\welcome\welcome.component.html" />
<Content Include="wwwroot\app\wizard\welcome\welcome.component.js" /> <Content Include="wwwroot\app\wizard\welcome\welcome.component.js" />
<Content Include="wwwroot\app\wizard\welcome\welcome.component.js.map" /> <Content Include="wwwroot\app\wizard\welcome\welcome.component.js.map" />
@ -113,21 +96,23 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" /> <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" /> <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
<PackageReference Include="System.Security.Cryptography.Csp" Version="4.3.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" /> <ProjectReference Include="..\Ombi.Core\Ombi.Core.csproj" />
<ProjectReference Include="..\Ombi.DependencyInjection\Ombi.DependencyInjection.csproj" /> <ProjectReference Include="..\Ombi.DependencyInjection\Ombi.DependencyInjection.csproj" />
<ProjectReference Include="..\Ombi.Mapping\Ombi.Mapping.csproj" /> <ProjectReference Include="..\Ombi.Mapping\Ombi.Mapping.csproj" />
<ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.TheMovieDbApi.csproj" /> <ProjectReference Include="..\Ombi.TheMovieDbApi\Ombi.Api.TheMovieDb.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System.Configuration"> <Reference Include="System.Configuration">
<HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Configuration.dll</HintPath> <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.Configuration.dll</HintPath>
</Reference> </Reference>
<Reference Include="System.Security.Cryptography.Csp"> </ItemGroup>
<HintPath>..\..\..\..\..\.nuget\packages\system.security.cryptography.csp\4.3.0\ref\netstandard1.3\System.Security.Cryptography.Csp.dll</HintPath>
</Reference> <ItemGroup>
<Folder Include="Models\Plex\" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -713,4 +713,10 @@ body {
.ui-widget-content { .ui-widget-content {
border: 1px solid $form-color-lighter $i; border: 1px solid $form-color-lighter $i;
background: $form-color $i; background: $form-color $i;
}
// PrimeNg Overide
.ui-growl-item{
margin-top:35px $i;
} }

@ -1,4 +1,4 @@
<p-growl [value]="notificationService.messages" [life]="500000" ></p-growl> <p-growl [value]="notificationService.messages" [life]="500000"></p-growl>
<nav class="navbar navbar-default navbar-fixed-top"> <nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid"> <div class="container-fluid">

@ -0,0 +1,12 @@

export interface IPlexAuthentication {
user: IPlexUser
}
export interface IPlexUser {
email: string,
uuid: string,
username: string,
title: string,
authentication_token: string,
}

@ -21,7 +21,7 @@ export class NotificationService {
} }
public error(title: string, body: string) { public error(title: string, body: string) {
this.addMessage({ severity: 'danger', detail: body, summary: title }); this.addMessage({ severity: 'error', detail: body, summary: title });
} }
public clearMessages() { public clearMessages() {

@ -0,0 +1,20 @@
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Rx';
import { ServiceHelpers } from './service.helpers';
import { IPlexAuthentication } from '../interfaces/IPlex'
@Injectable()
export class PlexService extends ServiceHelpers {
constructor(http: Http) {
super(http, '/api/v1/Plex/');
}
logIn(login: string, password: string): Observable<IPlexAuthentication> {
return this.http.post(`${this.url}/`, JSON.stringify({ login: login, password:password}), { headers: this.headers }).map(this.extractData);
}
}

@ -0,0 +1,17 @@
<h4 class="media-heading landing-title">Plex Authentication</h4>
<div class="form-group">
<label for="username" class="control-label">Username and Password</label>
<div>
<input type="text" [(ngModel)]="login" class="form-control form-control-custom" id="username" placeholder="Username">
</div>
<br />
<div>
<input type="password" [(ngModel)]="password" class="form-control form-control-custom" placeholder="Password">
</div>
</div>
<small>Please note we do not store this information, we only store your Plex Authorization Token that will allow Ombi to view your media and friends</small>
<div class="form-group">
<div style="text-align: center; margin-top: 20px">
<button (click)="requestAuthToken()" class="btn btn-primary-outline">Request Token <i class="fa fa-key"></i></button>
</div>
</div>

@ -0,0 +1,34 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { PlexService } from '../../services/plex.service';
import { NotificationService } from '../../services/notification.service';
import { IPlexAuthentication } from '../../interfaces/IPlex';
@Component({
selector: 'ombi',
moduleId: module.id,
templateUrl: './plex.component.html',
})
export class PlexComponent {
constructor(private plexService: PlexService, private router: Router, private notificationService: NotificationService) { }
private authenticationResult: IPlexAuthentication;
login: string;
password: string;
requestAuthToken() {
this.plexService.logIn(this.login, this.password).subscribe(x => {
if (x.user == null) {
this.notificationService.error("Could Not Authenticate", "Username or password was incorrect. Could not authenticate with Plex.");
return;
}
this.authenticationResult = x;
this.router.navigate(['Wizard/CreateAdmin']);
});
}
}

@ -5,10 +5,14 @@ import { RouterModule, Routes } from '@angular/router';
import { WelcomeComponent } from './welcome/welcome.component'; import { WelcomeComponent } from './welcome/welcome.component';
import { MediaServerComponent } from './mediaserver/mediaserver.component'; import { MediaServerComponent } from './mediaserver/mediaserver.component';
import { PlexComponent } from './plex/plex.component';
import { PlexService } from '../services/plex.service';
const routes: Routes = [ const routes: Routes = [
{ path: 'Wizard', component: WelcomeComponent}, { path: 'Wizard', component: WelcomeComponent},
{ path: 'Wizard/MediaServer', component: MediaServerComponent}, { path: 'Wizard/MediaServer', component: MediaServerComponent},
{ path: 'Wizard/Plex', component: PlexComponent},
]; ];
@NgModule({ @NgModule({
@ -19,12 +23,14 @@ const routes: Routes = [
], ],
declarations: [ declarations: [
WelcomeComponent, WelcomeComponent,
MediaServerComponent MediaServerComponent,
PlexComponent
], ],
exports: [ exports: [
RouterModule RouterModule
], ],
providers: [ providers: [
PlexService
], ],
}) })

Loading…
Cancel
Save