Move all settings into the main server configuration

Decreased the timeout from 30 minutes to 5.
Public lookup values have been replaced with the short code.
This commit is contained in:
ConfusedPolarBear 2020-06-18 01:29:47 -05:00
parent 82887ec710
commit 4be476ec53
8 changed files with 41 additions and 120 deletions

View File

@ -1,20 +0,0 @@
using MediaBrowser.Common.Configuration;
namespace Emby.Server.Implementations.QuickConnect
{
/// <summary>
/// Configuration extension to support persistent quick connect configuration.
/// </summary>
public static class ConfigurationExtension
{
/// <summary>
/// Return the current quick connect configuration.
/// </summary>
/// <param name="manager">Configuration manager.</param>
/// <returns>Current quick connect configuration.</returns>
public static QuickConnectConfiguration GetQuickConnectConfiguration(this IConfigurationManager manager)
{
return manager.GetConfiguration<QuickConnectConfiguration>("quickconnect");
}
}
}

View File

@ -1,15 +0,0 @@
using MediaBrowser.Model.QuickConnect;
namespace Emby.Server.Implementations.QuickConnect
{
/// <summary>
/// Persistent quick connect configuration.
/// </summary>
public class QuickConnectConfiguration
{
/// <summary>
/// Gets or sets persistent quick connect availability state.
/// </summary>
public QuickConnectState State { get; set; }
}
}

View File

@ -1,27 +0,0 @@
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
namespace Emby.Server.Implementations.QuickConnect
{
/// <summary>
/// Configuration factory for quick connect.
/// </summary>
public class QuickConnectConfigurationFactory : IConfigurationFactory
{
/// <summary>
/// Returns the current quick connect configuration.
/// </summary>
/// <returns>Current quick connect configuration.</returns>
public IEnumerable<ConfigurationStore> GetConfigurations()
{
return new[]
{
new ConfigurationStore
{
Key = "quickconnect",
ConfigurationType = typeof(QuickConnectConfiguration)
}
};
}
}
}

View File

