aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Emby.Server.Implementations/QuickConnect/ConfigurationExtension.cs30
-rw-r--r--Emby.Server.Implementations/QuickConnect/QuickConnectConfiguration.cs13
-rw-r--r--Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs72
-rw-r--r--MediaBrowser.Api/QuickConnect/QuickConnectService.cs40
-rw-r--r--MediaBrowser.Controller/QuickConnect/IQuickConnect.cs8
5 files changed, 149 insertions, 14 deletions
diff --git a/Emby.Server.Implementations/QuickConnect/ConfigurationExtension.cs b/Emby.Server.Implementations/QuickConnect/ConfigurationExtension.cs
new file mode 100644
index 000000000..0e35ba80a
--- /dev/null
+++ b/Emby.Server.Implementations/QuickConnect/ConfigurationExtension.cs
@@ -0,0 +1,30 @@
+#pragma warning disable CS1591
+
+using System.Collections.Generic;
+using MediaBrowser.Common.Configuration;
+
+namespace Emby.Server.Implementations.QuickConnect
+{
+ public static class ConfigurationExtension
+ {
+ public static QuickConnectConfiguration GetQuickConnectConfiguration(this IConfigurationManager manager)
+ {
+ return manager.GetConfiguration<QuickConnectConfiguration>("quickconnect");
+ }
+ }
+
+ public class QuickConnectConfigurationFactory : IConfigurationFactory
+ {
+ public IEnumerable<ConfigurationStore> GetConfigurations()
+ {
+ return new ConfigurationStore[]
+ {
+ new ConfigurationStore
+ {
+ Key = "quickconnect",
+ ConfigurationType = typeof(QuickConnectConfiguration)
+ }
+ };
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectConfiguration.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectConfiguration.cs
new file mode 100644
index 000000000..befc46379
--- /dev/null
+++ b/Emby.Server.Implementations/QuickConnect/QuickConnectConfiguration.cs
@@ -0,0 +1,13 @@
+using MediaBrowser.Model.QuickConnect;
+
+namespace Emby.Server.Implementations.QuickConnect
+{
+ public class QuickConnectConfiguration
+ {
+ public QuickConnectConfiguration()
+ {
+ }
+
+ public QuickConnectState State { get; set; }
+ }
+}
diff --git a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs
index 30418097c..671ddc2b9 100644
--- a/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs
+++ b/Emby.Server.Implementations/QuickConnect/QuickConnectManager.cs
@@ -3,7 +3,9 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Security.Cryptography;
+using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.QuickConnect;
@@ -12,6 +14,7 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.QuickConnect;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Services;
+using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.QuickConnect
@@ -24,6 +27,7 @@ namespace Emby.Server.Implementations.QuickConnect
private readonly RNGCryptoServiceProvider _rng = new RNGCryptoServiceProvider();
private Dictionary<string, QuickConnectResult> _currentRequests = new Dictionary<string, QuickConnectResult>();
+ private IServerConfigurationManager _config;
private ILogger _logger;
private IUserManager _userManager;
private ILocalizationManager _localizationManager;
@@ -31,11 +35,13 @@ namespace Emby.Server.Implementations.QuickConnect
private IAuthenticationRepository _authenticationRepository;
private IAuthorizationContext _authContext;
private IServerApplicationHost _appHost;
+ private ITaskManager _taskManager;
/// <summary>
/// Initializes a new instance of the <see cref="QuickConnectManager"/> class.
/// Should only be called at server startup when a singleton is created.
/// </summary>
+ /// <param name="config">Configuration.</param>
/// <param name="loggerFactory">Logger.</param>
/// <param name="userManager">User manager.</param>
/// <param name="localization">Localization.</param>
@@ -43,15 +49,19 @@ namespace Emby.Server.Implementations.QuickConnect
/// <param name="appHost">Application host.</param>
/// <param name="authContext">Authentication context.</param>
/// <param name="authenticationRepository">Authentication repository.</param>
+ /// <param name="taskManager">Task scheduler.</param>
public QuickConnectManager(
+ IServerConfigurationManager config,
ILoggerFactory loggerFactory,
IUserManager userManager,
ILocalizationManager localization,
IJsonSerializer jsonSerializer,
IServerApplicationHost appHost,
IAuthorizationContext authContext,
- IAuthenticationRepository authenticationRepository)
+ IAuthenticationRepository authenticationRepository,
+ ITaskManager taskManager)
{
+ _config = config;
_logger = loggerFactory.CreateLogger(nameof(QuickConnectManager));
_userManager = userManager;
_localizationManager = localization;
@@ -59,6 +69,16 @@ namespace Emby.Server.Implementations.QuickConnect
_appHost = appHost;
_authContext = authContext;
_authenticationRepository = authenticationRepository;
+ _taskManager = taskManager;
+
+ ReloadConfiguration();
+ }
+
+ private void ReloadConfiguration()
+ {
+ var config = _config.GetQuickConnectConfiguration();
+
+ State = config.State;
}
/// <inheritdoc/>
@@ -73,6 +93,10 @@ namespace Emby.Server.Implementations.QuickConnect
/// <inheritdoc/>
public int RequestExpiry { get; set; } = 30;
+ private bool TemporaryActivation { get; set; } = false;
+
+ private DateTime DateActivated { get; set; }
+
/// <inheritdoc/>
public void AssertActive()
{
@@ -83,16 +107,36 @@ namespace Emby.Server.Implementations.QuickConnect
}
/// <inheritdoc/>
+ public QuickConnectResult Activate()
+ {
+ // This should not call SetEnabled since that would persist the "temporary" activation to the configuration file
+ State = QuickConnectState.Active;
+ DateActivated = DateTime.Now;
+ TemporaryActivation = true;
+
+ return new QuickConnectResult();
+ }
+
+ /// <inheritdoc/>
public void SetEnabled(QuickConnectState newState)
{
_logger.LogDebug("Changed quick connect state from {0} to {1}", State, newState);
State = newState;
+
+ _config.SaveConfiguration("quickconnect", new QuickConnectConfiguration()
+ {
+ State = State
+ });
+
+ _logger.LogDebug("Configuration saved");
}
/// <inheritdoc/>
public QuickConnectResult TryConnect(string friendlyName)
{
+ ExpireRequests(true);
+
if (State != QuickConnectState.Active)
{
_logger.LogDebug("Refusing quick connect initiation request, current state is {0}", State);
@@ -122,13 +166,11 @@ namespace Emby.Server.Implementations.QuickConnect
/// <inheritdoc/>
public QuickConnectResult CheckRequestStatus(string secret)
{
- AssertActive();
ExpireRequests();
+ AssertActive();
string lookup = _currentRequests.Where(x => x.Value.Secret == secret).Select(x => x.Value.Lookup).DefaultIfEmpty(string.Empty).First();
- _logger.LogDebug("Transformed private identifier {0} into public lookup {1}", secret, lookup);
-
if (!_currentRequests.ContainsKey(lookup))
{
throw new KeyNotFoundException("Unable to find request with provided identifier");
@@ -146,8 +188,8 @@ namespace Emby.Server.Implementations.QuickConnect
/// <inheritdoc/>
public List<QuickConnectResult> GetCurrentRequestsInternal()
{
- AssertActive();
ExpireRequests();
+ AssertActive();
return _currentRequests.Values.ToList();
}
@@ -174,12 +216,11 @@ namespace Emby.Server.Implementations.QuickConnect
/// <inheritdoc/>
public bool AuthorizeRequest(IRequest request, string lookup)
{
+ ExpireRequests();
AssertActive();
var auth = _authContext.GetAuthorizationInfo(request);
- ExpireRequests();
-
if (!_currentRequests.ContainsKey(lookup))
{
throw new KeyNotFoundException("Unable to find request");
@@ -208,6 +249,8 @@ namespace Emby.Server.Implementations.QuickConnect
UserId = auth.UserId
});
+ _logger.LogInformation("Allowing device {0} to login as user {1} with quick connect code {2}", result.FriendlyName, auth.User.Name, result.Code);
+
return true;
}
@@ -239,8 +282,21 @@ namespace Emby.Server.Implementations.QuickConnect
return string.Join(string.Empty, bytes.Select(x => x.ToString("x2", CultureInfo.InvariantCulture)));
}
- private void ExpireRequests()
+ private void ExpireRequests(bool onlyCheckTime = false)
{
+ // check if quick connect should be deactivated
+ if (TemporaryActivation && DateTime.Now > DateActivated.AddMinutes(10) && State == QuickConnectState.Active)
+ {
+ _logger.LogDebug("Quick connect time expired, deactivating");
+ SetEnabled(QuickConnectState.Available);
+ }
+
+ if (onlyCheckTime)
+ {
+ return;
+ }
+
+ // expire stale connection requests
var delete = new List<string>();
var values = _currentRequests.Values.ToList();
diff --git a/MediaBrowser.Api/QuickConnect/QuickConnectService.cs b/MediaBrowser.Api/QuickConnect/QuickConnectService.cs
index 889a78839..60d6ac414 100644
--- a/MediaBrowser.Api/QuickConnect/QuickConnectService.cs
+++ b/MediaBrowser.Api/QuickConnect/QuickConnectService.cs
@@ -98,6 +98,11 @@ namespace MediaBrowser.Api.QuickConnect
public object Get(QuickConnectList request)
{
+ if(_quickConnect.State != QuickConnectState.Active)
+ {
+ return Array.Empty<QuickConnectResultDto>();
+ }
+
return _quickConnect.GetCurrentRequests();
}
@@ -124,15 +129,40 @@ namespace MediaBrowser.Api.QuickConnect
public object Post(Activate request)
{
- if (_quickConnect.State == QuickConnectState.Available)
+ string name = _authContext.GetAuthorizationInfo(Request).User.Name;
+
+ if(_quickConnect.State == QuickConnectState.Unavailable)
+ {
+ return new QuickConnectResult()
+ {
+ Error = "Quick connect is not enabled on this server"
+ };
+ }
+
+ else if(_quickConnect.State == QuickConnectState.Available)
{
- _quickConnect.SetEnabled(QuickConnectState.Active);
+ var result = _quickConnect.Activate();
- string name = _authContext.GetAuthorizationInfo(Request).User.Name;
- Logger.LogInformation("{name} enabled quick connect", name);
+ if (string.IsNullOrEmpty(result.Error))
+ {
+ Logger.LogInformation("{name} temporarily activated quick connect", name);
+ }
+
+ return result;
}
- return _quickConnect.State;
+ else if(_quickConnect.State == QuickConnectState.Active)
+ {
+ return new QuickConnectResult()
+ {
+ Error = ""
+ };
+ }
+
+ return new QuickConnectResult()
+ {
+ Error = "Unknown current state"
+ };
}
public object Post(Available request)
diff --git a/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs b/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs
index e4a790ffe..d44765e11 100644
--- a/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs
+++ b/MediaBrowser.Controller/QuickConnect/IQuickConnect.cs
@@ -36,9 +36,15 @@ namespace MediaBrowser.Controller.QuickConnect
void AssertActive();
/// <summary>
+ /// Temporarily activates quick connect for a short amount of time.
+ /// </summary>
+ /// <returns>A quick connect result object indicating success.</returns>
+ QuickConnectResult Activate();
+
+ /// <summary>
/// Changes the status of quick connect.
/// </summary>
- /// <param name="newState">New state to change to</param>
+ /// <param name="newState">New state to change to.</param>
void SetEnabled(QuickConnectState newState);
/// <summary>