Implemented option to enable folder-status service (disabled by default).

This commit is contained in:
Kenneth Skovhede
2026-02-19 17:30:57 +01:00
parent 0a702f48ff
commit 01130f4cd5
6 changed files with 26 additions and 21 deletions
@@ -82,6 +82,7 @@ namespace Duplicati.Server.Database
public const string REMOTE_CONTROL_STORAGE_API_ID = "remote-control-storage-api-id";
public const string REMOTE_CONTROL_STORAGE_API_KEY = "remote-control-storage-api-key";
public const string REMOTE_CONTROL_STORAGE_ENDPOINT_URL = "remote-control-storage-endpoint-url";
public const string ENABLE_FOLDER_STATUS_SERVICE = "enable-folder-status-service";
}
private readonly Dictionary<string, string?> settings;
@@ -708,6 +709,12 @@ namespace Duplicati.Server.Database
set => SetAndSaveSetting(CONST.REMOTE_CONTROL_STORAGE_ENDPOINT_URL, value);
}
public bool EnableFolderStatusService
{
get => Utility.ParseBool(settings[CONST.ENABLE_FOLDER_STATUS_SERVICE], false);
set => SetAndSaveSetting(CONST.ENABLE_FOLDER_STATUS_SERVICE, value.ToString());
}
public string? BackupListSortOrder
{
get
+1
View File
@@ -80,6 +80,7 @@ Error message: {0}", error); }
public static string WebserverPreAuthTokensDescription { get { return LC.L(@"A list of pre-authenticated tokens, separated with semicolons. These can be used in cases where the authentication is provided by a proxy. Each token must be at least 10 characters and not contain extended characters. The token must be provided by setting the header on each request to contain: Authentication: PreAuth <token>"); } }
public static string WebserverDisableApiExtensionsDescription { get { return LC.L(@"Disable the API extensions reported by the server. This will not disable the functionality, but will not report the extensions in the API responses. Use this option to degrade the server to a more basic API."); } }
public static string WebserverTokenDurationDescription { get { return LC.L(@"The duration of the refresh tokens issued by the server. This value indicates how much time can pass without activity before the user is asked to log in again. The value must be greater than zero and is capped at 30 days."); } }
public static string WebserverEnableFolderStatusServiceDescription { get { return LC.L(@"Enable the folder status service for showing overlay icons in the file explorer"); } }
public static string DisabledbencryptionLong { get { return LC.L(@"Use this option to disable database encryption of sensitive fields"); } }
public static string DisabledbencryptionShort { get { return LC.L(@"Disable database encryption"); } }
public static string LogwindowseventlogLong { get { return LC.L(@"Use this option to log to the Windows event log. The provided name is in the format Log:Source. If no log name is provided, ""Duplicati 2"" is used."); } }
+5 -1
View File
@@ -572,13 +572,16 @@ namespace Duplicati.Server
connection.ApplicationSettings.EnableForeverTokens();
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_DISABLE_SIGNIN_TOKENS))
connection.ApplicationSettings.DisableSigninTokens = Library.Utility.Utility.ParseBool(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_DISABLE_SIGNIN_TOKENS], true);
connection.ApplicationSettings.DisableSigninTokens = Library.Utility.Utility.ParseBoolOption(commandlineOptions, WebServerLoader.OPTION_WEBSERVICE_DISABLE_SIGNIN_TOKENS);
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_DISABLEAPIEXTENSIONS))
connection.ApplicationSettings.DisabledAPIExtensions = commandlineOptions.GetValueOrDefault(WebServerLoader.OPTION_WEBSERVICE_DISABLEAPIEXTENSIONS)?
.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.ToHashSet(StringComparer.OrdinalIgnoreCase) ?? [];
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_ENABLE_FOLDER_STATUS_SERVICE))
connection.ApplicationSettings.EnableFolderStatusService = Library.Utility.Utility.ParseBoolOption(commandlineOptions, WebServerLoader.OPTION_WEBSERVICE_ENABLE_FOLDER_STATUS_SERVICE);
if (commandlineOptions.ContainsKey(WebServerLoader.OPTION_WEBSERVICE_PASSWORD))
connection.ApplicationSettings.SetWebserverPassword(commandlineOptions[WebServerLoader.OPTION_WEBSERVICE_PASSWORD]);
@@ -1149,6 +1152,7 @@ namespace Duplicati.Server
new CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_CORS_ORIGINS, CommandLineArgument.ArgumentType.Path, Strings.Program.WebserverCorsOriginsDescription, Strings.Program.WebserverCorsOriginsDescription, WebServerLoader.DEFAULT_OPTION_SPAPATHS),
new CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_PRE_AUTH_TOKENS, CommandLineArgument.ArgumentType.String, Strings.Program.WebserverPreAuthTokensDescription, Strings.Program.WebserverPreAuthTokensDescription),
new CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_TOKENDURATION, CommandLineArgument.ArgumentType.Timespan, Strings.Program.WebserverTokenDurationDescription, Strings.Program.WebserverTokenDurationDescription, WebServerLoader.DEFAULT_OPTION_TOKENDURATION),
new CommandLineArgument(WebServerLoader.OPTION_WEBSERVICE_ENABLE_FOLDER_STATUS_SERVICE, CommandLineArgument.ArgumentType.Boolean, Strings.Program.WebserverEnableFolderStatusServiceDescription, Strings.Program.WebserverEnableFolderStatusServiceDescription),
new CommandLineArgument(PING_PONG_KEEPALIVE_OPTION, CommandLineArgument.ArgumentType.Boolean, Strings.Program.PingpongkeepaliveShort, Strings.Program.PingpongkeepaliveLong),
new CommandLineArgument(DISABLE_UPDATE_CHECK_OPTION, CommandLineArgument.ArgumentType.Boolean, Strings.Program.DisableupdatecheckShort, Strings.Program.DisableupdatecheckLong),
new CommandLineArgument(LOG_RETENTION_OPTION, CommandLineArgument.ArgumentType.Timespan, Strings.Program.LogretentionShort, Strings.Program.LogretentionLong, DEFAULT_LOG_RETENTION),
+5
View File
@@ -156,6 +156,11 @@ public static class WebServerLoader
/// </summary>
public const string OPTION_WEBSERVICE_DISABLEAPIEXTENSIONS = "webservice-disable-api-extensions";
/// <summary>
/// Enables the folder status service for the TrayIcon
/// </summary>
public const string OPTION_WEBSERVICE_ENABLE_FOLDER_STATUS_SERVICE = "webservice-enable-folder-status-service";
/// <summary>
/// The default listening interface
/// </summary>
@@ -1,23 +1,3 @@
<!-- Copyright (C) 2025, The Duplicati Team -->
<!-- https://duplicati.com, hello@duplicati.com -->
<!-- -->
<!-- Permission is hereby granted, free of charge, to any person obtaining a -->
<!-- copy of this software and associated documentation files (the "Software"), -->
<!-- to deal in the Software without restriction, including without limitation -->
<!-- the rights to use, copy, modify, merge, publish, distribute, sublicense, -->
<!-- and/or sell copies of the Software, and to permit persons to whom the -->
<!-- Software is furnished to do so, subject to the following conditions: -->
<!-- -->
<!-- The above copyright notice and this permission notice shall be included in -->
<!-- all copies or substantial portions of the Software. -->
<!-- -->
<!-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -->
<!-- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -->
<!-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -->
<!-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -->
<!-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -->
<!-- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -->
<!-- DEALINGS IN THE SOFTWARE. -->
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
@@ -23,6 +23,7 @@ using Duplicati.Server.Database;
using Duplicati.Server.Serialization.Interface;
using Duplicati.WebserverCore.Abstractions;
using Duplicati.WebserverCore.Dto;
using Duplicati.WebserverCore.Exceptions;
namespace Duplicati.WebserverCore.Services;
@@ -51,7 +52,11 @@ public class FolderStatusService : IFolderStatusService
/// </summary>
public IEnumerable<FolderStatusDto> GetAllFolderStatuses()
{
if (!_connection.ApplicationSettings.EnableFolderStatusService)
throw new ServiceUnavailableException("Folder status service is disabled");
var results = new List<FolderStatusDto>();
var activeBackupIds = GetActiveBackupIds();
var backups = _connection.Backups;
@@ -87,6 +92,9 @@ public class FolderStatusService : IFolderStatusService
/// </summary>
public FolderStatusDto GetFolderStatus(string path)
{
if (!_connection.ApplicationSettings.EnableFolderStatusService)
throw new ServiceUnavailableException("Folder status service is disabled");
if (string.IsNullOrEmpty(path))
{
return new FolderStatusDto