@ -11,7 +11,9 @@ using MediaBrowser.Controller.QuickConnect;
using MediaBrowser.Controller.Security;
using MediaBrowser.Model.QuickConnect;
using MediaBrowser.Model.Services;
using MediaBrowser.Common;
using Microsoft.Extensions.Logging;
using MediaBrowser.Common.Extensions;
namespace Emby.Server.Implementations.QuickConnect
{
@ -64,9 +66,7 @@ namespace Emby.Server.Implementations.QuickConnect
public QuickConnectState State { get; private set; } = QuickConnectState.Unavailable;
/// <inheritdoc/>
public int RequestExpiry { get; set; } = 30;
private bool TemporaryActivation { get; set; } = false;
public int Timeout { get; set; } = 5;
private DateTime DateActivated { get; set; }
@ -82,10 +82,9 @@ 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;
SetEnabled(QuickConnectState.Active);
DateActivated = DateTime.Now;
TemporaryActivation = true;
return new QuickConnectResult();
}
@ -96,12 +95,10 @@ namespace Emby.Server.Implementations.QuickConnect
_logger.LogDebug("Changed quick connect state from {0} to {1}", State, newState);
ExpireRequests(true);
State = newState;
_config.SaveConfiguration("quickconnect", new QuickConnectConfiguration()
{
State = State
});
State = newState;
_config.Configuration.QuickConnectAvailable = newState == QuickConnectState.Available || newState == QuickConnectState.Active;
_config.SaveConfiguration();
_logger.LogDebug("Configuration saved");
}
@ -123,17 +120,16 @@ namespace Emby.Server.Implementations.QuickConnect
_logger.LogDebug("Got new quick connect request from {friendlyName}", friendlyName);
var lookup = GenerateSecureRandom();
var code = GenerateCode();
var result = new QuickConnectResult()
{
Lookup = lookup,
Secret = GenerateSecureRandom(),
FriendlyName = friendlyName,
DateAdded = DateTime.Now,
Code = GenerateCode()
Code = code
};
_currentRequests[lookup] = result;
_currentRequests[code] = result;
return result;
}
@ -143,17 +139,16 @@ namespace Emby.Server.Implementations.QuickConnect
ExpireRequests();
AssertActive();
string lookup = _currentRequests.Where(x => x.Value.Secret == secret).Select(x => x.Value.Lookup).DefaultIfEmpty(string.Empty).First();
string code = _currentRequests.Where(x => x.Value.Secret == secret).Select(x => x.Value.Code).DefaultIfEmpty(string.Empty).First();
if (!_currentRequests.TryGetValue(lookup, out QuickConnectResult result))
if (!_currentRequests.TryGetValue(code, out QuickConnectResult result))
{
throw new KeyNotFoundException("Unable to find request with provided identifier");
throw new ResourceNotFoundException("Unable to find request with provided secret");
}
return result;
}
/// <inheritdoc/>
public List<QuickConnectResultDto> GetCurrentRequests()
{
return GetCurrentRequestsInternal().Select(x => (QuickConnectResultDto)x).ToList();
@ -186,16 +181,16 @@ namespace Emby.Server.Implementations.QuickConnect
}
/// <inheritdoc/>
public bool AuthorizeRequest(IRequest request, string lookup)
public bool AuthorizeRequest(IRequest request, string code)
{
ExpireRequests();
AssertActive();
var auth = _authContext.GetAuthorizationInfo(request);
if (!_currentRequests.TryGetValue(lookup, out QuickConnectResult result))
if (!_currentRequests.TryGetValue(code, out QuickConnectResult result))
{
throw new KeyNotFoundException("Unable to find request");
throw new ResourceNotFoundException("Unable to find request");
}
if (result.Authenticated)
@ -205,9 +200,9 @@ namespace Emby.Server.Implementations.QuickConnect
result.Authentication = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture);
// Advance the time on the request so it expires sooner as the client will pick up the changes in a few seconds
var added = result.DateAdded ?? DateTime.Now.Subtract(new TimeSpan(0, RequestExpiry, 0));
result.DateAdded = added.Subtract(new TimeSpan(0, RequestExpiry - 1, 0));
// Change the time on the request so it expires one minute into the future. It can't expire immediately as otherwise some clients wouldn't ever see that they have been authenticated.
var added = result.DateAdded ?? DateTime.Now.Subtract(new TimeSpan(0, Timeout, 0));
result.DateAdded = added.Subtract(new TimeSpan(0, Timeout - 1, 0));
_authenticationRepository.Create(new AuthenticationInfo
{
@ -271,7 +266,7 @@ namespace Emby.Server.Implementations.QuickConnect
var bytes = new byte[length];
_rng.GetBytes(bytes);
return string.Join(string.Empty, bytes.Select(x => x.ToString("x2", CultureInfo.InvariantCulture)));
return Hex.Encode(bytes);
}
/// <summary>
@ -281,12 +276,11 @@ namespace Emby.Server.Implementations.QuickConnect
private void ExpireRequests(bool expireAll = false)
{
// Check if quick connect should be deactivated
if (TemporaryActivation && DateTime.Now > DateActivated.AddMinutes(10) && State == QuickConnectState.Active && !expireAll)
if (State == QuickConnectState.Active && DateTime.Now > DateActivated.AddMinutes(Timeout) && !expireAll)
{
_logger.LogDebug("Quick connect time expired, deactivating");
SetEnabled(QuickConnectState.Available);
expireAll = true;
TemporaryActivation = false;
}
// Expire stale connection requests
@ -296,28 +290,28 @@ namespace Emby.Server.Implementations.QuickConnect
for (int i = 0; i < values.Count; i++)
{
var added = values[i].DateAdded ?? DateTime.UnixEpoch;
if (DateTime.Now > added.AddMinutes(RequestExpiry) || expireAll)
if (DateTime.Now > added.AddMinutes(Timeout) || expireAll)
{
delete.Add(values[i].Lookup);
delete.Add(values[i].Code);
}
}
foreach (var lookup in delete)
foreach (var code in delete)
{
_logger.LogDebug("Removing expired request {lookup}", lookup);
_logger.LogDebug("Removing expired request {code}", code);
if (!_currentRequests.TryRemove(lookup, out _))
if (!_currentRequests.TryRemove(code, out _))
{
_logger.LogWarning("Request {lookup} already expired", lookup);
_logger.LogWarning("Request {code} already expired", code);
}
}
}
private void ReloadConfiguration()
{
var config = _config.GetQuickConnectConfiguration();
var available = _config.Configuration.QuickConnectAvailable;
State = config.State;
State = available ? QuickConnectState.Available : QuickConnectState.Unavailable;
}
}
}

