From 9ebab414d7b06ccda243c71e83eac4978569e363 Mon Sep 17 00:00:00 2001 From: Dmitry Kolinchuk Date: Fri, 26 Feb 2021 17:35:44 +0200 Subject: [PATCH 01/17] #557 Implement the Install Packages functionality for Sitecore 9 and later --- src/SIM.Base/WebRequestHelper.cs | 8 ++ src/SIM.Pipelines/Agent/AgentFiles.cs | 106 ++++++++++++++++++ src/SIM.Pipelines/Agent/AgentHelper.cs | 2 +- ...nstallModulesForSitecore9AndLaterButton.cs | 43 +++++++ src/SIM.Tool.Windows/MainWindowData.cs | 8 ++ src/SIM.Tool.Windows/SIM.Tool.Windows.csproj | 3 + .../Helpers/SitecoreIdServerAuth.cs | 42 +++++++ .../ButtonsConfiguration.json | 2 + 8 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs create mode 100644 src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs diff --git a/src/SIM.Base/WebRequestHelper.cs b/src/SIM.Base/WebRequestHelper.cs index 5f0318b0..a8b80a91 100644 --- a/src/SIM.Base/WebRequestHelper.cs +++ b/src/SIM.Base/WebRequestHelper.cs @@ -16,6 +16,8 @@ public static class WebRequestHelper public const int Minute = 60 * Second; public const int Second = 1000; + public static string AuthToken; + #endregion #region Public methods @@ -219,6 +221,12 @@ private static HttpWebRequest CreateRequest(Uri url, int? timeout = null, int? r var webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Timeout = timeout ?? Settings.CoreWebDownloadConnectionTimeout.Value; webRequest.ReadWriteTimeout = readWriteTimeout ?? Settings.CoreWebDownloadTimeoutMinutes.Value * Minute; + + if (AuthToken != null) + { + webRequest.Headers.Add("Authorization", AuthToken); + } + if (cookies != null) { webRequest.Headers.Add(HttpRequestHeader.Cookie, cookies); diff --git a/src/SIM.Pipelines/Agent/AgentFiles.cs b/src/SIM.Pipelines/Agent/AgentFiles.cs index 28a981d1..8c9053ca 100644 --- a/src/SIM.Pipelines/Agent/AgentFiles.cs +++ b/src/SIM.Pipelines/Agent/AgentFiles.cs @@ -112,6 +112,112 @@ private string GetFilePath(string name) #endregion +"; + + public const string InstallPackageContentsForSitecore9AndLater = @" +<%@ Page Language=""C#"" AutoEventWireup=""true"" %> +<%@ Import Namespace=""System.IO"" %> +<%@ Import Namespace=""Sitecore.Configuration"" %> +<%@ Import Namespace=""Sitecore.Data.Engines"" %> +<%@ Import Namespace=""Sitecore.Diagnostics"" %> +<%@ Import Namespace=""Sitecore.Install"" %> +<%@ Import Namespace=""Sitecore.Install.Files"" %> +<%@ Import Namespace=""Sitecore.Install.Framework"" %> +<%@ Import Namespace=""Sitecore.Install.Items"" %> +<%@ Import Namespace=""Sitecore.Install.Utils"" %> +<%@ Import Namespace=""Sitecore.SecurityModel"" %> +<%@ Import Namespace=""Sitecore.Security.Accounts"" %> + +"; public const string InstallPackageFileName = @"InstallPackage.aspx"; diff --git a/src/SIM.Pipelines/Agent/AgentHelper.cs b/src/SIM.Pipelines/Agent/AgentHelper.cs index 92f1a0b2..b6032351 100644 --- a/src/SIM.Pipelines/Agent/AgentHelper.cs +++ b/src/SIM.Pipelines/Agent/AgentHelper.cs @@ -52,7 +52,7 @@ public static void CopyAgentFiles([NotNull] Instance instance) new { FileName = AgentFiles.InstallPackageFileName, - Contents = AgentFiles.InstallPackageContents + Contents = instance.Type == Instance.InstanceType.Sitecore9AndLater ? AgentFiles.InstallPackageContentsForSitecore9AndLater : AgentFiles.InstallPackageContents }, new { diff --git a/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs b/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs new file mode 100644 index 00000000..76239a96 --- /dev/null +++ b/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs @@ -0,0 +1,43 @@ +using System.Threading.Tasks; +using System.Windows; +using JetBrains.Annotations; +using SIM.Instances; +using SIM.Tool.Base.Pipelines; +using SIM.Tool.Base.Wizards; +using SIM.Tool.Windows.UserControls.Helpers; + +namespace SIM.Tool.Windows.MainWindowComponents.Buttons +{ + [UsedImplicitly] + public class InstallModulesForSitecore9AndLaterButton : InstanceOnlyButton + { + public override void OnClick(Window mainWindow, Instance instance) + { + if (instance != null) + { + if (instance.Type == Instance.InstanceType.Sitecore9AndLater) + { + int sitecoreVersion; + int.TryParse(instance.Product.ShortVersion, out sitecoreVersion); + if (sitecoreVersion >= 91) + { + string sitecoreIdServerUri = "https://" + instance.SitecoreEnvironment.Name + "Id.local"; + string authToken = null; + var task = Task.Run(async () => { + authToken = await + SitecoreIdServerAuth.GetToken(sitecoreIdServerUri, "SitecorePassword", "SIF-Default", "password", "sitecore\\admin", "b"); + }); + task?.Wait(); + + WebRequestHelper.AuthToken = authToken; + } + } + + var id = MainWindowHelper.GetListItemID(instance.ID); + WizardPipelineManager.Start("installmodules", mainWindow, null, null, ignore => MainWindowHelper.MakeInstanceSelected(id), () => new InstallModulesWizardArgs(instance)); + + WebRequestHelper.AuthToken = null; + } + } + } +} diff --git a/src/SIM.Tool.Windows/MainWindowData.cs b/src/SIM.Tool.Windows/MainWindowData.cs index a25a9ac1..1284add2 100644 --- a/src/SIM.Tool.Windows/MainWindowData.cs +++ b/src/SIM.Tool.Windows/MainWindowData.cs @@ -685,6 +685,12 @@ private static ButtonDefinition GetPatchButton() Image = "/Images/$lg/install.png, SIM.Tool.Windows", Handler = new InstallModulesButton() }, + new ButtonDefinition + { + Label = "Install Packages", + Image = "/Images/$lg/install.png, SIM.Tool.Windows", + Handler = new InstallModulesForSitecore9AndLaterButton() + }, } }, GetManageGroupDefinition(), @@ -1154,6 +1160,8 @@ private static GroupDefinition GetManageGroupDefinition() new ButtonDefinition { Label = "Export", Image = "/Images/$sm/download.png, SIM.Tool.Windows", Handler = new ExportInstanceButton() }, new ButtonDefinition { Handler = new InstallModulesButton() }, new ButtonDefinition { Label = "Install modules", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesButton() }, + new ButtonDefinition { Handler = new InstallModulesButton() }, + new ButtonDefinition { Label = "Install modules", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesForSitecore9AndLaterButton() }, new ButtonDefinition { Handler = new ReinstallInstanceButton() }, new ButtonDefinition { Label = "Reinstall instance", Image = "/Images/$sm/redo.png, SIM.Tool.Windows", Handler = new ReinstallInstanceButton() }, new ButtonDefinition { Handler = new DeleteInstanceButton() }, diff --git a/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj b/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj index 82718347..c930e29c 100644 --- a/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj +++ b/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj @@ -99,6 +99,7 @@ + ..\packages\ControlzEx.2.0.1.61\lib\net45\System.Windows.Interactivity.dll @@ -152,6 +153,7 @@ + @@ -279,6 +281,7 @@ + ImportWebsite.xaml diff --git a/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs new file mode 100644 index 00000000..9acaa896 --- /dev/null +++ b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Newtonsoft.Json; + +namespace SIM.Tool.Windows.UserControls.Helpers +{ + public static class SitecoreIdServerAuth + { + public static async Task GetToken(string idServerUri, string clientId, string clientSecret, string grantType, string username, string password) + { + using (var client = new HttpClient()) + { + client.BaseAddress = new Uri(idServerUri); + client.DefaultRequestHeaders.Accept.Clear(); + client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + var content = new FormUrlEncodedContent(new[] + { + new KeyValuePair("client_id", clientId), + new KeyValuePair("client_secret", clientSecret), + new KeyValuePair("grant_type", grantType), + new KeyValuePair("username", username), + new KeyValuePair("password", password) + }); + var response = await client.PostAsync("connect/token", content); + var result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); + return $"Bearer {result.access_token}"; + } + } + + private struct TokenResponse + { + public string access_token { get; set; } + + public long expires_in { get; set; } + + public string token_type { get; set; } + } + } +} \ No newline at end of file diff --git a/src/SIM.Tool/ButtonsConfiguration/ButtonsConfiguration.json b/src/SIM.Tool/ButtonsConfiguration/ButtonsConfiguration.json index cb372fef..58f3199d 100644 --- a/src/SIM.Tool/ButtonsConfiguration/ButtonsConfiguration.json +++ b/src/SIM.Tool/ButtonsConfiguration/ButtonsConfiguration.json @@ -94,6 +94,7 @@ "ManagedArgsTracerButton" ], "Sitecore9AndLaterButtons": [ + "InstallModulesForSitecore9AndLaterButton", "RefreshButton", "InstallInstanceButton", "Install9InstanceButton", @@ -172,6 +173,7 @@ "BackupGroup" ], "Sitecore9AndLaterGroups": [ + "InstallGroup", "PageGroup", "FileSystemGroup", "AppsGroup", From 869839524fff3e00e51c5521ac1ca2286a48f0a6 Mon Sep 17 00:00:00 2001 From: Dmitry Kolinchuk Date: Thu, 18 Mar 2021 17:19:42 +0200 Subject: [PATCH 02/17] #557 Extend API to use cookies and headers in order to install packages under authenticated user --- src/SIM.Base/WebRequestHelper.cs | 28 +++++---- src/SIM.Pipelines/Agent/AgentHelper.cs | 20 +++---- .../Install/Modules/InstallPackages.cs | 7 ++- .../InstallModules/InstallModulesArgs.cs | 8 ++- .../InstallModules/InstallPackages.cs | 2 +- .../InstallModules/PerformPostStepActions.cs | 2 +- .../Pipelines/InstallModulesWizardArgs.cs | 11 +++- ...nstallModulesForSitecore9AndLaterButton.cs | 55 +++++++++++------ src/SIM.Tool.Windows/SIM.Tool.Windows.csproj | 1 + .../Helpers/SitecoreIdServerAuth.cs | 20 +++---- .../Helpers/SitecoreServicesClientAuth.cs | 60 +++++++++++++++++++ 11 files changed, 156 insertions(+), 58 deletions(-) create mode 100644 src/SIM.Tool.Windows/UserControls/Helpers/SitecoreServicesClientAuth.cs diff --git a/src/SIM.Base/WebRequestHelper.cs b/src/SIM.Base/WebRequestHelper.cs index a8b80a91..1de5f1b7 100644 --- a/src/SIM.Base/WebRequestHelper.cs +++ b/src/SIM.Base/WebRequestHelper.cs @@ -7,6 +7,7 @@ using System.Threading; using Sitecore.Diagnostics.Base; using Sitecore.Diagnostics.Logging; + using System.Collections.Generic; public static class WebRequestHelper { @@ -16,8 +17,6 @@ public static class WebRequestHelper public const int Minute = 60 * Second; public const int Second = 1000; - public static string AuthToken; - #endregion #region Public methods @@ -132,9 +131,9 @@ public static void DownloadFile(string destFileName, Stream responseStream, Canc } } - public static string DownloadString(string url, int? timeout = null, int? readWriteTimeout = null) + public static string DownloadString(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) { - using (var response = RequestAndGetResponse(url, timeout, readWriteTimeout)) + using (var response = RequestAndGetResponse(url, timeout, readWriteTimeout, cookies: cookies, headers: headers)) { Assert.IsNotNull(response, "No response provided"); var stream = response.GetResponseStream(); @@ -195,14 +194,14 @@ public static string GetFileName(WebResponse response) return GetCookieValue(contentDisposition, "filename").Trim('"'); } - public static HttpWebResponse RequestAndGetResponse(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null) + public static HttpWebResponse RequestAndGetResponse(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) { - return RequestAndGetResponse(new Uri(url), timeout, readWriteTimeout, cookies); + return RequestAndGetResponse(new Uri(url), timeout, readWriteTimeout, cookies, headers); } - public static HttpWebResponse RequestAndGetResponse(Uri uri, int? timeout = null, int? readWriteTimeout = null, string cookies = null) + public static HttpWebResponse RequestAndGetResponse(Uri uri, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) { - var webRequest = CreateRequest(uri, timeout, readWriteTimeout, cookies); + var webRequest = CreateRequest(uri, timeout, readWriteTimeout, cookies, headers); return webRequest.GetResponse() as HttpWebResponse; } @@ -216,20 +215,23 @@ private static HttpWebRequest CreateRequest(string url, int? timeout = null, int return CreateRequest(new Uri(url), timeout, readWriteTimeout, cookies); } - private static HttpWebRequest CreateRequest(Uri url, int? timeout = null, int? readWriteTimeout = null, string cookies = null) + private static HttpWebRequest CreateRequest(Uri url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) { var webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Timeout = timeout ?? Settings.CoreWebDownloadConnectionTimeout.Value; webRequest.ReadWriteTimeout = readWriteTimeout ?? Settings.CoreWebDownloadTimeoutMinutes.Value * Minute; - if (AuthToken != null) + if (cookies != null) { - webRequest.Headers.Add("Authorization", AuthToken); + webRequest.Headers.Add(HttpRequestHeader.Cookie, cookies); } - if (cookies != null) + if (headers != null) { - webRequest.Headers.Add(HttpRequestHeader.Cookie, cookies); + foreach (KeyValuePair header in headers) + { + webRequest.Headers.Add(header.Key, header.Value); + } } return webRequest; diff --git a/src/SIM.Pipelines/Agent/AgentHelper.cs b/src/SIM.Pipelines/Agent/AgentHelper.cs index b6032351..f137b949 100644 --- a/src/SIM.Pipelines/Agent/AgentHelper.cs +++ b/src/SIM.Pipelines/Agent/AgentHelper.cs @@ -101,7 +101,7 @@ public static void DeleteAgentFiles([NotNull] Instance instance) #region Package installation - public static void InstallPackage([NotNull] Instance instance, [NotNull] Product module) + public static void InstallPackage([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) { Assert.ArgumentNotNull(instance, nameof(instance)); Assert.ArgumentNotNull(module, nameof(module)); @@ -113,10 +113,10 @@ public static void InstallPackage([NotNull] Instance instance, [NotNull] Product var statusUrl = GetUrl(instance, AgentFiles.StatusFileName); - ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.InstallPackageFileName, installPackageUrl, PackageInstalling, PackageInstalled); + ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.InstallPackageFileName, installPackageUrl, PackageInstalling, PackageInstalled, cookies: cookies, headers: headers); } - public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] Product module) + public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) { XmlDocument xmlDocument = module.Manifest; bool skipPostActions = module.SkipPostActions; @@ -160,7 +160,7 @@ public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] { var value = custom.Aggregate(string.Empty, (current, pair) => current + ($";{pair[0]}-{pair[1]}")); var postInstallUrl = GetUrl(instance, AgentFiles.PostInstallActionsFileName, value.TrimStart(';'), "custom"); - ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.PostInstallActionsFileName, postInstallUrl, ActionsPerforming, ActionsPerformed); + ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.PostInstallActionsFileName, postInstallUrl, ActionsPerforming, ActionsPerformed, cookies: cookies, headers: headers); return; } } @@ -174,7 +174,7 @@ public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] var fileName = Path.GetFileName(module.PackagePath); Assert.IsNotNull(fileName, nameof(fileName)); var url = GetUrl(instance, AgentFiles.PostInstallActionsFileName, fileName); - ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.PostInstallActionsFileName, url, ActionsPerforming, ActionsPerformed); + ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.PostInstallActionsFileName, url, ActionsPerforming, ActionsPerformed, cookies: cookies, headers: headers); } #endregion @@ -190,7 +190,7 @@ public static string GetUrl(Instance instance, string pageName, string value = n } [NotNull] - public static string Request([NotNull] string url, [NotNull] string pageName) + public static string Request([NotNull] string url, [NotNull] string pageName, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) { Assert.ArgumentNotNull(url, nameof(url)); Assert.ArgumentNotNullOrEmpty(pageName, nameof(pageName)); @@ -200,7 +200,7 @@ public static string Request([NotNull] string url, [NotNull] string pageName) try { Log.Info($"Requesting URL {url}"); - result = WebRequestHelper.DownloadString(url).Trim(); + result = WebRequestHelper.DownloadString(url, cookies: cookies, headers: headers).Trim(); if (result.ToLower().StartsWith("error:")) { throw new InvalidOperationException(errorPrefix + result); @@ -222,10 +222,10 @@ public static string Request([NotNull] string url, [NotNull] string pageName) #region Private methods - private static void ExecuteAgent(string statusFileName, string statusUrl, string agentName, string operationUrl, string operationStartedStatus, string operationCompletedStatus) + private static void ExecuteAgent(string statusFileName, string statusUrl, string agentName, string operationUrl, string operationStartedStatus, string operationCompletedStatus, string cookies = null, Dictionary headers = null) { // Call agent main operation - var status = Request(operationUrl, agentName); + var status = Request(operationUrl, agentName, cookies: cookies, headers: headers); // If the package installation process takes more than http timeout, retrive status if (status != operationCompletedStatus) @@ -233,7 +233,7 @@ private static void ExecuteAgent(string statusFileName, string statusUrl, string // Retrive status while the previous request timed out, status is in progress or package is already being installed while (status == TimedOut || status == InProgress || status == operationStartedStatus) { - status = Request(statusUrl, statusFileName); + status = Request(statusUrl, statusFileName, cookies: cookies, headers: headers); Thread.Sleep(2000); } diff --git a/src/SIM.Pipelines/Install/Modules/InstallPackages.cs b/src/SIM.Pipelines/Install/Modules/InstallPackages.cs index 0e1cfcdd..36ee3810 100644 --- a/src/SIM.Pipelines/Install/Modules/InstallPackages.cs +++ b/src/SIM.Pipelines/Install/Modules/InstallPackages.cs @@ -6,13 +6,14 @@ namespace SIM.Pipelines.Install.Modules using SIM.Products; using Sitecore.Diagnostics.Base; using JetBrains.Annotations; + using SIM.Pipelines.InstallModules; #region #endregion [UsedImplicitly] - public class InstallPackages : InstallProcessor + public class InstallPackages : InstallModulesProcessor { #region Fields @@ -22,7 +23,7 @@ public class InstallPackages : InstallProcessor #region Methods - protected override void Process([NotNull] InstallArgs args) + protected override void Process([NotNull] InstallModulesArgs args) { Assert.ArgumentNotNull(args, nameof(args)); @@ -35,7 +36,7 @@ protected override void Process([NotNull] InstallArgs args) continue; } - AgentHelper.InstallPackage(args.Instance, module); + AgentHelper.InstallPackage(args.Instance, module, args.Cookies, args.Headers); _Done.Add(module); } diff --git a/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs b/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs index 1027480e..37b526f3 100644 --- a/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs +++ b/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs @@ -23,11 +23,15 @@ public class InstallModulesArgs : ProcessorArgs private string instanceName { get; } + public string Cookies { get; } + + public Dictionary Headers { get; } + #endregion #region Constructors - public InstallModulesArgs([NotNull] Instance instance, [NotNull] IEnumerable modules, [CanBeNull] SqlConnectionStringBuilder connectionString = null) + public InstallModulesArgs([NotNull] Instance instance, [NotNull] IEnumerable modules, [CanBeNull] SqlConnectionStringBuilder connectionString = null, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) { Assert.ArgumentNotNull(instance, nameof(instance)); Assert.ArgumentNotNull(modules, nameof(modules)); @@ -36,6 +40,8 @@ public InstallModulesArgs([NotNull] Instance instance, [NotNull] IEnumerable Headers { get; } + #endregion #region Constructors @@ -29,13 +33,16 @@ public InstallModulesWizardArgs() { } - public InstallModulesWizardArgs(Instance instance) + public InstallModulesWizardArgs(Instance instance, string cookies = null, Dictionary headers = null) { Instance = instance; if (instance != null) { WebRootPath = instance.WebRootPath; } + + Cookies = cookies; + Headers = headers; } #endregion @@ -81,7 +88,7 @@ public override ProcessorArgs ToProcessorArgs() products.Add(product); } - return new InstallModulesArgs(Instance, products, connectionString); + return new InstallModulesArgs(Instance, products, connectionString, Cookies, Headers); } #endregion diff --git a/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs b/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs index 76239a96..611be702 100644 --- a/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs +++ b/src/SIM.Tool.Windows/MainWindowComponents/Buttons/InstallModulesForSitecore9AndLaterButton.cs @@ -1,7 +1,10 @@ -using System.Threading.Tasks; +using System.Collections.Generic; +using System.Threading.Tasks; using System.Windows; using JetBrains.Annotations; +using SIM.Core; using SIM.Instances; +using SIM.Tool.Base; using SIM.Tool.Base.Pipelines; using SIM.Tool.Base.Wizards; using SIM.Tool.Windows.UserControls.Helpers; @@ -15,29 +18,47 @@ public override void OnClick(Window mainWindow, Instance instance) { if (instance != null) { - if (instance.Type == Instance.InstanceType.Sitecore9AndLater) + Dictionary headers = null; + string authCookie = null; + + int.TryParse(instance.Product.ShortVersion, out int sitecoreVersion); + if (sitecoreVersion >= 91) { - int sitecoreVersion; - int.TryParse(instance.Product.ShortVersion, out sitecoreVersion); - if (sitecoreVersion >= 91) + string idServerAuthToken = null; + string sitecoreIdServerUri = "https://" + instance.SitecoreEnvironment.Name + "Id.local"; + var task = Task.Run(async () => { + idServerAuthToken = await + SitecoreIdServerAuth.GetToken(sitecoreIdServerUri, CoreAppSettings.AppLoginAsAdminUserName.Value, CoreAppSettings.AppLoginAsAdminNewPassword.Value); + }); + task?.Wait(); + + if (string.IsNullOrEmpty(idServerAuthToken)) { - string sitecoreIdServerUri = "https://" + instance.SitecoreEnvironment.Name + "Id.local"; - string authToken = null; - var task = Task.Run(async () => { - authToken = await - SitecoreIdServerAuth.GetToken(sitecoreIdServerUri, "SitecorePassword", "SIF-Default", "password", "sitecore\\admin", "b"); - }); - task?.Wait(); + WindowHelper.ShowMessage("Unable to get authentication token from the following Sitecore Identity Server: " + sitecoreIdServerUri, MessageBoxButton.OK, MessageBoxImage.Warning); + return; + } + + headers = new Dictionary { { "Authorization", idServerAuthToken } }; + } + else if (sitecoreVersion == 90) + { + string instanceUri = instance.GetUrl(); + var task = Task.Run(async () => { + authCookie = await + SitecoreServicesClientAuth.GetCookie(instanceUri, CoreAppSettings.AppLoginAsAdminUserName.Value, CoreAppSettings.AppLoginAsAdminNewPassword.Value); + }); + task?.Wait(); - WebRequestHelper.AuthToken = authToken; + if (string.IsNullOrEmpty(authCookie)) + { + WindowHelper.ShowMessage("Unable to get authentication cookie from the following Sitecore instance: " + instanceUri, MessageBoxButton.OK, MessageBoxImage.Warning); + return; } } var id = MainWindowHelper.GetListItemID(instance.ID); - WizardPipelineManager.Start("installmodules", mainWindow, null, null, ignore => MainWindowHelper.MakeInstanceSelected(id), () => new InstallModulesWizardArgs(instance)); - - WebRequestHelper.AuthToken = null; + WizardPipelineManager.Start("installmodules", mainWindow, null, null, ignore => MainWindowHelper.MakeInstanceSelected(id), () => new InstallModulesWizardArgs(instance, authCookie, headers)); } } } -} +} \ No newline at end of file diff --git a/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj b/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj index c930e29c..95b2baa9 100644 --- a/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj +++ b/src/SIM.Tool.Windows/SIM.Tool.Windows.csproj @@ -281,6 +281,7 @@ + ImportWebsite.xaml diff --git a/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs index 9acaa896..6c308ea0 100644 --- a/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs +++ b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreIdServerAuth.cs @@ -9,22 +9,22 @@ namespace SIM.Tool.Windows.UserControls.Helpers { public static class SitecoreIdServerAuth { - public static async Task GetToken(string idServerUri, string clientId, string clientSecret, string grantType, string username, string password) + public static async Task GetToken(string idServerUri, string userName, string password) { - using (var client = new HttpClient()) + using (HttpClient authClient = new HttpClient()) { - client.BaseAddress = new Uri(idServerUri); - client.DefaultRequestHeaders.Accept.Clear(); - client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + authClient.BaseAddress = new Uri(idServerUri); + authClient.DefaultRequestHeaders.Accept.Clear(); + authClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var content = new FormUrlEncodedContent(new[] { - new KeyValuePair("client_id", clientId), - new KeyValuePair("client_secret", clientSecret), - new KeyValuePair("grant_type", grantType), - new KeyValuePair("username", username), + new KeyValuePair("client_id", "SitecorePassword"), + new KeyValuePair("client_secret", "SIF-Default"), + new KeyValuePair("grant_type", "password"), + new KeyValuePair("username", userName), new KeyValuePair("password", password) }); - var response = await client.PostAsync("connect/token", content); + var response = await authClient.PostAsync("connect/token", content); var result = JsonConvert.DeserializeObject(response.Content.ReadAsStringAsync().Result); return $"Bearer {result.access_token}"; } diff --git a/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreServicesClientAuth.cs b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreServicesClientAuth.cs new file mode 100644 index 00000000..6be66796 --- /dev/null +++ b/src/SIM.Tool.Windows/UserControls/Helpers/SitecoreServicesClientAuth.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; + +namespace SIM.Tool.Windows.UserControls.Helpers +{ + public static class SitecoreServicesClientAuth + { + public static async Task GetCookie(string idServerUri, string userName, string password) + { + CookieContainer cookieContainer = new CookieContainer(); + HttpClientHandler httpClientHandler = new HttpClientHandler + { + CookieContainer = cookieContainer, + UseCookies = true + }; + + using (HttpClient authClient = new HttpClient(httpClientHandler)) + { + Uri uri = new Uri(idServerUri + "/sitecore/api/ssc/auth/login"); + + authClient.BaseAddress = uri; + authClient.DefaultRequestHeaders.Accept.Clear(); + authClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); + + GetDomainAndName(userName, out string domain, out string name); + + FormUrlEncodedContent content = new FormUrlEncodedContent(new[] + { + new KeyValuePair("domain", domain), + new KeyValuePair("username", name), + new KeyValuePair("password", password) + }); + await authClient.PostAsync(uri, content); + Cookie authCookie = cookieContainer.GetCookies(uri).Cast().FirstOrDefault(x => x.Name == ".ASPXAUTH"); + return authCookie?.ToString(); + } + } + + private static void GetDomainAndName(string userName, out string domain, out string username) + { + domain = null; + username = null; + if (!string.IsNullOrEmpty(userName)) + { + int charLocation = userName.IndexOf("\\", StringComparison.InvariantCultureIgnoreCase); + + if (charLocation > 0) + { + domain = userName.Substring(0, charLocation); + username = userName.Substring(charLocation + 1); + } + } + } + } +} \ No newline at end of file From b5433f6cc0b229678716b7529333156e645fb48a Mon Sep 17 00:00:00 2001 From: Dmitry Kolinchuk Date: Fri, 19 Mar 2021 10:28:49 +0200 Subject: [PATCH 03/17] #557 Rename context menu items --- src/SIM.Tool.Windows/MainWindowData.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/SIM.Tool.Windows/MainWindowData.cs b/src/SIM.Tool.Windows/MainWindowData.cs index 1284add2..46e9cc64 100644 --- a/src/SIM.Tool.Windows/MainWindowData.cs +++ b/src/SIM.Tool.Windows/MainWindowData.cs @@ -1159,9 +1159,9 @@ private static GroupDefinition GetManageGroupDefinition() new ButtonDefinition { Handler = new ExportInstanceButton() }, new ButtonDefinition { Label = "Export", Image = "/Images/$sm/download.png, SIM.Tool.Windows", Handler = new ExportInstanceButton() }, new ButtonDefinition { Handler = new InstallModulesButton() }, - new ButtonDefinition { Label = "Install modules", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesButton() }, + new ButtonDefinition { Label = "Install packages", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesButton() }, new ButtonDefinition { Handler = new InstallModulesButton() }, - new ButtonDefinition { Label = "Install modules", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesForSitecore9AndLaterButton() }, + new ButtonDefinition { Label = "Install packages", Image = "/Images/$sm/install.png, SIM.Tool.Windows", Handler = new InstallModulesForSitecore9AndLaterButton() }, new ButtonDefinition { Handler = new ReinstallInstanceButton() }, new ButtonDefinition { Label = "Reinstall instance", Image = "/Images/$sm/redo.png, SIM.Tool.Windows", Handler = new ReinstallInstanceButton() }, new ButtonDefinition { Handler = new DeleteInstanceButton() }, From db08f6e2472cd4a7f0b28f90f696e74444cef60f Mon Sep 17 00:00:00 2001 From: Dmitry Kolinchuk Date: Fri, 19 Mar 2021 10:32:57 +0200 Subject: [PATCH 04/17] #557 Change Dictionary to IDictionary --- src/SIM.Base/WebRequestHelper.cs | 8 ++++---- src/SIM.Pipelines/Agent/AgentHelper.cs | 8 ++++---- src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs | 4 ++-- src/SIM.Tool.Base/Pipelines/InstallModulesWizardArgs.cs | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/SIM.Base/WebRequestHelper.cs b/src/SIM.Base/WebRequestHelper.cs index 1de5f1b7..cacf92aa 100644 --- a/src/SIM.Base/WebRequestHelper.cs +++ b/src/SIM.Base/WebRequestHelper.cs @@ -131,7 +131,7 @@ public static void DownloadFile(string destFileName, Stream responseStream, Canc } } - public static string DownloadString(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) + public static string DownloadString(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, IDictionary headers = null) { using (var response = RequestAndGetResponse(url, timeout, readWriteTimeout, cookies: cookies, headers: headers)) { @@ -194,12 +194,12 @@ public static string GetFileName(WebResponse response) return GetCookieValue(contentDisposition, "filename").Trim('"'); } - public static HttpWebResponse RequestAndGetResponse(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) + public static HttpWebResponse RequestAndGetResponse(string url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, IDictionary headers = null) { return RequestAndGetResponse(new Uri(url), timeout, readWriteTimeout, cookies, headers); } - public static HttpWebResponse RequestAndGetResponse(Uri uri, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) + public static HttpWebResponse RequestAndGetResponse(Uri uri, int? timeout = null, int? readWriteTimeout = null, string cookies = null, IDictionary headers = null) { var webRequest = CreateRequest(uri, timeout, readWriteTimeout, cookies, headers); @@ -215,7 +215,7 @@ private static HttpWebRequest CreateRequest(string url, int? timeout = null, int return CreateRequest(new Uri(url), timeout, readWriteTimeout, cookies); } - private static HttpWebRequest CreateRequest(Uri url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, Dictionary headers = null) + private static HttpWebRequest CreateRequest(Uri url, int? timeout = null, int? readWriteTimeout = null, string cookies = null, IDictionary headers = null) { var webRequest = (HttpWebRequest)WebRequest.Create(url); webRequest.Timeout = timeout ?? Settings.CoreWebDownloadConnectionTimeout.Value; diff --git a/src/SIM.Pipelines/Agent/AgentHelper.cs b/src/SIM.Pipelines/Agent/AgentHelper.cs index f137b949..b84bef7b 100644 --- a/src/SIM.Pipelines/Agent/AgentHelper.cs +++ b/src/SIM.Pipelines/Agent/AgentHelper.cs @@ -101,7 +101,7 @@ public static void DeleteAgentFiles([NotNull] Instance instance) #region Package installation - public static void InstallPackage([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) + public static void InstallPackage([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] IDictionary headers = null) { Assert.ArgumentNotNull(instance, nameof(instance)); Assert.ArgumentNotNull(module, nameof(module)); @@ -116,7 +116,7 @@ public static void InstallPackage([NotNull] Instance instance, [NotNull] Product ExecuteAgent(AgentFiles.StatusFileName, statusUrl, AgentFiles.InstallPackageFileName, installPackageUrl, PackageInstalling, PackageInstalled, cookies: cookies, headers: headers); } - public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) + public static void PerformPostStepAction([NotNull] Instance instance, [NotNull] Product module, [CanBeNull] string cookies = null, [CanBeNull] IDictionary headers = null) { XmlDocument xmlDocument = module.Manifest; bool skipPostActions = module.SkipPostActions; @@ -190,7 +190,7 @@ public static string GetUrl(Instance instance, string pageName, string value = n } [NotNull] - public static string Request([NotNull] string url, [NotNull] string pageName, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) + public static string Request([NotNull] string url, [NotNull] string pageName, [CanBeNull] string cookies = null, [CanBeNull] IDictionary headers = null) { Assert.ArgumentNotNull(url, nameof(url)); Assert.ArgumentNotNullOrEmpty(pageName, nameof(pageName)); @@ -222,7 +222,7 @@ public static string Request([NotNull] string url, [NotNull] string pageName, [C #region Private methods - private static void ExecuteAgent(string statusFileName, string statusUrl, string agentName, string operationUrl, string operationStartedStatus, string operationCompletedStatus, string cookies = null, Dictionary headers = null) + private static void ExecuteAgent(string statusFileName, string statusUrl, string agentName, string operationUrl, string operationStartedStatus, string operationCompletedStatus, string cookies = null, IDictionary headers = null) { // Call agent main operation var status = Request(operationUrl, agentName, cookies: cookies, headers: headers); diff --git a/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs b/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs index 37b526f3..db1b1d46 100644 --- a/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs +++ b/src/SIM.Pipelines/InstallModules/InstallModulesArgs.cs @@ -25,13 +25,13 @@ public class InstallModulesArgs : ProcessorArgs public string Cookies { get; } - public Dictionary Headers { get; } + public IDictionary Headers { get; } #endregion #region Constructors - public InstallModulesArgs([NotNull] Instance instance, [NotNull] IEnumerable modules, [CanBeNull] SqlConnectionStringBuilder connectionString = null, [CanBeNull] string cookies = null, [CanBeNull] Dictionary headers = null) + public InstallModulesArgs([NotNull] Instance instance, [NotNull] IEnumerable modules, [CanBeNull] SqlConnectionStringBuilder connectionString = null, [CanBeNull] string cookies = null, [CanBeNull] IDictionary headers = null) { Assert.ArgumentNotNull(instance, nameof(instance)); Assert.ArgumentNotNull(modules, nameof(modules)); diff --git a/src/SIM.Tool.Base/Pipelines/InstallModulesWizardArgs.cs b/src/SIM.Tool.Base/Pipelines/InstallModulesWizardArgs.cs index b1ad7597..4f481746 100644 --- a/src/SIM.Tool.Base/Pipelines/InstallModulesWizardArgs.cs +++ b/src/SIM.Tool.Base/Pipelines/InstallModulesWizardArgs.cs @@ -23,7 +23,7 @@ public class InstallModulesWizardArgs : WizardArgs public string Cookies { get; } - public Dictionary Headers { get; } + public IDictionary Headers { get; } #endregion @@ -33,7 +33,7 @@ public InstallModulesWizardArgs() { } - public InstallModulesWizardArgs(Instance instance, string cookies = null, Dictionary headers = null) + public InstallModulesWizardArgs(Instance instance, string cookies = null, IDictionary headers = null) { Instance = instance; if (instance != null) From 3a03954ac644286d436fa046e7169785eaaa5ba6 Mon Sep 17 00:00:00 2001 From: Dmitry Kolinchuk Date: Fri, 19 Mar 2021 13:41:29 +0200 Subject: [PATCH 05/17] #557 Implement the Credentials dialog --- .../Dialogs/CredentialsContext.cs | 18 +++++ .../Dialogs/CredentialsDialog.xaml | 34 ++++++++ .../Dialogs/CredentialsDialog.xaml.cs | 47 +++++++++++ ...nstallModulesForSitecore9AndLaterButton.cs | 79 +++++++++++++++---- src/SIM.Tool.Windows/SIM.Tool.Windows.csproj | 12 ++- .../SitecoreIdServerAuth.cs | 6 +- .../SitecoreServicesClientAuth.cs | 2 +- 7 files changed, 179 insertions(+), 19 deletions(-) create mode 100644 src/SIM.Tool.Windows/Dialogs/CredentialsContext.cs create mode 100644 src/SIM.Tool.Windows/Dialogs/CredentialsDialog.xaml create mode 100644 src/SIM.Tool.Windows/Dialogs/CredentialsDialog.xaml.cs rename src/SIM.Tool.Windows/UserControls/{Helpers => SitecoreAuthentication}/SitecoreIdServerAuth.cs (90%) rename src/SIM.Tool.Windows/UserControls/{Helpers => SitecoreAuthentication}/SitecoreServicesClientAuth.cs (96%) diff --git a/src/SIM.Tool.Windows/Dialogs/CredentialsContext.cs b/src/SIM.Tool.Windows/Dialogs/CredentialsContext.cs new file mode 100644 index 00000000..87085eca --- /dev/null +++ b/src/SIM.Tool.Windows/Dialogs/CredentialsContext.cs @@ -0,0 +1,18 @@ +namespace SIM.Tool.Windows.Dialogs +{ + public class CredentialsContext + { + public string UserName { get; } + + public string Password { get; } + + public string Uri { get; } + + public CredentialsContext(string userName, string password, string uri = null) + { + this.UserName = userName; + this.Password = password; + this.Uri = uri; + } + } +} \ No newline at end of file diff --git a/src/SIM.Tool.Windows/Dialogs/CredentialsDialog.xaml b/src/SIM.Tool.Windows/Dialogs/CredentialsDialog.xaml new file mode 100644 index 00000000..3bed0501 --- /dev/null +++ b/src/SIM.Tool.Windows/Dialogs/CredentialsDialog.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + +