mirror of
https://github.com/Kareadita/Kavita.git
synced 2025-07-09 03:04:19 -04:00
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
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using API.Data;
|
using API.Data;
|
||||||
using API.DTOs.Email;
|
using API.DTOs.Email;
|
||||||
@ -70,6 +71,27 @@ public class SettingsController : BaseApiController
|
|||||||
return await UpdateSettings(_mapper.Map<ServerSettingDto>(Seed.DefaultSettings));
|
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>
|
/// <summary>
|
||||||
/// Resets the email service url
|
/// Resets the email service url
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -145,6 +167,22 @@ public class SettingsController : BaseApiController
|
|||||||
_unitOfWork.SettingsRepository.Update(setting);
|
_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)
|
if (setting.Key == ServerSettingKey.BaseUrl && updateSettingsDto.BaseUrl + string.Empty != setting.Value)
|
||||||
{
|
{
|
||||||
var path = !updateSettingsDto.BaseUrl.StartsWith("/")
|
var path = !updateSettingsDto.BaseUrl.StartsWith("/")
|
||||||
|
@ -18,6 +18,10 @@ public class ServerSettingDto
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public int Port { get; set; }
|
public int Port { get; set; }
|
||||||
/// <summary>
|
/// <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
|
/// Allows anonymous information to be collected and sent to KavitaStats
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowStatCollection { get; set; }
|
public bool AllowStatCollection { get; set; }
|
||||||
|
@ -89,6 +89,9 @@ public static class Seed
|
|||||||
{
|
{
|
||||||
Key = ServerSettingKey.Port, Value = "5000"
|
Key = ServerSettingKey.Port, Value = "5000"
|
||||||
}, // Not used from DB, but DB is sync with appSettings.json
|
}, // 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.AllowStatCollection, Value = "true"},
|
||||||
new() {Key = ServerSettingKey.EnableOpds, Value = "true"},
|
new() {Key = ServerSettingKey.EnableOpds, Value = "true"},
|
||||||
new() {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
|
new() {Key = ServerSettingKey.EnableAuthentication, Value = "true"},
|
||||||
@ -116,9 +119,11 @@ public static class Seed
|
|||||||
|
|
||||||
await context.SaveChangesAsync();
|
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 =
|
context.ServerSetting.First(s => s.Key == ServerSettingKey.Port).Value =
|
||||||
Configuration.Port + string.Empty;
|
Configuration.Port + string.Empty;
|
||||||
|
context.ServerSetting.First(s => s.Key == ServerSettingKey.IpAddresses).Value =
|
||||||
|
Configuration.IpAddresses;
|
||||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheDirectory).Value =
|
context.ServerSetting.First(s => s.Key == ServerSettingKey.CacheDirectory).Value =
|
||||||
directoryService.CacheDirectory + string.Empty;
|
directoryService.CacheDirectory + string.Empty;
|
||||||
context.ServerSetting.First(s => s.Key == ServerSettingKey.BackupDirectory).Value =
|
context.ServerSetting.First(s => s.Key == ServerSettingKey.BackupDirectory).Value =
|
||||||
|
@ -110,5 +110,9 @@ public enum ServerSettingKey
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[Description("HostName")]
|
[Description("HostName")]
|
||||||
HostName = 20,
|
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:
|
case ServerSettingKey.Port:
|
||||||
destination.Port = int.Parse(row.Value);
|
destination.Port = int.Parse(row.Value);
|
||||||
break;
|
break;
|
||||||
|
case ServerSettingKey.IpAddresses:
|
||||||
|
destination.IpAddresses = row.Value;
|
||||||
|
break;
|
||||||
case ServerSettingKey.AllowStatCollection:
|
case ServerSettingKey.AllowStatCollection:
|
||||||
destination.AllowStatCollection = bool.Parse(row.Value);
|
destination.AllowStatCollection = bool.Parse(row.Value);
|
||||||
break;
|
break;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Abstractions;
|
using System.IO.Abstractions;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -173,7 +173,25 @@ public class Program
|
|||||||
{
|
{
|
||||||
webBuilder.UseKestrel((opts) =>
|
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>();
|
webBuilder.UseStartup<Startup>();
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"TokenKey": "super secret unguessable key",
|
"TokenKey": "super secret unguessable key",
|
||||||
"Port": 5000
|
"Port": 5000,
|
||||||
|
"IpAddresses": "0.0.0.0,::"
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"TokenKey": "super secret unguessable key",
|
"TokenKey": "super secret unguessable key",
|
||||||
"Port": 5000
|
"Port": 5000,
|
||||||
|
"IpAddresses": "0.0.0.0,::"
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ namespace Kavita.Common;
|
|||||||
|
|
||||||
public static class Configuration
|
public static class Configuration
|
||||||
{
|
{
|
||||||
|
public const string DefaultIPAddresses = "0.0.0.0,::";
|
||||||
public static readonly string AppSettingsFilename = Path.Join("config", GetAppSettingFilename());
|
public static readonly string AppSettingsFilename = Path.Join("config", GetAppSettingFilename());
|
||||||
|
|
||||||
public static int Port
|
public static int Port
|
||||||
@ -16,6 +17,12 @@ public static class Configuration
|
|||||||
set => SetPort(GetAppSettingFilename(), value);
|
set => SetPort(GetAppSettingFilename(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string IpAddresses
|
||||||
|
{
|
||||||
|
get => GetIpAddresses(GetAppSettingFilename());
|
||||||
|
set => SetIpAddresses(GetAppSettingFilename(), value);
|
||||||
|
}
|
||||||
|
|
||||||
public static string JwtToken
|
public static string JwtToken
|
||||||
{
|
{
|
||||||
get => GetJwtToken(GetAppSettingFilename());
|
get => GetJwtToken(GetAppSettingFilename());
|
||||||
@ -63,9 +70,10 @@ public static class Configuration
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var currentToken = GetJwtToken(filePath);
|
var json = File.ReadAllText(filePath);
|
||||||
var json = File.ReadAllText(filePath)
|
var jsonObj = JsonSerializer.Deserialize<AppSettings>(json);
|
||||||
.Replace("\"TokenKey\": \"" + currentToken, "\"TokenKey\": \"" + token);
|
jsonObj.TokenKey = token;
|
||||||
|
json = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true });
|
||||||
File.WriteAllText(filePath, json);
|
File.WriteAllText(filePath, json);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -101,8 +109,10 @@ public static class Configuration
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var currentPort = GetPort(filePath);
|
var json = File.ReadAllText(filePath);
|
||||||
var json = File.ReadAllText(filePath).Replace("\"Port\": " + currentPort, "\"Port\": " + port);
|
var jsonObj = JsonSerializer.Deserialize<AppSettings>(json);
|
||||||
|
jsonObj.Port = port;
|
||||||
|
json = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true });
|
||||||
File.WriteAllText(filePath, json);
|
File.WriteAllText(filePath, json);
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@ -139,4 +149,61 @@ public static class Configuration
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region Ip Addresses
|
||||||
|
|
||||||
|
private static void SetIpAddresses(string filePath, string ipAddresses)
|
||||||
|
{
|
||||||
|
if (new OsInfo(Array.Empty<IOsVersionAdapter>()).IsDocker)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(filePath);
|
||||||
|
var jsonObj = JsonSerializer.Deserialize<AppSettings>(json);
|
||||||
|
jsonObj.IpAddresses = ipAddresses;
|
||||||
|
json = JsonSerializer.Serialize(jsonObj, new JsonSerializerOptions { WriteIndented = true });
|
||||||
|
File.WriteAllText(filePath, json);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
/* Swallow Exception */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetIpAddresses(string filePath)
|
||||||
|
{
|
||||||
|
if (new OsInfo(Array.Empty<IOsVersionAdapter>()).IsDocker)
|
||||||
|
{
|
||||||
|
return DefaultIPAddresses;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var json = File.ReadAllText(filePath);
|
||||||
|
var jsonObj = JsonSerializer.Deserialize<dynamic>(json);
|
||||||
|
const string key = "IpAddresses";
|
||||||
|
|
||||||
|
if (jsonObj.TryGetProperty(key, out JsonElement tokenElement))
|
||||||
|
{
|
||||||
|
return tokenElement.GetString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Error writing app settings: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefaultIPAddresses;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private class AppSettings
|
||||||
|
{
|
||||||
|
public string TokenKey { get; set; }
|
||||||
|
public int Port { get; set; }
|
||||||
|
public string IpAddresses { get; set; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ export interface ServerSettings {
|
|||||||
taskBackup: string;
|
taskBackup: string;
|
||||||
loggingLevel: string;
|
loggingLevel: string;
|
||||||
port: number;
|
port: number;
|
||||||
|
ipAddresses: string;
|
||||||
allowStatCollection: boolean;
|
allowStatCollection: boolean;
|
||||||
enableOpds: boolean;
|
enableOpds: boolean;
|
||||||
baseUrl: string;
|
baseUrl: string;
|
||||||
|
@ -34,14 +34,32 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-0 mb-2">
|
<div class="row g-0 mb-2">
|
||||||
<div class="col-md-3 col-sm-12 pe-2">
|
<div class="col-md-8 col-sm-12 pe-2">
|
||||||
|
<label for="settings-ipaddresses" class="form-label">IP Addresses</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="ipAddressesTooltip" role="button" tabindex="0"></i>
|
||||||
|
<ng-template #ipAddressesTooltip>This does not apply to Docker</ng-template>
|
||||||
|
<span class="visually-hidden" id="settings-ipaddresses-help">Comma separated list of Ip addresses the server listens on. This is fixed if you are running on Docker. Requires restart to take effect.</span>
|
||||||
|
<div class="input-group">
|
||||||
|
<input id="settings-ipaddresses" aria-describedby="settings-ipaddresses-help" class="form-control" formControlName="ipAddresses" type="text"
|
||||||
|
[class.is-invalid]="settingsForm.get('ipAddresses')?.invalid && settingsForm.get('ipAddresses')?.touched">
|
||||||
|
<button class="btn btn-outline-secondary" (click)="resetIPAddresses()">Reset</button>
|
||||||
|
</div>
|
||||||
|
<div id="ipaddresses-validations" class="invalid-feedback" *ngIf="settingsForm.dirty || settingsForm.touched">
|
||||||
|
<div *ngIf="settingsForm.get('ipAddresses')?.errors?.pattern">
|
||||||
|
IP addresses can only contain valid IPv4 or IPv6 addresses
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4 col-sm-12 pe-2">
|
||||||
<label for="settings-port" class="form-label">Port</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="portTooltip" role="button" tabindex="0"></i>
|
<label for="settings-port" class="form-label">Port</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="portTooltip" role="button" tabindex="0"></i>
|
||||||
<ng-template #portTooltip>Port the server listens on. This is fixed if you are running on Docker. Requires restart to take effect.</ng-template>
|
<ng-template #portTooltip>Port the server listens on. This is fixed if you are running on Docker. Requires restart to take effect.</ng-template>
|
||||||
<span class="visually-hidden" id="settings-port-help">Port the server listens on. This is fixed if you are running on Docker. Requires restart to take effect.</span>
|
<span class="visually-hidden" id="settings-port-help">Port the server listens on. This is fixed if you are running on Docker. Requires restart to take effect.</span>
|
||||||
<input id="settings-port" aria-describedby="settings-port-help" class="form-control" formControlName="port" type="number" step="1" min="1" onkeypress="return event.charCode >= 48 && event.charCode <= 57">
|
<input id="settings-port" aria-describedby="settings-port-help" class="form-control" formControlName="port" type="number" step="1" min="1" onkeypress="return event.charCode >= 48 && event.charCode <= 57">
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3 col-sm-12 pe-2">
|
<div class="row g-0 mb-2">
|
||||||
|
<div class="col-md-4 col-sm-12 pe-2">
|
||||||
<label for="backup-tasks" class="form-label">Days of Backups</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="backupTasksTooltip" role="button" tabindex="0"></i>
|
<label for="backup-tasks" class="form-label">Days of Backups</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="backupTasksTooltip" role="button" tabindex="0"></i>
|
||||||
<ng-template #backupTasksTooltip>The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
<ng-template #backupTasksTooltip>The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
||||||
<span class="visually-hidden" id="backup-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
<span class="visually-hidden" id="backup-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
||||||
@ -61,7 +79,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3 col-sm-12 pe-2">
|
<div class="col-md-4 col-sm-12 pe-2">
|
||||||
<label for="log-tasks" class="form-label">Days of Logs</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="logTasksTooltip" role="button" tabindex="0"></i>
|
<label for="log-tasks" class="form-label">Days of Logs</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="logTasksTooltip" role="button" tabindex="0"></i>
|
||||||
<ng-template #logTasksTooltip>The number of logs to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
<ng-template #logTasksTooltip>The number of logs to maintain. Default is 30, minumum is 1, maximum is 30.</ng-template>
|
||||||
<span class="visually-hidden" id="log-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
<span class="visually-hidden" id="log-tasks-help">The number of backups to maintain. Default is 30, minumum is 1, maximum is 30.</span>
|
||||||
@ -81,7 +99,7 @@
|
|||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-md-3 col-sm-12">
|
<div class="col-md-4 col-sm-12">
|
||||||
<label for="logging-level-port" class="form-label">Logging Level</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="loggingLevelTooltip" role="button" tabindex="0"></i>
|
<label for="logging-level-port" class="form-label">Logging Level</label> <i class="fa fa-info-circle" placement="right" [ngbTooltip]="loggingLevelTooltip" role="button" tabindex="0"></i>
|
||||||
<ng-template #loggingLevelTooltip>Use debug to help identify issues. Debug can eat up a lot of disk space.</ng-template>
|
<ng-template #loggingLevelTooltip>Use debug to help identify issues. Debug can eat up a lot of disk space.</ng-template>
|
||||||
<span class="visually-hidden" id="logging-level-port-help">Port the server listens on.</span>
|
<span class="visually-hidden" id="logging-level-port-help">Port the server listens on.</span>
|
||||||
|
@ -8,6 +8,7 @@ import { SettingsService } from '../settings.service';
|
|||||||
import { DirectoryPickerComponent, DirectoryPickerResult } from '../_modals/directory-picker/directory-picker.component';
|
import { DirectoryPickerComponent, DirectoryPickerResult } from '../_modals/directory-picker/directory-picker.component';
|
||||||
import { ServerSettings } from '../_models/server-settings';
|
import { ServerSettings } from '../_models/server-settings';
|
||||||
|
|
||||||
|
const ValidIpAddress = /^(\s*((([12]?\d{1,2}\.){3}[12]?\d{1,2})|(([\da-f]{0,4}\:){0,7}([\da-f]{0,4})))\s*\,)*\s*((([12]?\d{1,2}\.){3}[12]?\d{1,2})|(([\da-f]{0,4}\:){0,7}([\da-f]{0,4})))\s*$/i;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-manage-settings',
|
selector: 'app-manage-settings',
|
||||||
@ -25,7 +26,7 @@ export class ManageSettingsComponent implements OnInit {
|
|||||||
return TagBadgeCursor;
|
return TagBadgeCursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(private settingsService: SettingsService, private toastr: ToastrService,
|
constructor(private settingsService: SettingsService, private toastr: ToastrService,
|
||||||
private modalService: NgbModal) { }
|
private modalService: NgbModal) { }
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@ -41,6 +42,7 @@ export class ManageSettingsComponent implements OnInit {
|
|||||||
this.settingsForm.addControl('bookmarksDirectory', new FormControl(this.serverSettings.bookmarksDirectory, [Validators.required]));
|
this.settingsForm.addControl('bookmarksDirectory', new FormControl(this.serverSettings.bookmarksDirectory, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
this.settingsForm.addControl('taskScan', new FormControl(this.serverSettings.taskScan, [Validators.required]));
|
||||||
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
this.settingsForm.addControl('taskBackup', new FormControl(this.serverSettings.taskBackup, [Validators.required]));
|
||||||
|
this.settingsForm.addControl('ipAddresses', new FormControl(this.serverSettings.ipAddresses, [Validators.required, Validators.pattern(ValidIpAddress)]));
|
||||||
this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required]));
|
this.settingsForm.addControl('port', new FormControl(this.serverSettings.port, [Validators.required]));
|
||||||
this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
this.settingsForm.addControl('loggingLevel', new FormControl(this.serverSettings.loggingLevel, [Validators.required]));
|
||||||
this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
this.settingsForm.addControl('allowStatCollection', new FormControl(this.serverSettings.allowStatCollection, [Validators.required]));
|
||||||
@ -60,6 +62,7 @@ export class ManageSettingsComponent implements OnInit {
|
|||||||
this.settingsForm.get('bookmarksDirectory')?.setValue(this.serverSettings.bookmarksDirectory);
|
this.settingsForm.get('bookmarksDirectory')?.setValue(this.serverSettings.bookmarksDirectory);
|
||||||
this.settingsForm.get('scanTask')?.setValue(this.serverSettings.taskScan);
|
this.settingsForm.get('scanTask')?.setValue(this.serverSettings.taskScan);
|
||||||
this.settingsForm.get('taskBackup')?.setValue(this.serverSettings.taskBackup);
|
this.settingsForm.get('taskBackup')?.setValue(this.serverSettings.taskBackup);
|
||||||
|
this.settingsForm.get('ipAddresses')?.setValue(this.serverSettings.ipAddresses);
|
||||||
this.settingsForm.get('port')?.setValue(this.serverSettings.port);
|
this.settingsForm.get('port')?.setValue(this.serverSettings.port);
|
||||||
this.settingsForm.get('loggingLevel')?.setValue(this.serverSettings.loggingLevel);
|
this.settingsForm.get('loggingLevel')?.setValue(this.serverSettings.loggingLevel);
|
||||||
this.settingsForm.get('allowStatCollection')?.setValue(this.serverSettings.allowStatCollection);
|
this.settingsForm.get('allowStatCollection')?.setValue(this.serverSettings.allowStatCollection);
|
||||||
@ -96,6 +99,16 @@ export class ManageSettingsComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetIPAddresses() {
|
||||||
|
this.settingsService.resetIPAddressesSettings().pipe(take(1)).subscribe(async (settings: ServerSettings) => {
|
||||||
|
this.serverSettings.ipAddresses = settings.ipAddresses;
|
||||||
|
this.settingsForm.get("ipAddresses")?.setValue(this.serverSettings.ipAddresses);
|
||||||
|
this.toastr.success('IP Addresses Reset');
|
||||||
|
}, (err: any) => {
|
||||||
|
console.error('error: ', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
openDirectoryChooser(existingDirectory: string, formControl: string) {
|
openDirectoryChooser(existingDirectory: string, formControl: string) {
|
||||||
const modalRef = this.modalService.open(DirectoryPickerComponent, { scrollable: true, size: 'lg' });
|
const modalRef = this.modalService.open(DirectoryPickerComponent, { scrollable: true, size: 'lg' });
|
||||||
modalRef.componentInstance.startingFolder = existingDirectory || '';
|
modalRef.componentInstance.startingFolder = existingDirectory || '';
|
||||||
|
@ -33,6 +33,10 @@ export class SettingsService {
|
|||||||
return this.http.post<ServerSettings>(this.baseUrl + 'settings/reset', {});
|
return this.http.post<ServerSettings>(this.baseUrl + 'settings/reset', {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resetIPAddressesSettings() {
|
||||||
|
return this.http.post<ServerSettings>(this.baseUrl + 'settings/reset-ip-addresses', {});
|
||||||
|
}
|
||||||
|
|
||||||
resetEmailServerSettings() {
|
resetEmailServerSettings() {
|
||||||
return this.http.post<ServerSettings>(this.baseUrl + 'settings/reset-email-url', {});
|
return this.http.post<ServerSettings>(this.baseUrl + 'settings/reset-email-url', {});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user