diff --git a/Duplicati.Library.RestAPI/BackupImportExportHandler.cs b/Duplicati.Library.RestAPI/BackupImportExportHandler.cs
index 6c11b0b46..c1f6b569c 100644
--- a/Duplicati.Library.RestAPI/BackupImportExportHandler.cs
+++ b/Duplicati.Library.RestAPI/BackupImportExportHandler.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using Duplicati.Server.Database;
using Duplicati.Server.Serialization;
using Duplicati.Server.Serialization.Interface;
@@ -14,9 +15,9 @@ public static class BackupImportExportHandler
backup.SanitizeTargetUrl();
}
- public static byte[] ExportToJSON(IBackup backup, string passphrase)
+ public static byte[] ExportToJSON(Connection connection, IBackup backup, string passphrase)
{
- Server.Serializable.ImportExportStructure ipx = FIXMEGlobal.DataConnection.PrepareBackupForExport(backup);
+ Server.Serializable.ImportExportStructure ipx = connection.PrepareBackupForExport(backup);
byte[] data;
using (var ms = new System.IO.MemoryStream())
diff --git a/Duplicati.Library.RestAPI/EventPollNotify.cs b/Duplicati.Library.RestAPI/EventPollNotify.cs
index 777dc4a1e..4c32f1943 100644
--- a/Duplicati.Library.RestAPI/EventPollNotify.cs
+++ b/Duplicati.Library.RestAPI/EventPollNotify.cs
@@ -1,7 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
namespace Duplicati.Server
{
diff --git a/Duplicati.Library.RestAPI/FIXMEGlobal.cs b/Duplicati.Library.RestAPI/FIXMEGlobal.cs
index 730b5c79e..b034f8f4a 100644
--- a/Duplicati.Library.RestAPI/FIXMEGlobal.cs
+++ b/Duplicati.Library.RestAPI/FIXMEGlobal.cs
@@ -27,11 +27,6 @@ namespace Duplicati.Library.RestAPI
///
public static Server.Database.Connection DataConnection;
- ///
- /// The controller interface for pause/resume and throttle options
- ///
- public static LiveControls LiveControl => Provider.GetRequiredService();
-
///
/// A delegate method for creating a copy of the current progress state
///
diff --git a/Duplicati.Library.RestAPI/Serializable/ServerStatus.cs b/Duplicati.Library.RestAPI/Serializable/ServerStatus.cs
index df2a8f6e6..76f5f3ec5 100644
--- a/Duplicati.Library.RestAPI/Serializable/ServerStatus.cs
+++ b/Duplicati.Library.RestAPI/Serializable/ServerStatus.cs
@@ -29,21 +29,21 @@ namespace Duplicati.Server.Serializable
///
/// This class collects all reportable status properties into a single class that can be exported as JSON
///
- public class ServerStatus : Duplicati.Server.Serialization.Interface.IServerStatus
+ public class ServerStatus(LiveControls liveControls) : Duplicati.Server.Serialization.Interface.IServerStatus
{
public LiveControlState ProgramState
{
- get { return EnumConverter.Convert(FIXMEGlobal.LiveControl.State); }
+ get { return EnumConverter.Convert(liveControls.State); }
}
- public string UpdatedVersion
- {
- get
- {
+ public string UpdatedVersion
+ {
+ get
+ {
var u = FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion;
if (u == null)
return null;
-
+
Version v;
if (!Version.TryParse(u.Version, out v))
return null;
@@ -51,7 +51,7 @@ namespace Duplicati.Server.Serializable
if (v <= System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
return null;
- return u.Displayname;
+ return u.Displayname;
}
}
@@ -64,8 +64,8 @@ namespace Duplicati.Server.Serializable
public Tuple ActiveTask
{
- get
- {
+ get
+ {
var t = FIXMEGlobal.WorkThread.CurrentTask;
if (t == null)
return null;
@@ -85,18 +85,18 @@ namespace Duplicati.Server.Serializable
{
return (
from n in FIXMEGlobal.Scheduler.Schedule
- let backupid = (from t in n.Value.Tags
- where t != null && t.StartsWith("ID=", StringComparison.Ordinal)
- select t.Substring("ID=".Length)).FirstOrDefault()
- where !string.IsNullOrWhiteSpace(backupid)
- select new Tuple(backupid, n.Key)
+ let backupid = (from t in n.Value.Tags
+ where t != null && t.StartsWith("ID=", StringComparison.Ordinal)
+ select t.Substring("ID=".Length)).FirstOrDefault()
+ where !string.IsNullOrWhiteSpace(backupid)
+ select new Tuple(backupid, n.Key)
).ToList();
}
}
-
+
public bool HasWarning { get { return FIXMEGlobal.DataConnection.ApplicationSettings.UnackedWarning; } }
public bool HasError { get { return FIXMEGlobal.DataConnection.ApplicationSettings.UnackedError; } }
-
+
public SuggestedStatusIcon SuggestedStatusIcon
{
get
@@ -105,12 +105,12 @@ namespace Duplicati.Server.Serializable
{
if (this.ProgramState == LiveControlState.Paused)
return SuggestedStatusIcon.Paused;
-
+
if (this.HasError)
return SuggestedStatusIcon.ReadyError;
if (this.HasWarning)
return SuggestedStatusIcon.ReadyWarning;
-
+
return SuggestedStatusIcon.Ready;
}
else
@@ -123,18 +123,18 @@ namespace Duplicati.Server.Serializable
}
}
- public DateTime EstimatedPauseEnd
+ public DateTime EstimatedPauseEnd
{
- get
- {
- return FIXMEGlobal.LiveControl.EstimatedPauseEnd;
+ get
+ {
+ return liveControls.EstimatedPauseEnd;
}
}
private long m_lastEventID = FIXMEGlobal.StatusEventNotifyer.EventNo;
- public long LastEventID
- {
+ public long LastEventID
+ {
get { return m_lastEventID; }
set { m_lastEventID = value; }
}
diff --git a/Duplicati.Library.RestAPI/UpdatePollThread.cs b/Duplicati.Library.RestAPI/UpdatePollThread.cs
index 5ed4a3a5b..6f0ce0ac7 100644
--- a/Duplicati.Library.RestAPI/UpdatePollThread.cs
+++ b/Duplicati.Library.RestAPI/UpdatePollThread.cs
@@ -22,7 +22,7 @@
using System;
using System.Linq;
using System.Threading;
-using Duplicati.Library.RestAPI;
+using Duplicati.Server.Database;
using Duplicati.Server.Serialization;
namespace Duplicati.Server
@@ -30,7 +30,7 @@ namespace Duplicati.Server
///
/// The thread that checks on the update server if new versions are available
///
- public class UpdatePollThread
+ public class UpdatePollThread(Connection connection, EventPollNotify eventPollNotify)
{
private Thread m_thread;
private volatile bool m_terminated = false;
@@ -51,7 +51,7 @@ namespace Duplicati.Server
var oldv = m_downloadProgress;
m_downloadProgress = value;
if ((int)(oldv * 100) != (int)(value * 100))
- FIXMEGlobal.StatusEventNotifyer.SignalNewEvent();
+ eventPollNotify.SignalNewEvent();
}
}
@@ -97,12 +97,12 @@ namespace Duplicati.Server
while (!m_terminated)
{
- var nextCheck = FIXMEGlobal.DataConnection.ApplicationSettings.NextUpdateCheck;
+ var nextCheck = connection.ApplicationSettings.NextUpdateCheck;
var maxcheck = TimeSpan.FromDays(7);
try
{
- maxcheck = Library.Utility.Timeparser.ParseTimeSpan(FIXMEGlobal.DataConnection.ApplicationSettings.UpdateCheckInterval);
+ maxcheck = Library.Utility.Timeparser.ParseTimeSpan(connection.ApplicationSettings.UpdateCheckInterval);
}
catch
{
@@ -118,14 +118,14 @@ namespace Duplicati.Server
m_forceCheck = false;
ThreadState = UpdatePollerStates.Checking;
- FIXMEGlobal.StatusEventNotifyer.SignalNewEvent();
+ eventPollNotify.SignalNewEvent();
DateTime started = DateTime.UtcNow;
- FIXMEGlobal.DataConnection.ApplicationSettings.LastUpdateCheck = started;
- nextCheck = FIXMEGlobal.DataConnection.ApplicationSettings.NextUpdateCheck;
+ connection.ApplicationSettings.LastUpdateCheck = started;
+ nextCheck = connection.ApplicationSettings.NextUpdateCheck;
Library.AutoUpdater.ReleaseType rt;
- if (!Enum.TryParse(FIXMEGlobal.DataConnection.ApplicationSettings.UpdateChannel, true, out rt))
+ if (!Enum.TryParse(connection.ApplicationSettings.UpdateChannel, true, out rt))
rt = Duplicati.Library.AutoUpdater.ReleaseType.Unknown;
// Choose the default channel in case we have unknown
@@ -135,7 +135,7 @@ namespace Duplicati.Server
{
var update = Duplicati.Library.AutoUpdater.UpdaterManager.CheckForUpdate(rt);
if (update != null)
- FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion = update;
+ connection.ApplicationSettings.UpdatedVersion = update;
}
catch
{
@@ -144,10 +144,10 @@ namespace Duplicati.Server
// It could be that we have registered an update from a more unstable channel,
// but the user has switched to a more stable channel.
// In that case we discard the old update to avoid offering it.
- if (FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion != null)
+ if (connection.ApplicationSettings.UpdatedVersion != null)
{
Library.AutoUpdater.ReleaseType updatert;
- var updatertstring = FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion.ReleaseType;
+ var updatertstring = connection.ApplicationSettings.UpdatedVersion.ReleaseType;
if (string.Equals(updatertstring, "preview", StringComparison.OrdinalIgnoreCase))
updatertstring = Library.AutoUpdater.ReleaseType.Experimental.ToString();
@@ -158,15 +158,15 @@ namespace Duplicati.Server
updatert = Duplicati.Library.AutoUpdater.ReleaseType.Nightly;
if (updatert > rt)
- FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion = null;
+ connection.ApplicationSettings.UpdatedVersion = null;
}
- var updatedinfo = FIXMEGlobal.DataConnection.ApplicationSettings.UpdatedVersion;
+ var updatedinfo = connection.ApplicationSettings.UpdatedVersion;
if (updatedinfo != null && Duplicati.Library.AutoUpdater.UpdaterManager.TryParseVersion(updatedinfo.Version) > System.Reflection.Assembly.GetExecutingAssembly().GetName().Version)
{
var package = updatedinfo.FindPackage();
- FIXMEGlobal.DataConnection.RegisterNotification(
+ connection.RegisterNotification(
NotificationType.Information,
"Found update",
updatedinfo.Displayname,
@@ -189,7 +189,7 @@ namespace Duplicati.Server
if (ThreadState != UpdatePollerStates.Waiting)
{
ThreadState = UpdatePollerStates.Waiting;
- FIXMEGlobal.StatusEventNotifyer.SignalNewEvent();
+ eventPollNotify.SignalNewEvent();
}
var waitTime = nextCheck - DateTime.UtcNow;
diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs
index d17337701..c9166a7e1 100644
--- a/Duplicati/Server/Program.cs
+++ b/Duplicati/Server/Program.cs
@@ -26,6 +26,7 @@ using System.Threading.Tasks;
using Duplicati.Library.Common;
using Duplicati.Library.Common.IO;
using Duplicati.Library.RestAPI;
+using Duplicati.Server.Database;
using Duplicati.WebserverCore;
using Duplicati.WebserverCore.Abstractions;
using Microsoft.Extensions.DependencyInjection;
@@ -263,7 +264,7 @@ namespace Duplicati.Server
DataConnection.LogError(null, "Error in updater", obj);
};
- DuplicatiWebserver = StartWebServer(commandlineOptions).ConfigureAwait(false).GetAwaiter().GetResult();
+ DuplicatiWebserver = StartWebServer(commandlineOptions, DataConnection).ConfigureAwait(false).GetAwaiter().GetResult();
UpdatePoller.Init();
@@ -325,9 +326,9 @@ namespace Duplicati.Server
return 0;
}
- private static async Task StartWebServer(IReadOnlyDictionary options)
+ private static async Task StartWebServer(IReadOnlyDictionary options, Connection connection)
{
- var server = await WebServerLoader.TryRunServer(options, async parsedOptions =>
+ var server = await WebServerLoader.TryRunServer(options, connection, async parsedOptions =>
{
var mappedSettings = new DuplicatiWebserver.InitSettings(
parsedOptions.WebRoot,
@@ -340,7 +341,7 @@ namespace Duplicati.Server
var server = new DuplicatiWebserver();
- server.InitWebServer(mappedSettings, DataConnection);
+ server.InitWebServer(mappedSettings, connection);
server.Start(mappedSettings);
return server;
}).ConfigureAwait(false);
diff --git a/Duplicati/Server/WebServerLoader.cs b/Duplicati/Server/WebServerLoader.cs
index 83b350a5b..80158f271 100644
--- a/Duplicati/Server/WebServerLoader.cs
+++ b/Duplicati/Server/WebServerLoader.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using Duplicati.Library.RestAPI;
+using Duplicati.Server.Database;
namespace Duplicati.Server;
@@ -93,7 +94,7 @@ public static class WebServerLoader
///
/// A set of options
/// The method to start the server
- public static async Task TryRunServer(IReadOnlyDictionary options, Func> createServer)
+ public static async Task TryRunServer(IReadOnlyDictionary options, Connection connection, Func> createServer)
{
var ports = Enumerable.Empty();
options.TryGetValue(OPTION_PORT, out var portstring);
@@ -109,7 +110,7 @@ public static class WebServerLoader
options.TryGetValue(OPTION_INTERFACE, out var interfacestring);
if (string.IsNullOrWhiteSpace(interfacestring))
- interfacestring = FIXMEGlobal.DataConnection.ApplicationSettings.ServerListenInterface;
+ interfacestring = connection.ApplicationSettings.ServerListenInterface;
if (string.IsNullOrWhiteSpace(interfacestring))
interfacestring = DEFAULT_OPTION_INTERFACE;
@@ -129,7 +130,7 @@ public static class WebServerLoader
{
try
{
- cert = FIXMEGlobal.DataConnection.ApplicationSettings.ServerSSLCertificate;
+ cert = connection.ApplicationSettings.ServerSSLCertificate;
}
catch (Exception ex)
{
@@ -138,7 +139,7 @@ public static class WebServerLoader
}
else if (certificateFile.Length == 0)
{
- FIXMEGlobal.DataConnection.ApplicationSettings.ServerSSLCertificate = null;
+ connection.ApplicationSettings.ServerSSLCertificate = null;
}
else
{
@@ -197,11 +198,11 @@ public static class WebServerLoader
settings = settings with { Port = p };
var server = await createServer(settings);
- if (interfacestring != FIXMEGlobal.DataConnection.ApplicationSettings.ServerListenInterface)
- FIXMEGlobal.DataConnection.ApplicationSettings.ServerListenInterface = interfacestring;
+ if (interfacestring != connection.ApplicationSettings.ServerListenInterface)
+ connection.ApplicationSettings.ServerListenInterface = interfacestring;
- if (certValid && cert != FIXMEGlobal.DataConnection.ApplicationSettings.ServerSSLCertificate)
- FIXMEGlobal.DataConnection.ApplicationSettings.ServerSSLCertificate = cert;
+ if (certValid && cert != connection.ApplicationSettings.ServerSSLCertificate)
+ connection.ApplicationSettings.ServerSSLCertificate = cert;
Duplicati.Library.Logging.Log.WriteInformationMessage(LOGTAG, "ServerListening", Duplicati.Server.Strings.Server.StartedServer(listenInterface.ToString(), p));
diff --git a/Duplicati/UnitTest/ImportExportTests.cs b/Duplicati/UnitTest/ImportExportTests.cs
index 590ad88ac..23b86a0e0 100644
--- a/Duplicati/UnitTest/ImportExportTests.cs
+++ b/Duplicati/UnitTest/ImportExportTests.cs
@@ -107,7 +107,7 @@ namespace Duplicati.UnitTest
byte[] jsonByteArray;
using (Program.DataConnection = Program.GetDatabaseConnection(advancedOptions))
{
- jsonByteArray = BackupImportExportHandler.ExportToJSON(backup, null);
+ jsonByteArray = BackupImportExportHandler.ExportToJSON(Program.DataConnection, backup, null);
}
// The username should not have the '%40' converted to '@' since the import code
@@ -131,14 +131,14 @@ namespace Duplicati.UnitTest
{
// Unencrypted file, don't import metadata.
string unencryptedWithoutMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName());
- File.WriteAllBytes(unencryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(this.CreateBackup("unencrypted without metadata", "user", "password", metadata), null));
+ File.WriteAllBytes(unencryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("unencrypted without metadata", "user", "password", metadata), null));
BackupImportExportHandler.ImportBackup(unencryptedWithoutMetadata, false, () => null, advancedOptions);
Assert.AreEqual(1, Program.DataConnection.Backups.Length);
Assert.AreEqual(0, Program.DataConnection.Backups[0].Metadata.Count);
// Unencrypted file, import metadata.
string unencryptedWithMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName());
- File.WriteAllBytes(unencryptedWithMetadata, BackupImportExportHandler.ExportToJSON(this.CreateBackup("unencrypted with metadata", "user", "password", metadata), null));
+ File.WriteAllBytes(unencryptedWithMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("unencrypted with metadata", "user", "password", metadata), null));
BackupImportExportHandler.ImportBackup(unencryptedWithMetadata, true, () => null, advancedOptions);
Assert.AreEqual(2, Program.DataConnection.Backups.Length);
Assert.AreEqual(metadata.Count, Program.DataConnection.Backups[1].Metadata.Count);
@@ -146,14 +146,14 @@ namespace Duplicati.UnitTest
// Encrypted file, don't import metadata.
string encryptedWithoutMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName());
string passphrase = "abcde";
- File.WriteAllBytes(encryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(this.CreateBackup("encrypted without metadata", "user", "password", metadata), passphrase));
+ File.WriteAllBytes(encryptedWithoutMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("encrypted without metadata", "user", "password", metadata), passphrase));
BackupImportExportHandler.ImportBackup(encryptedWithoutMetadata, false, () => passphrase, advancedOptions);
Assert.AreEqual(3, Program.DataConnection.Backups.Length);
Assert.AreEqual(0, Program.DataConnection.Backups[2].Metadata.Count);
// Encrypted file, import metadata.
string encryptedWithMetadata = Path.Combine(this.serverDatafolder, Path.GetRandomFileName());
- File.WriteAllBytes(encryptedWithMetadata, BackupImportExportHandler.ExportToJSON(this.CreateBackup("encrypted with metadata", "user", "password", metadata), passphrase));
+ File.WriteAllBytes(encryptedWithMetadata, BackupImportExportHandler.ExportToJSON(Program.DataConnection, this.CreateBackup("encrypted with metadata", "user", "password", metadata), passphrase));
BackupImportExportHandler.ImportBackup(encryptedWithMetadata, true, () => passphrase, advancedOptions);
Assert.AreEqual(4, Program.DataConnection.Backups.Length);
Assert.AreEqual(metadata.Count, Program.DataConnection.Backups[3].Metadata.Count);
diff --git a/Duplicati/WebserverCore/DuplicatiWebserver.cs b/Duplicati/WebserverCore/DuplicatiWebserver.cs
index 75f146b29..4d675398f 100644
--- a/Duplicati/WebserverCore/DuplicatiWebserver.cs
+++ b/Duplicati/WebserverCore/DuplicatiWebserver.cs
@@ -78,8 +78,6 @@ public partial class DuplicatiWebserver
.AddHostedService()
.AddEndpointsApiExplorer()
.AddSwaggerGen()
- .AddSingleton(connection)
- .AddSingleton()
.AddHttpContextAccessor()
.AddAntiforgery(options =>
{
@@ -88,7 +86,7 @@ public partial class DuplicatiWebserver
options.FormFieldName = "x-xsrf-token";
});
- builder.Services.AddDuplicati();
+ builder.Services.AddDuplicati(connection);
Configuration = builder.Configuration;
App = builder.Build();
diff --git a/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPutDelete.cs b/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPutDelete.cs
index 4b9ed7280..ae73f2cb0 100644
--- a/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPutDelete.cs
+++ b/Duplicati/WebserverCore/Endpoints/V1/Backup/BackupPutDelete.cs
@@ -1,4 +1,5 @@
using System.Text.Json;
+using Duplicati.Library.IO;
using Duplicati.Library.RestAPI;
using Duplicati.Library.RestAPI.Abstractions;
using Duplicati.Server;
@@ -33,9 +34,9 @@ public class BackupPutDelete : IEndpointV1
});
- group.MapDelete("/backup/{id}", ([FromServices] Connection connection, [FromServices] IWorkerThreadsManager workerThreadsManager, [FromServices] ICaptchaProvider captchaProvider, [FromServices] IHttpContextAccessor httpContextAccessor, [FromRoute] string id, [FromQuery] bool? delete_remote_files, [FromQuery] bool? delete_local_db, [FromQuery] string captcha_token, [FromQuery] string captcha_answer, [FromQuery] bool force) =>
+ group.MapDelete("/backup/{id}", ([FromServices] Connection connection, [FromServices] IWorkerThreadsManager workerThreadsManager, [FromServices] ICaptchaProvider captchaProvider, [FromServices] LiveControls liveControls, [FromServices] IHttpContextAccessor httpContextAccessor, [FromRoute] string id, [FromQuery] bool? delete_remote_files, [FromQuery] bool? delete_local_db, [FromQuery] string captcha_token, [FromQuery] string captcha_answer, [FromQuery] bool force) =>
{
- var res = ExecuteDelete(GetBackup(connection, id), connection, workerThreadsManager, captchaProvider, delete_remote_files ?? false, delete_local_db, captcha_token, captcha_answer, force);
+ var res = ExecuteDelete(GetBackup(connection, id), connection, workerThreadsManager, captchaProvider, liveControls, delete_remote_files ?? false, delete_local_db, captcha_token, captcha_answer, force);
if (res.Status != "OK" && httpContextAccessor.HttpContext != null)
httpContextAccessor.HttpContext.Response.StatusCode = 500;
return res;
@@ -127,7 +128,7 @@ public class BackupPutDelete : IEndpointV1
}
}
- private static Dto.DeleteBackupOutputDto ExecuteDelete(IBackup backup, Connection connection, IWorkerThreadsManager workerThreadsManager, ICaptchaProvider captchaProvider, bool delete_remote_files, bool? delete_local_db, string captcha_token, string captcha_answer, bool force)
+ private static Dto.DeleteBackupOutputDto ExecuteDelete(IBackup backup, Connection connection, IWorkerThreadsManager workerThreadsManager, ICaptchaProvider captchaProvider, LiveControls liveControls, bool delete_remote_files, bool? delete_local_db, string captcha_token, string captcha_answer, bool force)
{
if (delete_remote_files)
{
@@ -151,8 +152,8 @@ public class BackupPutDelete : IEndpointV1
return new Dto.DeleteBackupOutputDto("failed", "backup-in-progress", nt?.TaskID);
- bool hasPaused = FIXMEGlobal.LiveControl.State == LiveControls.LiveControlState.Paused;
- FIXMEGlobal.LiveControl.Pause();
+ bool hasPaused = liveControls.State == LiveControls.LiveControlState.Paused;
+ liveControls.Pause();
for (int i = 0; i < 10; i++)
if (workerThreadsManager.WorkerThread.Active)
@@ -172,14 +173,14 @@ public class BackupPutDelete : IEndpointV1
if (backup.Equals(t == null ? null : t.Backup))
{
if (hasPaused)
- FIXMEGlobal.LiveControl.Resume();
+ liveControls.Resume();
return new Dto.DeleteBackupOutputDto("failed", "backup-unstoppable", t?.TaskID);
}
}
if (hasPaused)
- FIXMEGlobal.LiveControl.Resume();
+ liveControls.Resume();
}
}
catch (Exception ex)
diff --git a/Duplicati/WebserverCore/Endpoints/V1/ServerState.cs b/Duplicati/WebserverCore/Endpoints/V1/ServerState.cs
index f67509d63..93f7794d3 100644
--- a/Duplicati/WebserverCore/Endpoints/V1/ServerState.cs
+++ b/Duplicati/WebserverCore/Endpoints/V1/ServerState.cs
@@ -1,4 +1,5 @@
using Duplicati.Library.RestAPI;
+using Duplicati.Server;
using Duplicati.WebserverCore.Abstractions;
using Duplicati.WebserverCore.Exceptions;
using Microsoft.AspNetCore.Mvc;
@@ -12,8 +13,8 @@ public class ServerState : IEndpointV1
group.MapGet("/serverstate", ([FromQuery] long? lastEventId, [FromQuery] bool? longpoll, string? duration, [FromServices] IStatusService statusService)
=> Execute(lastEventId, longpoll, duration, statusService));
- group.MapPost("/serverstate/pause", ([FromServices] IStatusService statusService, [FromQuery] string? duration) => ExecutePause(statusService, duration));
- group.MapPost("/serverstate/resume", ([FromServices] IStatusService statusService) => ExecuteResume(statusService));
+ group.MapPost("/serverstate/pause", ([FromServices] IStatusService statusService, [FromServices] LiveControls liveControls, [FromQuery] string? duration) => ExecutePause(statusService, liveControls, duration));
+ group.MapPost("/serverstate/resume", ([FromServices] IStatusService statusService, [FromServices] LiveControls liveControls) => ExecuteResume(statusService, liveControls));
}
private static Dto.ServerStatusDto Execute(long? lastEventId, bool? longpoll, string? duration, IStatusService statusService)
@@ -42,7 +43,7 @@ public class ServerState : IEndpointV1
return status;
}
- private static void ExecutePause(IStatusService statusService, string? duration)
+ private static void ExecutePause(IStatusService statusService, LiveControls liveControls, string? duration)
{
var ts = TimeSpan.Zero;
if (duration != null)
@@ -50,13 +51,13 @@ public class ServerState : IEndpointV1
catch { throw new BadRequestException("The duration must be a valid time span"); }
if (ts.TotalMilliseconds > 0)
- FIXMEGlobal.LiveControl.Pause(ts);
+ liveControls.Pause(ts);
else
- FIXMEGlobal.LiveControl.Pause();
+ liveControls.Pause();
}
- private static void ExecuteResume(IStatusService statusService)
+ private static void ExecuteResume(IStatusService statusService, LiveControls liveControls)
{
- FIXMEGlobal.LiveControl.Resume();
+ liveControls.Resume();
}
}
\ No newline at end of file
diff --git a/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs b/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
index 047c62661..6c734c7fc 100644
--- a/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
+++ b/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
@@ -2,6 +2,7 @@ using Duplicati.Library.IO;
using Duplicati.Library.RestAPI;
using Duplicati.Library.RestAPI.Abstractions;
using Duplicati.Server;
+using Duplicati.Server.Database;
using Duplicati.Server.Serialization;
using Duplicati.WebserverCore.Abstractions;
using Duplicati.WebserverCore.Abstractions.Notifications;
@@ -14,13 +15,17 @@ namespace Duplicati.WebserverCore.Extensions;
public static class ServiceCollectionsExtensions
{
- public static IServiceCollection AddDuplicati(this IServiceCollection services)
+ public static IServiceCollection AddDuplicati(this IServiceCollection services, Connection connection)
{
//old part
- services.AddSingleton();
- services.AddSingleton(Serializer.JsonSettings);
- services.AddSingleton();
- services.AddSingleton();
+ services
+ .AddSingleton()
+ .AddSingleton(Serializer.JsonSettings)
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton()
+ .AddSingleton(connection);
+
//transitional part - services that act as a proxy to old part for various reasons (not accessible in assembly i.e.)
services.AddSingleton(c => c.GetRequiredService());