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:
parent
82887ec710
commit
4be476ec53
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user