View File

@ -26,9 +26,9 @@ namespace MediaBrowser.Controller.QuickConnect
public QuickConnectState State { get; }
/// <summary>
/// Gets or sets the time (in minutes) before a pending request will expire.
/// Gets or sets the time (in minutes) before quick connect will automatically deactivate.
/// </summary>
public int RequestExpiry { get; set; }
public int Timeout { get; set; }
/// <summary>
/// Assert that quick connect is currently active and throws an exception if it is not.
@ -77,9 +77,9 @@ namespace MediaBrowser.Controller.QuickConnect
/// Authorizes a quick connect request to connect as the calling user.
/// </summary>
/// <param name="request">HTTP request object.</param>
/// <param name="lookup">Public request lookup value.</param>
/// <param name="lookup">Identifying code for the request..</param>
/// <returns>A boolean indicating if the authorization completed successfully.</returns>
bool AuthorizeRequest(IRequest request, string lookup);
bool AuthorizeRequest(IRequest request, string code);
/// <summary>
/// Deletes all quick connect access tokens for the provided user.

View File

@ -76,6 +76,11 @@ namespace MediaBrowser.Model.Configuration
/// <value><c>true</c> if this instance is port authorized; otherwise, <c>false</c>.</value>
public bool IsPortAuthorized { get; set; }
/// <summary>
/// Gets or sets if quick connect is available for use on this server.
/// </summary>
public bool QuickConnectAvailable { get; set; }
public bool AutoRunWebApp { get; set; }
public bool EnableRemoteAccess { get; set; }
@ -281,6 +286,7 @@ namespace MediaBrowser.Model.Configuration
AutoRunWebApp = true;
EnableRemoteAccess = true;
QuickConnectAvailable = false;
EnableUPnP = false;
MinResumePct = 5;

View File

@ -17,11 +17,6 @@ namespace MediaBrowser.Model.QuickConnect
/// </summary>
public string? Secret { get; set; }
/// <summary>
/// Gets or sets the public value used to uniquely identify this request. Can only be used to authorize the request.
/// </summary>
public string? Lookup { get; set; }
/// <summary>
/// Gets or sets the user facing code used so the user can quickly differentiate this request from others.
/// </summary>

View File

@ -17,25 +17,15 @@ namespace MediaBrowser.Model.QuickConnect
/// </summary>
public string? Code { get; private set; }
/// <summary>
/// Gets the public value used to uniquely identify this request. Can only be used to authorize the request.
/// </summary>
public string? Lookup { get; private set; }
/// <summary>
/// Gets the device friendly name.
/// </summary>
public string? FriendlyName { get; private set; }
/// <summary>
/// Gets the DateTime that this request was created.
/// </summary>
public DateTime? DateAdded { get; private set; }
/// <summary>
/// Cast an internal quick connect result to a DTO by removing all sensitive properties.
/// </summary>
/// <param name="result">QuickConnectResult object to cast</param>
/// <param name="result">QuickConnectResult object to cast.</param>
public static implicit operator QuickConnectResultDto(QuickConnectResult result)
{
QuickConnectResultDto resultDto = new QuickConnectResultDto
@ -43,8 +33,6 @@ namespace MediaBrowser.Model.QuickConnect
Authenticated = result.Authenticated,
Code = result.Code,
FriendlyName = result.FriendlyName,
DateAdded = result.DateAdded,
Lookup = result.Lookup
};
return resultDto;