From 0fefb316ebd92f642fbda8a79bdb771db24b08db Mon Sep 17 00:00:00 2001 From: natan Date: Mon, 22 Apr 2024 10:15:56 +0200 Subject: [PATCH] Selenium Tests --- .../Abstractions/IModernHttpRequestAccess.cs | 6 + .../RESTMethods/Backup.cs | 3 +- .../RESTMethods/RemoteOperation.cs | 15 +- .../Drivers/BrowserDriver.cs | 149 ++++++++++++++---- .../Duplicati.Browser.Test.csproj | 3 +- .../Features/LocalBackup.feature | 5 +- .../Features/LocalBackup.feature.cs | 17 +- .../PageObjects/AddBackupPage.cs | 147 +++++++++++++++++ .../PageObjects/DuplicatiPageObject.cs | 21 +-- .../Steps/DuplicatiStepDefinitions.cs | 35 ++-- .../AutoUpdater/IUpdateManagerAccessor.cs | 6 - .../AutoUpdater/UpdateManagerAccessor.cs | 6 - Duplicati/Server/Program.cs | 12 -- Duplicati/WebserverCore/Dto/ServerStatus.cs | 2 +- .../ServiceCollectionsExtensions.cs | 1 - .../WebserverCore/LegacyHttpRequestShim.cs | 8 +- .../WebserverCore/Services/StatusService.cs | 6 +- 17 files changed, 333 insertions(+), 109 deletions(-) create mode 100644 Duplicati.Library.RestAPI/Abstractions/IModernHttpRequestAccess.cs create mode 100644 Duplicati/Duplicati.Browser.Test/PageObjects/AddBackupPage.cs delete mode 100644 Duplicati/Library/AutoUpdater/IUpdateManagerAccessor.cs delete mode 100644 Duplicati/Library/AutoUpdater/UpdateManagerAccessor.cs 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()