diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
index 4ab0a2a3f2..fa4b3080c9 100644
--- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
+++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
@@ -10,6 +10,7 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
+using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.AppBase
@@ -268,7 +269,7 @@ namespace Emby.Server.Implementations.AppBase
}
///
- public object GetConfiguration(string key)
+ public object GetConfiguration(string key, Type objectType = null)
{
return _configurations.GetOrAdd(key, k =>
{
@@ -277,12 +278,12 @@ namespace Emby.Server.Implementations.AppBase
var configurationInfo = _configurationStores
.FirstOrDefault(i => string.Equals(i.Key, key, StringComparison.OrdinalIgnoreCase));
- if (configurationInfo == null)
+ if (configurationInfo == null && objectType == null)
{
throw new ResourceNotFoundException("Configuration with key " + key + " not found.");
}
- var configurationType = configurationInfo.ConfigurationType;
+ var configurationType = configurationInfo?.ConfigurationType ?? objectType;
lock (_configurationSyncLock)
{
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 77584e9d0d..9d70c15269 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -16,6 +16,7 @@ using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using System.Xml.Serialization;
using Emby.Dlna;
using Emby.Dlna.Main;
using Emby.Dlna.Ssdp;
@@ -48,6 +49,8 @@ using Emby.Server.Implementations.SyncPlay;
using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Updates;
using Jellyfin.Api.Helpers;
+using Jellyfin.Api.Migrations;
+using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
@@ -100,6 +103,7 @@ using MediaBrowser.Providers.Manager;
using MediaBrowser.Providers.Plugins.TheTvdb;
using MediaBrowser.Providers.Subtitles;
using MediaBrowser.XbmcMetadata.Providers;
+using Microsoft.AspNetCore.DataProtection.Repositories;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
@@ -273,6 +277,7 @@ namespace Emby.Server.Implementations
ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
NetManager = new NetworkManager((IServerConfigurationManager)ConfigurationManager, LoggerFactory.CreateLogger());
+ NetManager.UpdateSettings(GetNetworkConfiguration());
Logger = LoggerFactory.CreateLogger();
@@ -298,6 +303,21 @@ namespace Emby.Server.Implementations
ApplicationUserAgent = Name.Replace(' ', '-') + "/" + ApplicationVersionString;
}
+ private NetworkConfiguration GetNetworkConfiguration()
+ {
+ string path = Path.Combine(ConfigurationManager.CommonApplicationPaths.ConfigurationDirectoryPath, "network.xml");
+ if (!File.Exists(path))
+ {
+ var networkSettings = new NetworkConfiguration();
+ ClassMigrationHelper.CopyProperties(ServerConfigurationManager.Configuration, networkSettings);
+ _xmlSerializer.SerializeToFile(networkSettings, path);
+
+ return networkSettings;
+ }
+
+ return (NetworkConfiguration)ConfigurationManager.GetConfiguration("network", typeof(NetworkConfiguration));
+ }
+
public string ExpandVirtualPath(string path)
{
var appPaths = ApplicationPaths;
@@ -480,14 +500,15 @@ namespace Emby.Server.Implementations
///
public void Init()
{
- HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
- HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
+ var networkConfiguration = ServerConfigurationManager.GetNetworkConfiguration();
+ HttpPort = networkConfiguration.HttpServerPortNumber;
+ HttpsPort = networkConfiguration.HttpsPortNumber;
// Safeguard against invalid configuration
if (HttpPort == HttpsPort)
{
- HttpPort = ServerConfiguration.DefaultHttpPort;
- HttpsPort = ServerConfiguration.DefaultHttpsPort;
+ HttpPort = NetworkConfiguration.DefaultHttpPort;
+ HttpsPort = NetworkConfiguration.DefaultHttpsPort;
}
if (Plugins != null)
@@ -929,9 +950,10 @@ namespace Emby.Server.Implementations
// Don't do anything if these haven't been set yet
if (HttpPort != 0 && HttpsPort != 0)
{
+ var networkConfiguration = ServerConfigurationManager.GetNetworkConfiguration();
// Need to restart if ports have changed
- if (ServerConfigurationManager.Configuration.HttpServerPortNumber != HttpPort ||
- ServerConfigurationManager.Configuration.HttpsPortNumber != HttpsPort)
+ if (networkConfiguration.HttpServerPortNumber != HttpPort ||
+ networkConfiguration.HttpsPortNumber != HttpsPort)
{
if (ServerConfigurationManager.Configuration.IsPortAuthorized)
{
@@ -1253,7 +1275,7 @@ namespace Emby.Server.Implementations
}
///
- public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.Configuration.EnableHttps;
+ public bool ListenWithHttps => Certificate != null && ServerConfigurationManager.GetNetworkConfiguration().EnableHttps;
///
public string GetSmartApiUrl(IPAddress ipAddress, int? port = null)
@@ -1337,7 +1359,7 @@ namespace Emby.Server.Implementations
Scheme = scheme ?? (ListenWithHttps ? Uri.UriSchemeHttps : Uri.UriSchemeHttp),
Host = host,
Port = port ?? (ListenWithHttps ? HttpsPort : HttpPort),
- Path = ServerConfigurationManager.Configuration.BaseUrl
+ Path = ServerConfigurationManager.GetNetworkConfiguration().BaseUrl
}.ToString().TrimEnd('/');
}
diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index 2e8cc76d23..14201ead29 100644
--- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -8,6 +8,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Events;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
@@ -56,7 +57,7 @@ namespace Emby.Server.Implementations.EntryPoints
private string GetConfigIdentifier()
{
const char Separator = '|';
- var config = _config.Configuration;
+ var config = _config.GetNetworkConfiguration();
return new StringBuilder(32)
.Append(config.EnableUPnP).Append(Separator)
@@ -93,7 +94,8 @@ namespace Emby.Server.Implementations.EntryPoints
private void Start()
{
- if (!_config.Configuration.EnableUPnP || !_config.Configuration.EnableRemoteAccess)
+ var config = _config.GetNetworkConfiguration();
+ if (!config.EnableUPnP || !config.EnableRemoteAccess)
{
return;
}
@@ -156,11 +158,12 @@ namespace Emby.Server.Implementations.EntryPoints
private IEnumerable CreatePortMaps(INatDevice device)
{
- yield return CreatePortMap(device, _appHost.HttpPort, _config.Configuration.PublicPort);
+ var config = _config.GetNetworkConfiguration();
+ yield return CreatePortMap(device, _appHost.HttpPort, config.PublicPort);
if (_appHost.ListenWithHttps)
{
- yield return CreatePortMap(device, _appHost.HttpsPort, _config.Configuration.PublicHttpsPort);
+ yield return CreatePortMap(device, _appHost.HttpsPort, config.PublicHttpsPort);
}
}
diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs
index e1c9f69f61..09d72e8b10 100644
--- a/Jellyfin.Api/Controllers/ConfigurationController.cs
+++ b/Jellyfin.Api/Controllers/ConfigurationController.cs
@@ -4,7 +4,9 @@ using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
+using Jellyfin.Api.Migrations;
using Jellyfin.Api.Models.ConfigurationDtos;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Common.Json;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.MediaEncoding;
@@ -49,6 +51,10 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult GetConfiguration()
{
+ // TODO: Temp workaround until the web can be changed.
+ var net = _configurationManager.GetNetworkConfiguration();
+ ClassMigrationHelper.CopyProperties(net, _configurationManager.Configuration);
+
return _configurationManager.Configuration;
}
@@ -64,6 +70,12 @@ namespace Jellyfin.Api.Controllers
public ActionResult UpdateConfiguration([FromBody, Required] ServerConfiguration configuration)
{
_configurationManager.ReplaceConfiguration(configuration);
+
+ // TODO: Temp workaround until the web can be changed.
+ var network = _configurationManager.GetNetworkConfiguration();
+ ClassMigrationHelper.CopyProperties(configuration, network);
+ _configurationManager.SaveConfiguration("Network", network);
+
return NoContent();
}
diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs
index e59c6e1ddf..d9cb34557b 100644
--- a/Jellyfin.Api/Controllers/StartupController.cs
+++ b/Jellyfin.Api/Controllers/StartupController.cs
@@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Models.StartupDtos;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using Microsoft.AspNetCore.Authorization;
@@ -89,9 +90,10 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SetRemoteAccess([FromBody, Required] StartupRemoteAccessDto startupRemoteAccessDto)
{
- _config.Configuration.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
- _config.Configuration.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping;
- _config.SaveConfiguration();
+ NetworkConfiguration settings = _config.GetNetworkConfiguration();
+ settings.EnableRemoteAccess = startupRemoteAccessDto.EnableRemoteAccess;
+ settings.EnableUPnP = startupRemoteAccessDto.EnableAutomaticPortMapping;
+ _config.SaveConfiguration("network", settings);
return NoContent();
}
diff --git a/Jellyfin.Api/Helpers/ClassMigrationHelper.cs b/Jellyfin.Api/Helpers/ClassMigrationHelper.cs
new file mode 100644
index 0000000000..123fd012de
--- /dev/null
+++ b/Jellyfin.Api/Helpers/ClassMigrationHelper.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Reflection;
+
+namespace Jellyfin.Api.Migrations
+{
+ ///
+ /// A static class for reflection type functions. Temporary until web changed.
+ ///
+ public static class ClassMigrationHelper
+ {
+ ///
+ /// Extension for 'Object' that copies the properties to a destination object.
+ ///
+ /// The source.
+ /// The destination.
+ public static void CopyProperties(this object source, object destination)
+ {
+ // If any this null throw an exception
+ if (source == null || destination == null)
+ {
+ throw new Exception("Source or/and Destination Objects are null");
+ }
+
+ // Getting the Types of the objects
+ Type typeDest = destination.GetType();
+ Type typeSrc = source.GetType();
+
+ // Iterate the Properties of the source instance and populate them from their desination counterparts.
+ PropertyInfo[] srcProps = typeSrc.GetProperties();
+ foreach (PropertyInfo srcProp in srcProps)
+ {
+ if (!srcProp.CanRead)
+ {
+ continue;
+ }
+
+ var targetProperty = typeDest.GetProperty(srcProp.Name);
+ if (targetProperty == null)
+ {
+ continue;
+ }
+
+ if (!targetProperty.CanWrite)
+ {
+ continue;
+ }
+
+ var obj = targetProperty.GetSetMethod(true);
+ if (obj != null && obj.IsPrivate)
+ {
+ continue;
+ }
+
+ var target = targetProperty.GetSetMethod();
+ if (target != null && (target.Attributes & MethodAttributes.Static) != 0)
+ {
+ continue;
+ }
+
+ if (!targetProperty.PropertyType.IsAssignableFrom(srcProp.PropertyType))
+ {
+ continue;
+ }
+
+ // Passed all tests, lets set the value
+ targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
+ }
+ }
+ }
+}
diff --git a/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs b/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
index c7fbfa4d02..6bf6f383fc 100644
--- a/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
+++ b/Jellyfin.Server/Extensions/ApiApplicationBuilderExtensions.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using Jellyfin.Networking.Configuration;
using Jellyfin.Server.Middleware;
using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Builder;
@@ -24,8 +25,8 @@ namespace Jellyfin.Server.Extensions
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
- var baseUrl = serverConfigurationManager.Configuration.BaseUrl.Trim('/');
- var apiDocBaseUrl = serverConfigurationManager.Configuration.BaseUrl;
+ var baseUrl = serverConfigurationManager.GetNetworkConfiguration().BaseUrl.Trim('/');
+ var apiDocBaseUrl = serverConfigurationManager.GetNetworkConfiguration().BaseUrl;
if (!string.IsNullOrEmpty(baseUrl))
{
baseUrl += '/';
diff --git a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
index 9316737bdf..c23da2fd63 100644
--- a/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
+++ b/Jellyfin.Server/Middleware/BaseUrlRedirectionMiddleware.cs
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Controller.Configuration;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
@@ -42,7 +43,7 @@ namespace Jellyfin.Server.Middleware
public async Task Invoke(HttpContext httpContext, IServerConfigurationManager serverConfigurationManager)
{
var localPath = httpContext.Request.Path.ToString();
- var baseUrlPrefix = serverConfigurationManager.Configuration.BaseUrl;
+ var baseUrlPrefix = serverConfigurationManager.GetNetworkConfiguration().BaseUrl;
if (string.Equals(localPath, baseUrlPrefix + "/", StringComparison.OrdinalIgnoreCase)
|| string.Equals(localPath, baseUrlPrefix, StringComparison.OrdinalIgnoreCase)
diff --git a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs
index 0713d97d65..6f636819fc 100644
--- a/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs
+++ b/Jellyfin.Server/Middleware/IpBasedAccessValidationMiddleware.cs
@@ -1,5 +1,6 @@
using System.Net;
using System.Threading.Tasks;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@@ -42,7 +43,7 @@ namespace Jellyfin.Server.Middleware
var remoteIp = httpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback;
- if (serverConfigurationManager.Configuration.EnableRemoteAccess)
+ if (serverConfigurationManager.GetNetworkConfiguration().EnableRemoteAccess)
{
// Comma separated list of IP addresses or IP/netmask entries for networks that will be allowed to connect remotely.
// If left blank, all remote addresses will be allowed.
@@ -52,7 +53,7 @@ namespace Jellyfin.Server.Middleware
{
// remoteAddressFilter is a whitelist or blacklist.
bool isListed = remoteAddressFilter.Contains(remoteIp);
- if (!serverConfigurationManager.Configuration.IsRemoteIPFilterBlacklist)
+ if (!serverConfigurationManager.GetNetworkConfiguration().IsRemoteIPFilterBlacklist)
{
// Black list, so flip over.
isListed = !isListed;
diff --git a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs
index 1ef460bd76..1f4e80053d 100644
--- a/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs
+++ b/Jellyfin.Server/Middleware/LanFilteringMiddleware.cs
@@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
+using Jellyfin.Networking.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@@ -37,7 +38,7 @@ namespace Jellyfin.Server.Middleware
{
var host = httpContext.Connection.RemoteIpAddress ?? IPAddress.Loopback;
- if (!networkManager.IsInLocalNetwork(host) && !serverConfigurationManager.Configuration.EnableRemoteAccess)
+ if (!networkManager.IsInLocalNetwork(host) && !serverConfigurationManager.GetNetworkConfiguration().EnableRemoteAccess)
{
return;
}
diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs
index 2f4620aa63..3484598b8c 100644
--- a/Jellyfin.Server/Startup.cs
+++ b/Jellyfin.Server/Startup.cs
@@ -2,6 +2,7 @@ using System;
using System.ComponentModel;
using System.Net.Http.Headers;
using Jellyfin.Api.TypeConverters;
+using Jellyfin.Networking.Configuration;
using Jellyfin.Server.Extensions;
using Jellyfin.Server.Implementations;
using Jellyfin.Server.Middleware;
@@ -52,7 +53,7 @@ namespace Jellyfin.Server
{
options.HttpsPort = _serverApplicationHost.HttpsPort;
});
- services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.Configuration.KnownProxies);
+ services.AddJellyfinApi(_serverApplicationHost.GetApiPluginAssemblies(), _serverConfigurationManager.GetNetworkConfiguration().KnownProxies);
services.AddJellyfinApiSwagger();
@@ -96,7 +97,7 @@ namespace Jellyfin.Server
app.UseBaseUrlRedirection();
// Wrap rest of configuration so everything only listens on BaseUrl.
- app.Map(_serverConfigurationManager.Configuration.BaseUrl, mainApp =>
+ app.Map(_serverConfigurationManager.GetNetworkConfiguration().BaseUrl, mainApp =>
{
if (env.IsDevelopment())
{
diff --git a/MediaBrowser.Common/Configuration/IConfigurationManager.cs b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
index fe726090d6..7bcd4d8ed3 100644
--- a/MediaBrowser.Common/Configuration/IConfigurationManager.cs
+++ b/MediaBrowser.Common/Configuration/IConfigurationManager.cs
@@ -50,8 +50,9 @@ namespace MediaBrowser.Common.Configuration
/// Gets the configuration.
///
/// The key.
+ /// Optional parameter containing the key object to create, if it hasn't been registered.
/// System.Object.
- object GetConfiguration(string key);
+ object GetConfiguration(string key, Type objectType = null);
///
/// Gets the type of the configuration.