Allow changing listening ip addresses (#1713)
* Allow changing listening ip address * Use Json serialize for appsettings.config saving * BOM * IP Address validation * ip address reset * ValidIpAddress regex
This commit is contained in:
parent
01aed6ad99
commit
11cb2cfb17
13 changed files with 194 additions and 17 deletions
|
@ -2,6 +2,7 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using API.Data;
|
||||
using API.DTOs.Email;
|
||||
|
@ -70,6 +71,27 @@ public class SettingsController : BaseApiController
|
|||
return await UpdateSettings(_mapper.Map<ServerSettingDto>(Seed.DefaultSettings));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the IP Addresses
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[Authorize(Policy = "RequireAdminRole")]
|
||||
[HttpPost("reset-ip-addresses")]
|
||||
public async Task<ActionResult<ServerSettingDto>> ResetIPAddressesSettings()
|
||||
{
|
||||
_logger.LogInformation("{UserName} is resetting IP Addresses Setting", User.GetUsername());
|
||||
var ipAddresses = await _unitOfWork.SettingsRepository.GetSettingAsync(ServerSettingKey.IpAddresses);
|
||||
ipAddresses.Value = Configuration.DefaultIPAddresses;
|
||||
_unitOfWork.SettingsRepository.Update(ipAddresses);
|
||||
|
||||
if (!await _unitOfWork.CommitAsync())
|
||||
{
|
||||
await _unitOfWork.RollbackAsync();
|
||||
}
|
||||
|
||||
return Ok(await _unitOfWork.SettingsRepository.GetSettingsDtoAsync());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the email service url
|
||||
/// </summary>
|
||||
|
@ -145,6 +167,22 @@ public class SettingsController : BaseApiController
|
|||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.IpAddresses && updateSettingsDto.IpAddresses != setting.Value)
|
||||
{
|
||||
// Validate IP addresses
|
||||
foreach (var ipAddress in updateSettingsDto.IpAddresses.Split(','))
|
||||
{
|
||||
if (!IPAddress.TryParse(ipAddress.Trim(), out _)) {
|
||||
return BadRequest($"IP Address '{ipAddress}' is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
setting.Value = updateSettingsDto.IpAddresses;
|
||||
// IpAddesses is managed in appSetting.json
|
||||
Configuration.IpAddresses = updateSettingsDto.IpAddresses;
|
||||
_unitOfWork.SettingsRepository.Update(setting);
|
||||
}
|
||||
|
||||
if (setting.Key == ServerSettingKey.BaseUrl && updateSettingsDto.BaseUrl + string.Empty != setting.Value)
|
||||
{
|
||||
var path = !updateSettingsDto.BaseUrl.StartsWith("/")
|
||||
|
|
|
@ -18,6 +18,10 @@ public class ServerSettingDto
|
|||
/// </summary>
|
||||
public int Port { get; set; }
|
||||
/// <summary>
|
||||
/// Comma separated list of ip addresses the server listens on. Managed in appsettings.json
|
||||
/// </summary>
|
||||
public string IpAddresses { get; set; }
|
||||
/// <summary>
|
||||
/// Allows anonymous information to be collected and sent to KavitaStats
|
||||
/// </summary>
|
||||
public bool AllowStatCollection { get; set; }
|
||||
|
|
|
@ -89,6 +89,9 @@ public static class Seed
|
|||
{
|
||||
Key = ServerSettingKey.Port, Value = "5000"
|
||||
}, // Not used from DB, but DB is sync with appSettings.json
|
||||
new() {
|
||||
Key = ServerSettingKey.IpAddresses, Value = "0.0.0.0,::"
|
||||
}, // Not used from DB, but DB is sync with appSettings.json
|
||||
new() {Key = ServerSettingKey.AllowStatCollection, Value = "true"},
|
||||
new() {Key = ServerSettingKey.EnableOpds, Value = "true"},
|
||||
new() {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
|
||||
|
@ -116,9 +119,11 @@ public static class Seed
|
|||
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
// Port and LoggingLevel are managed in appSettings.json. Update the DB values to match
|
||||
// Port, IpAddresses and LoggingLevel are managed in appSettings.json. Update the DB values to match
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.Port).Value =
|
||||
Configuration.Port + string.Empty;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.IpAddresses).Value =
|
||||
Configuration.IpAddresses;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheDirectory).Value =
|
||||
directoryService.CacheDirectory + string.Empty;
|
||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.BackupDirectory).Value =
|
||||
|
|
|
@ -110,5 +110,9 @@ public enum ServerSettingKey
|
|||
/// </summary>
|
||||
[Description("HostName")]
|
||||
HostName = 20,
|
||||
|
||||
/// <summary>
|
||||
/// Ip addresses the server listens on. Not managed in DB. Managed in appsettings.json and synced to DB.
|
||||
/// </summary>
|
||||
[Description("IpAddresses")]
|
||||
IpAddresses = 21,
|
||||
}
|
||||
|
|
|
@ -30,6 +30,9 @@ public class ServerSettingConverter : ITypeConverter<IEnumerable<ServerSetting>,
|
|||
case ServerSettingKey.Port:
|
||||
destination.Port = int.Parse(row.Value);
|
||||
break;
|
||||
case ServerSettingKey.IpAddresses:
|
||||
destination.IpAddresses = row.Value;
|
||||
break;
|
||||
case ServerSettingKey.AllowStatCollection:
|
||||
destination.AllowStatCollection = bool.Parse(row.Value);
|
||||
break;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using System;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Abstractions;
|
||||
using System.Linq;
|
||||
|
@ -173,7 +173,25 @@ public class Program
|
|||
{
|
||||
webBuilder.UseKestrel((opts) =>
|
||||
{
|
||||
opts.ListenAnyIP(HttpPort, options => { options.Protocols = HttpProtocols.Http1AndHttp2; });
|
||||
var ipAddresses = Configuration.IpAddresses;
|
||||
if (ipAddresses == null || ipAddresses.Length == 0)
|
||||
{
|
||||
opts.ListenAnyIP(HttpPort, options => { options.Protocols = HttpProtocols.Http1AndHttp2; });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach(var ipAddress in ipAddresses.Split(','))
|
||||
{
|
||||
try {
|
||||
var address = System.Net.IPAddress.Parse(ipAddress.Trim());
|
||||
opts.Listen(address, HttpPort, options => { options.Protocols = HttpProtocols.Http1AndHttp2; });
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Log.Fatal(ex, "Could not parse ip addess '{0}'", ipAddress);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
webBuilder.UseStartup<Startup>();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"TokenKey": "super secret unguessable key",
|
||||
"Port": 5000
|
||||
"Port": 5000,
|
||||
"IpAddresses": "0.0.0.0,::"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
{
|
||||
"TokenKey": "super secret unguessable key",
|
||||
"Port": 5000
|
||||
"Port": 5000,
|
||||
"IpAddresses": "0.0.0.0,::"
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue