diff --git a/Duplicati.Library.RestAPI/Abstractions/IModernHttpRequestAccess.cs b/Duplicati.Library.RestAPI/Abstractions/IModernHttpRequestAccess.cs
new file mode 100644
index 000000000..0249d0858
--- /dev/null
+++ b/Duplicati.Library.RestAPI/Abstractions/IModernHttpRequestAccess.cs
@@ -0,0 +1,6 @@
+namespace Duplicati.Library.RestAPI.Abstractions;
+
+public interface IModernHttpRequestAccess
+{
+ public string GetQueryParam(string name);
+}
\ No newline at end of file
diff --git a/Duplicati.Library.RestAPI/RESTMethods/Backup.cs b/Duplicati.Library.RestAPI/RESTMethods/Backup.cs
index e18730fea..c69473c6c 100644
--- a/Duplicati.Library.RestAPI/RESTMethods/Backup.cs
+++ b/Duplicati.Library.RestAPI/RESTMethods/Backup.cs
@@ -25,6 +25,7 @@ using System.IO;
using System.Linq;
using Duplicati.Server.Serialization.Interface;
using Duplicati.Library.RestAPI;
+using Duplicati.Library.RestAPI.Abstractions;
namespace Duplicati.Server.WebServer.RESTMethods
{
@@ -636,7 +637,7 @@ namespace Duplicati.Server.WebServer.RESTMethods
return;
}
- var delete_remote_files = Library.Utility.Utility.ParseBool(info.Request.Param["delete-remote-files"].Value, false);
+ var delete_remote_files = info.Request is IModernHttpRequestAccess request && Library.Utility.Utility.ParseBool(request.GetQueryParam("delete-remote-files"), false);
if (delete_remote_files)
{
diff --git a/Duplicati.Library.RestAPI/RESTMethods/RemoteOperation.cs b/Duplicati.Library.RestAPI/RESTMethods/RemoteOperation.cs
index f9a8ded5e..04997df72 100644
--- a/Duplicati.Library.RestAPI/RESTMethods/RemoteOperation.cs
+++ b/Duplicati.Library.RestAPI/RESTMethods/RemoteOperation.cs
@@ -224,8 +224,19 @@ namespace Duplicati.Server.WebServer.RESTMethods
{
string url;
- using(var sr = new System.IO.StreamReader(info.Request.Body, System.Text.Encoding.UTF8, true))
- url = sr.ReadToEnd();
+ using (var sr = new System.IO.StreamReader(info.Request.Body, System.Text.Encoding.UTF8, true))
+ {
+ try
+ {
+ url = sr.ReadToEnd();
+ }
+ catch (InvalidOperationException)
+ {
+ url = sr.ReadLineAsync().Result;
+ }
+ }
+
+ Console.WriteLine(url);
switch (key)
{
diff --git a/Duplicati/Duplicati.Browser.Test/Drivers/BrowserDriver.cs b/Duplicati/Duplicati.Browser.Test/Drivers/BrowserDriver.cs
index 4bb13477e..d1c6697d6 100644
--- a/Duplicati/Duplicati.Browser.Test/Drivers/BrowserDriver.cs
+++ b/Duplicati/Duplicati.Browser.Test/Drivers/BrowserDriver.cs
@@ -1,50 +1,133 @@
using System;
+using System.Threading;
using OpenQA.Selenium;
using OpenQA.Selenium.Edge;
-namespace Duplicati.Browser.Test.Drivers
+namespace Duplicati.Browser.Test.Drivers;
+
+///
+/// Manages a browser instance using Selenium
+///
+public class BrowserDriver : IDisposable
{
+ private readonly Lazy _currentWebDriverLazy = new(CreateWebDriver);
+ private bool _isDisposed;
+
///
- /// Manages a browser instance using Selenium
+ /// The Selenium IWebDriver instance
///
- public class BrowserDriver : IDisposable
+ public IWebDriver Current => _currentWebDriverLazy.Value;
+
+ ///
+ /// Creates the Selenium web driver (opens a browser)
+ ///
+ ///
+ private static EdgeDriver CreateWebDriver()
{
- private readonly Lazy _currentWebDriverLazy = new(CreateWebDriver);
- private bool _isDisposed;
+ //We use the Chrome browser
+ var chromeDriverService = EdgeDriverService.CreateDefaultService(".", "msedgedriver");
- ///
- /// The Selenium IWebDriver instance
- ///
- public IWebDriver Current => _currentWebDriverLazy.Value;
+ return new EdgeDriver(chromeDriverService, new EdgeOptions());
+ }
- ///
- /// Creates the Selenium web driver (opens a browser)
- ///
- ///
- private static EdgeDriver CreateWebDriver()
+ ///
+ /// Disposes the Selenium web driver (closing the browser)
+ ///
+ public void Dispose()
+ {
+ if (_isDisposed)
{
- //We use the Chrome browser
- var chromeDriverService = EdgeDriverService.CreateDefaultService(".", "msedgedriver");
-
- return new EdgeDriver(chromeDriverService, new EdgeOptions());
+ return;
}
- ///
- /// Disposes the Selenium web driver (closing the browser)
- ///
- public void Dispose()
+ if (_currentWebDriverLazy.IsValueCreated)
{
- if (_isDisposed)
- {
- return;
- }
-
- if (_currentWebDriverLazy.IsValueCreated)
- {
- Current.Quit();
- }
-
- _isDisposed = true;
+ Current.Quit();
}
+
+ _isDisposed = true;
+ }
+}
+
+public static class DriverExtensions
+{
+ public static int SingleLoopWait = 100;
+ public static TimeSpan DefaultMaxWait = TimeSpan.FromSeconds(30);
+
+ public static IWebElement WaitForElement(this ISearchContext driver, By selector, TimeSpan? maxWait = null)
+ {
+ maxWait ??= DefaultMaxWait;
+ var i = 0;
+ while (i < maxWait.Value.TotalMilliseconds)
+ {
+ try
+ {
+ return driver.FindElement(selector);
+ }
+ catch (NoSuchElementException)
+ {
+ //swallow and wait for another loop
+ }
+
+ i += SingleLoopWait;
+ Thread.Sleep(TimeSpan.FromMilliseconds(SingleLoopWait));
+ }
+
+ return driver.FindElement(selector);
+ }
+
+ public static bool WaitForElementBeing(this IWebElement element, Func predicate,
+ TimeSpan? maxWait = null)
+ {
+ maxWait ??= DefaultMaxWait;
+ var i = 0;
+ while (i < maxWait.Value.TotalMilliseconds)
+ {
+ try
+ {
+ if (predicate.Invoke(element))
+ {
+ return true;
+ }
+ }
+ catch (NoSuchElementException)
+ {
+ //swallow and wait for another loop
+ }
+
+ i += SingleLoopWait;
+ Thread.Sleep(TimeSpan.FromMilliseconds(SingleLoopWait));
+ }
+
+ throw new Exception($"Timout of waiting for element to satisfy predicate: {predicate}!");
+ }
+
+ public static void SendKeysAndCheck(this IWebElement element, string text, TimeSpan? maxWait = null)
+ {
+ maxWait ??= DefaultMaxWait;
+ var i = 0;
+ while (i < maxWait.Value.TotalMilliseconds)
+ {
+ try
+ {
+ if (element.GetAttribute("value") != text)
+ {
+ element.SendKeys(text);
+ }
+ else
+ {
+ return;
+ }
+ }
+ catch (NoSuchElementException)
+ {
+ //swallow and wait for another loop
+ }
+
+ i += SingleLoopWait;
+ Thread.Sleep(TimeSpan.FromMilliseconds(SingleLoopWait));
+ }
+
+ throw new Exception("Could not set text value of element!");
}
}
\ No newline at end of file
diff --git a/Duplicati/Duplicati.Browser.Test/Duplicati.Browser.Test.csproj b/Duplicati/Duplicati.Browser.Test/Duplicati.Browser.Test.csproj
index efd9ee9c8..b4817f5f7 100644
--- a/Duplicati/Duplicati.Browser.Test/Duplicati.Browser.Test.csproj
+++ b/Duplicati/Duplicati.Browser.Test/Duplicati.Browser.Test.csproj
@@ -19,11 +19,12 @@
+
- PreserveNewest
+ Always
diff --git a/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature b/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature
index c85e5f17c..4f63e9942 100644
--- a/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature
+++ b/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature
@@ -4,9 +4,8 @@ Link to a feature: [Calculator](Duplicati.Browser.Test/Features/LocalBackup.feat
***Further read***: **[Learn more about how to generate Living Documentation](https://docs.specflow.org/projects/specflow-livingdoc/en/latest/LivingDocGenerator/Generating-Documentation.html)**
Scenario: Configure Backup
- Given the first number is 50
- And the second number is 70
- When the two numbers are added
+ Given there is local backup defined
+ When you run the backup
Then the result should be 120
diff --git a/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature.cs b/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature.cs
index 721df1e86..141b4f297 100644
--- a/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature.cs
+++ b/Duplicati/Duplicati.Browser.Test/Features/LocalBackup.feature.cs
@@ -105,15 +105,12 @@ this.ScenarioInitialize(scenarioInfo);
{
this.ScenarioStart();
#line 7
- testRunner.Given("the first number is 50", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+ testRunner.Given("there is local backup defined", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
#line hidden
#line 8
- testRunner.And("the second number is 70", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+ testRunner.When("you run the backup", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
#line 9
- testRunner.When("the two numbers are added", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
-#line hidden
-#line 10
testRunner.Then("the result should be 120", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
}
@@ -133,7 +130,7 @@ this.ScenarioInitialize(scenarioInfo);
argumentsOfScenario.Add("Second number", secondNumber);
argumentsOfScenario.Add("Expected result", expectedResult);
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Add two numbers permutations", null, tagsOfScenario, argumentsOfScenario, this._featureTags);
-#line 13
+#line 12
this.ScenarioInitialize(scenarioInfo);
#line hidden
bool isScenarioIgnored = default(bool);
@@ -153,16 +150,16 @@ this.ScenarioInitialize(scenarioInfo);
else
{
this.ScenarioStart();
-#line 14
+#line 13
testRunner.Given(string.Format("the first number is {0}", firstNumber), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
#line hidden
-#line 15
+#line 14
testRunner.And(string.Format("the second number is {0}", secondNumber), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
#line hidden
-#line 16
+#line 15
testRunner.When("the two numbers are added", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 17
+#line 16
testRunner.Then(string.Format("the result should be {0}", expectedResult), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
}
diff --git a/Duplicati/Duplicati.Browser.Test/PageObjects/AddBackupPage.cs b/Duplicati/Duplicati.Browser.Test/PageObjects/AddBackupPage.cs
new file mode 100644
index 000000000..fe5c80870
--- /dev/null
+++ b/Duplicati/Duplicati.Browser.Test/PageObjects/AddBackupPage.cs
@@ -0,0 +1,147 @@
+using System.Threading;
+using Duplicati.Browser.Test.Drivers;
+using OpenQA.Selenium;
+
+namespace Duplicati.Browser.Test.PageObjects;
+
+public class AddBackupPage(IWebDriver webDriver)
+{
+ private IWebElement NextButtonElement => webDriver.WaitForElement(By.ClassName("submit"));
+
+ public GeneralBackupSettingsPage ToGeneralSettings()
+ {
+ NextButtonElement.Click();
+
+ return new GeneralBackupSettingsPage(webDriver);
+ }
+}
+
+public class GeneralBackupSettingsPage(IWebDriver webDriver)
+{
+ private IWebElement NameTextboxElement => webDriver.WaitForElement(By.Id("name"));
+ private IWebElement NextButtonElement => webDriver.WaitForElement(By.ClassName("submit"));
+ private IWebElement GeneratePasswordLink => webDriver.WaitForElement(By.PartialLinkText("Generuj"));
+
+ public GeneralBackupSettingsPage SetName(string name)
+ {
+ if (NameTextboxElement.WaitForElementBeing(e => e.GetAttribute("placeholder") is "Moje Zdjęcia" or "My Photos"))
+ {
+ NameTextboxElement.Clear();
+ NameTextboxElement.SendKeysAndCheck(name);
+ Thread.Sleep(1000);
+ NameTextboxElement.SendKeysAndCheck(name);
+ }
+
+ return this;
+ }
+
+ public GeneralBackupSettingsPage GenerateRandomPassword()
+ {
+ GeneratePasswordLink.Click();
+
+ return this;
+ }
+
+ public BackupTargetSettingsPage ToBackupTarget()
+ {
+ NextButtonElement.Click();
+
+ return new BackupTargetSettingsPage(webDriver);
+ }
+}
+
+public class BackupTargetSettingsPage(IWebDriver webDriver)
+{
+ private IWebElement NextButtonElement => webDriver.WaitForElement(By.CssSelector("#nextStep2.submit"));
+ private IWebElement ManualPathLink => webDriver.WaitForElement(By.LinkText("Podaj ścieżkę ręcznie"));
+ private IWebElement FilePathTextbox => webDriver.WaitForElement(By.Id("file_path"));
+
+ public BackupTargetSettingsPage ChoosePathManually()
+ {
+ ManualPathLink.Click();
+
+ return this;
+ }
+
+ public BackupTargetSettingsPage SetManualPath(string path)
+ {
+ if (FilePathTextbox.WaitForElementBeing(e => e.GetAttribute("placeholder") is "Wprowadź ścieżkę docelową"))
+ {
+ FilePathTextbox.Clear();
+ FilePathTextbox.SendKeysAndCheck(path);
+ }
+
+ return this;
+ }
+
+ public BackupSourceSettingsPage ToBackupSource()
+ {
+ NextButtonElement.Click();
+
+ return new BackupSourceSettingsPage(webDriver);
+ }
+}
+
+public class BackupSourceSettingsPage(IWebDriver webDriver)
+{
+ private IWebElement NextButtonElement => webDriver.WaitForElement(By.CssSelector("#nextStep3.submit"));
+ private IWebElement FilePathTextbox => webDriver.WaitForElement(By.Id("sourcePath"));
+ private IWebElement AddFilePathButton => webDriver.WaitForElement(By.Id("sourceFolderPathAdd"));
+ private IWebElement ConfirmAddPathButton => webDriver.WaitForElement(By.PartialLinkText("Tak"));
+
+ public BackupSourceSettingsPage AddSourceManually(string path)
+ {
+ if (FilePathTextbox.WaitForElementBeing(e => e.GetAttribute("placeholder") is "Dodaj ścieżkę bezpośrednio"))
+ {
+ FilePathTextbox.Clear();
+ FilePathTextbox.SendKeysAndCheck(path);
+ }
+ AddFilePathButton.Click();
+ ConfirmAddPathButton.Click();
+
+ return this;
+ }
+
+ public ScheduleSettingsPage ToSchedule()
+ {
+ Thread.Sleep(20000);
+ NextButtonElement.Click();
+
+ return new ScheduleSettingsPage(webDriver);
+ }
+}
+
+public class ScheduleSettingsPage(IWebDriver webDriver)
+{
+ private IWebElement NextButtonElement => webDriver.WaitForElement(By.CssSelector("#nextStep4.submit"));
+ private IWebElement AutoRunCheckbox => webDriver.WaitForElement(By.Id("useScheduleRun"));
+
+ public ScheduleSettingsPage DisableAutorun()
+ {
+ if (AutoRunCheckbox.Selected)
+ {
+ AutoRunCheckbox.Click();
+ }
+
+ return this;
+ }
+
+ public ToOptionsSettingsPage ToOptions()
+ {
+ NextButtonElement.Click();
+
+ return new ToOptionsSettingsPage(webDriver);
+ }
+}
+
+public class ToOptionsSettingsPage(IWebDriver webDriver)
+{
+ private IWebElement SaveButtonElement => webDriver.WaitForElement(By.CssSelector("#save"));
+
+ public ToOptionsSettingsPage Save()
+ {
+ SaveButtonElement.Click();
+
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/Duplicati/Duplicati.Browser.Test/PageObjects/DuplicatiPageObject.cs b/Duplicati/Duplicati.Browser.Test/PageObjects/DuplicatiPageObject.cs
index a7fedb83b..6afa26a90 100644
--- a/Duplicati/Duplicati.Browser.Test/PageObjects/DuplicatiPageObject.cs
+++ b/Duplicati/Duplicati.Browser.Test/PageObjects/DuplicatiPageObject.cs
@@ -1,4 +1,5 @@
using System;
+using Duplicati.Browser.Test.Drivers;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;
@@ -18,23 +19,15 @@ namespace Duplicati.Browser.Test.PageObjects
public const int DefaultWaitInSeconds = 5;
//Finding elements by ID
- private IWebElement AddBackupElement => webDriver.FindElement(By.ClassName("add"));
- private IWebElement SecondNumberElement => webDriver.FindElement(By.Id("second-number"));
- private IWebElement AddButtonElement => webDriver.FindElement(By.Id("add-button"));
- private IWebElement ResultElement => webDriver.FindElement(By.Id("result"));
- private IWebElement ResetButtonElement => webDriver.FindElement(By.Id("reset-button"));
+ private IWebElement AddBackupElement => webDriver.WaitForElement(By.ClassName("add"));
+ private IWebElement AddButtonElement => webDriver.WaitForElement(By.Id("add-button"));
+ private IWebElement ResultElement => webDriver.WaitForElement(By.Id("result"));
+ private IWebElement ResetButtonElement => webDriver.WaitForElement(By.Id("reset-button"));
- public void NavigateToBackupCreation()
+ public AddBackupPage NavigateToBackupCreation()
{
AddBackupElement.Click();
- }
-
- public void EnterSecondNumber(string number)
- {
- //Clear text box
- SecondNumberElement.Clear();
- //Enter text
- SecondNumberElement.SendKeys(number);
+ return new AddBackupPage(webDriver);
}
public void ClickAdd()
diff --git a/Duplicati/Duplicati.Browser.Test/Steps/DuplicatiStepDefinitions.cs b/Duplicati/Duplicati.Browser.Test/Steps/DuplicatiStepDefinitions.cs
index 2fdd45dec..6e10539f5 100644
--- a/Duplicati/Duplicati.Browser.Test/Steps/DuplicatiStepDefinitions.cs
+++ b/Duplicati/Duplicati.Browser.Test/Steps/DuplicatiStepDefinitions.cs
@@ -1,6 +1,8 @@
-using Duplicati.Browser.Test.Drivers;
+using System.IO;
+using Duplicati.Browser.Test.Drivers;
using Duplicati.Browser.Test.PageObjects;
using FluentAssertions;
+using OpenQA.Selenium.Support.Extensions;
using TechTalk.SpecFlow;
namespace Duplicati.Browser.Test.Steps
@@ -11,22 +13,29 @@ namespace Duplicati.Browser.Test.Steps
//Page Object for Calculator
private readonly DuplicatiPageObject _duplicatiPageObject = new(browserDriver.Current);
- [Given("the first number is (.*)")]
- public void GivenTheFirstNumberIs(int number)
+ [Given("there is local backup defined")]
+ public void GivenLocalBackupDefined()
{
+ browserDriver.Current.TakeScreenshot();
//delegate to Page Object
- _duplicatiPageObject.NavigateToBackupCreation();
+ _duplicatiPageObject.NavigateToBackupCreation()
+ .ToGeneralSettings()
+ .SetName("Local Backup")
+ .GenerateRandomPassword()
+ .ToBackupTarget()
+ .ChoosePathManually()
+ .SetManualPath(Path.Combine(Directory.GetCurrentDirectory(), "test-backup-target"))
+ .ToBackupSource()
+ .AddSourceManually(Path.Combine(Directory.GetCurrentDirectory(), "test-backup-source")+"/")
+ .ToSchedule()
+ .DisableAutorun()
+ .ToOptions()
+ .Save()
+ ;
}
- [Given("the second number is (.*)")]
- public void GivenTheSecondNumberIs(int number)
- {
- //delegate to Page Object
- _duplicatiPageObject.EnterSecondNumber(number.ToString());
- }
-
- [When("the two numbers are added")]
- public void WhenTheTwoNumbersAreAdded()
+ [When("you run the backup")]
+ public void WhenBackupIsRun()
{
//delegate to Page Object
_duplicatiPageObject.ClickAdd();
diff --git a/Duplicati/Library/AutoUpdater/IUpdateManagerAccessor.cs b/Duplicati/Library/AutoUpdater/IUpdateManagerAccessor.cs
deleted file mode 100644
index 26763743a..000000000
--- a/Duplicati/Library/AutoUpdater/IUpdateManagerAccessor.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Duplicati.Library.AutoUpdater;
-
-public interface IUpdateManagerAccessor
-{
- bool HasUpdateInstalled { get; }
-}
\ No newline at end of file
diff --git a/Duplicati/Library/AutoUpdater/UpdateManagerAccessor.cs b/Duplicati/Library/AutoUpdater/UpdateManagerAccessor.cs
deleted file mode 100644
index cc1cae43c..000000000
--- a/Duplicati/Library/AutoUpdater/UpdateManagerAccessor.cs
+++ /dev/null
@@ -1,6 +0,0 @@
-namespace Duplicati.Library.AutoUpdater;
-
-public class UpdateManagerAccessor : IUpdateManagerAccessor
-{
- public bool HasUpdateInstalled => UpdaterManager.HasUpdateInstalled;
-}
diff --git a/Duplicati/Server/Program.cs b/Duplicati/Server/Program.cs
index 4f2c965dc..6d9ef28bb 100644
--- a/Duplicati/Server/Program.cs
+++ b/Duplicati/Server/Program.cs
@@ -203,18 +203,6 @@ namespace Duplicati.Server
[STAThread]
public static int Main(string[] _args)
{
- // var methodInfo = typeof(TemporaryIoCAccessor).Assembly.EntryPoint;
- // var program = Activator.CreateInstance(methodInfo!.DeclaringType!);
- // methodInfo.Invoke(program, [Array.Empty()]);
- return Duplicati.Library.AutoUpdater.UpdaterManager.RunFromMostRecent(typeof(Program).GetMethod("RealMain"), args, Duplicati.Library.AutoUpdater.AutoUpdateStrategy.Never);
- }
-
- public static int RealMain(string[] _args)
- {
-#if DEBUG
- System.Diagnostics.Debugger.Launch();
-#endif
-
//If we are on Windows, append the bundled "win-tools" programs to the search path
//We add it last, to allow the user to override with other versions
if (Platform.IsClientWindows)
diff --git a/Duplicati/WebserverCore/Dto/ServerStatus.cs b/Duplicati/WebserverCore/Dto/ServerStatus.cs
index 219495afa..4bf91e2e0 100644
--- a/Duplicati/WebserverCore/Dto/ServerStatus.cs
+++ b/Duplicati/WebserverCore/Dto/ServerStatus.cs
@@ -19,6 +19,6 @@ public class ServerStatusDto : IServerStatus
public long LastNotificationUpdateID { get; init; }
public string? UpdatedVersion { get; init; }
public UpdatePollerStates UpdaterState { get; init; }
- public bool UpdateReady { get; init; }
+ public string UpdateDownloadLink { get; set; }
public double UpdateDownloadProgress { get; init; }
}
\ No newline at end of file
diff --git a/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs b/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
index 7e297472f..dcfb5db0e 100644
--- a/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
+++ b/Duplicati/WebserverCore/Extensions/ServiceCollectionsExtensions.cs
@@ -26,7 +26,6 @@ public static class ServiceCollectionsExtensions
services.AddSingleton();
//transitional part - services that act as a proxy to old part for various reasons (not accessible in assembly i.e.)
- services.AddSingleton();
services.AddSingleton(c => c.GetRequiredService());
services.AddSingleton();
diff --git a/Duplicati/WebserverCore/LegacyHttpRequestShim.cs b/Duplicati/WebserverCore/LegacyHttpRequestShim.cs
index 9a981ce41..fa30f101a 100644
--- a/Duplicati/WebserverCore/LegacyHttpRequestShim.cs
+++ b/Duplicati/WebserverCore/LegacyHttpRequestShim.cs
@@ -1,6 +1,7 @@
using System.Collections.Specialized;
using System.Globalization;
using System.Net;
+using Duplicati.Library.RestAPI.Abstractions;
using HttpServer;
using HttpServer.FormDecoders;
using Microsoft.AspNetCore.Http.Extensions;
@@ -8,7 +9,7 @@ using HttpRequest = Microsoft.AspNetCore.Http.HttpRequest;
namespace Duplicati.WebserverCore;
-class LegacyHttpRequestShim : HttpServer.IHttpRequest
+class LegacyHttpRequestShim : HttpServer.IHttpRequest, IModernHttpRequestAccess
{
HttpRequest request;
public LegacyHttpRequestShim(HttpRequest request) { this.request = request; }
@@ -147,4 +148,9 @@ class LegacyHttpRequestShim : HttpServer.IHttpRequest
{
throw new NotImplementedException();
}
+
+ public string? GetQueryParam(string name)
+ {
+ return request.Query[name].FirstOrDefault();
+ }
}
\ No newline at end of file
diff --git a/Duplicati/WebserverCore/Services/StatusService.cs b/Duplicati/WebserverCore/Services/StatusService.cs
index 4347c94b5..f610bb8f1 100644
--- a/Duplicati/WebserverCore/Services/StatusService.cs
+++ b/Duplicati/WebserverCore/Services/StatusService.cs
@@ -1,4 +1,3 @@
-using Duplicati.Library.AutoUpdater;
using Duplicati.Library.RestAPI;
using Duplicati.Library.RestAPI.Abstractions;
using Duplicati.Server;
@@ -14,7 +13,6 @@ public class StatusService : IStatusService
private readonly LiveControls m_liveControls;
private readonly UpdatePollThread m_updatePollThread;
private readonly IUpdateService m_updateService;
- private readonly IUpdateManagerAccessor m_updateManager;
private readonly IWorkerThreadsManager m_workerThreadsManager;
private readonly ISettingsService m_settingsService;
private readonly IScheduler m_scheduler;
@@ -24,7 +22,6 @@ public class StatusService : IStatusService
public StatusService(LiveControls liveControls,
UpdatePollThread updatePollThread,
IUpdateService updateService,
- IUpdateManagerAccessor updateManager,
IWorkerThreadsManager workerThreadsManager,
ISettingsService settingsService,
IScheduler scheduler,
@@ -35,7 +32,6 @@ public class StatusService : IStatusService
m_liveControls = liveControls;
m_updatePollThread = updatePollThread;
m_updateService = updateService;
- m_updateManager = updateManager;
m_workerThreadsManager = workerThreadsManager;
m_settingsService = settingsService;
m_scheduler = scheduler;
@@ -52,7 +48,6 @@ public class StatusService : IStatusService
UpdatedVersion = GetUpdatedVersion(),
UpdaterState = m_updatePollThread.ThreadState,
UpdateDownloadProgress = m_updatePollThread.DownloadProgess,
- UpdateReady = m_updateManager.HasUpdateInstalled,
ActiveTask = m_workerThreadsManager.CurrentTask,
SchedulerQueueIds = m_scheduler.GetSchedulerQueueIds(),
LastEventID = m_eventPollNotify.EventNo,
@@ -98,6 +93,7 @@ public class StatusService : IStatusService
{
status.HasError = m_settingsService.GetSettings().UnackedError;
status.HasWarning = m_settingsService.GetSettings().UnackedWarning;
+ status.UpdateDownloadLink = m_settingsService.GetSettings().UpdateCheckNewVersion;
}
private string? GetUpdatedVersion()