From a5ff29ccc7457ecb7ea82744e405daf58cdc2d57 Mon Sep 17 00:00:00 2001 From: Shannon Date: Tue, 15 Jan 2019 22:59:13 +1100 Subject: [PATCH] Gets package uninstall working, fixes other UI issues with packages --- .../Packaging/CompiledPackageXmlParser.cs | 37 ++-- .../Packaging/PackageDefinitionXmlParser.cs | 2 + .../Packaging/PackageInstallation.cs | 1 + .../src/views/packages/overview.controller.js | 15 +- .../src/views/packages/overview.html | 34 ++- .../views/install-local.controller.js | 2 +- .../packages/views/installed.controller.js | 16 +- .../Controllers/InstallPackageController.cs | 196 ------------------ src/Umbraco.Web/Install/UmbracoInstallArea.cs | 8 - 9 files changed, 67 insertions(+), 244 deletions(-) delete mode 100644 src/Umbraco.Web/Install/Controllers/InstallPackageController.cs diff --git a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs index eb9cf46008..be9c69667a 100644 --- a/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs +++ b/src/Umbraco.Core/Packaging/CompiledPackageXmlParser.cs @@ -149,37 +149,50 @@ namespace Umbraco.Core.Packaging return path; } + /// + /// Parses the package actions stored in the package definition + /// + /// + /// + /// public IEnumerable GetPackageActions(XElement actionsElement, string packageName) { - if (actionsElement == null) { return new PackageAction[0]; } + if (actionsElement == null) return Enumerable.Empty(); - if (string.Equals("Actions", actionsElement.Name.LocalName) == false) - throw new ArgumentException($"Must be \"Actions\" as root", nameof(actionsElement)); + //invariant check ... because people can realy enter anything :/ + if (!string.Equals("actions", actionsElement.Name.LocalName, StringComparison.InvariantCultureIgnoreCase)) + throw new FormatException("Must be \"\" as root"); - return actionsElement.Elements("Action") - .Select(elemet => + if (!actionsElement.HasElements) return Enumerable.Empty(); + + var actionElementName = actionsElement.Elements().First().Name.LocalName; + + //invariant check ... because people can realy enter anything :/ + if (!string.Equals("action", actionElementName, StringComparison.InvariantCultureIgnoreCase)) + throw new FormatException("Must be \" { - var aliasAttr = elemet.Attribute("Alias"); + var aliasAttr = e.Attribute("alias") ?? e.Attribute("Alias"); //allow both ... because people can really enter anything :/ if (aliasAttr == null) - throw new ArgumentException("missing \"Alias\" atribute in alias element", nameof(actionsElement)); + throw new ArgumentException("missing \"alias\" atribute in alias element", nameof(actionsElement)); var packageAction = new PackageAction { - XmlData = elemet, + XmlData = e, Alias = aliasAttr.Value, PackageName = packageName, }; - - var attr = elemet.Attribute("runat"); + var attr = e.Attribute("runat") ?? e.Attribute("Runat"); //allow both ... because people can really enter anything :/ if (attr != null && Enum.TryParse(attr.Value, true, out ActionRunAt runAt)) { packageAction.RunAt = runAt; } - attr = elemet.Attribute("undo"); + attr = e.Attribute("undo") ?? e.Attribute("Undo"); //allow both ... because people can really enter anything :/ if (attr != null && bool.TryParse(attr.Value, out var undo)) { packageAction.Undo = undo; } - return packageAction; }).ToArray(); } diff --git a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs index 0d7adf8ece..45e6fd9845 100644 --- a/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs +++ b/src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs @@ -105,5 +105,7 @@ namespace Umbraco.Core.Packaging return packageXml; } + + } } diff --git a/src/Umbraco.Core/Packaging/PackageInstallation.cs b/src/Umbraco.Core/Packaging/PackageInstallation.cs index 4563d31560..7abf96b266 100644 --- a/src/Umbraco.Core/Packaging/PackageInstallation.cs +++ b/src/Umbraco.Core/Packaging/PackageInstallation.cs @@ -76,6 +76,7 @@ namespace Umbraco.Core.Packaging { //running this will update the PackageDefinition with the items being removed var summary = _packageDataInstallation.UninstallPackageData(package, userId); + summary.Actions = _parser.GetPackageActions(XElement.Parse(package.Actions), package.Name); //run actions before files are removed diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js index 4ca0015aa5..ccd86c6f6c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesOverviewController($scope, $route, $location, navigationService, $timeout, localStorageService) { + function PackagesOverviewController($scope, $location, localStorageService) { //Hack! // if there is a cookie value for packageInstallUri then we need to redirect there, @@ -9,12 +9,13 @@ // because it will double load it. // we will refresh and then navigate there. - var installPackageUri = localStorageService.get("packageInstallUri"); - const packageUri = $location.search().subview; + let installPackageUri = localStorageService.get("packageInstallUri"); + let packageUri = $location.search().subview; if (installPackageUri) { localStorageService.remove("packageInstallUri"); } + if (installPackageUri && installPackageUri !== "installed") { //navigate to the custom installer screen, if it is just "installed", then we'll //show the installed view @@ -23,6 +24,8 @@ else { var vm = this; + packageUri = installPackageUri ? installPackageUri : packageUri; //use the path stored in storage over the one in the current path + vm.page = {}; vm.page.name = "Packages"; vm.page.navigation = [ @@ -30,7 +33,7 @@ "name": "Packages", "icon": "icon-cloud", "view": "views/packages/views/repo.html", - "active": !packageUri || installPackageUri === "navigation" || packageUri === "navigation", + "active": !packageUri || packageUri === "navigation", "alias": "umbPackages", "action": function() { $location.search("subview", "navigation"); @@ -40,7 +43,7 @@ "name": "Installed", "icon": "icon-box", "view": "views/packages/views/installed.html", - "active": installPackageUri === "installed" || packageUri === "installed", + "active": packageUri === "installed", "alias": "umbInstalled", "action": function() { $location.search("subview", "installed"); @@ -50,7 +53,7 @@ "name": "Install local", "icon": "icon-add", "view": "views/packages/views/install-local.html", - "active": installPackageUri === "local" || packageUri === "local", + "active": packageUri === "local", "alias": "umbInstallLocal", "action": function() { $location.search("subview", "local"); diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/overview.html b/src/Umbraco.Web.UI.Client/src/views/packages/overview.html index 250dc889d6..84f594b48d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/overview.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/overview.html @@ -1,28 +1,24 @@
-
+ - + + - - + - + + - - + - - - - - +
diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js index 9c6c2bb7c5..6753fad942 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PackagesInstallLocalController($scope, $route, $location, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService, $q) { + function PackagesInstallLocalController($scope, Upload, umbRequestHelper, packageResource, localStorageService, $timeout, $window, localizationService, $q) { var vm = this; vm.state = "upload"; diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js index ce1d2cca0f..6e0e162e86 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/installed.controller.js @@ -13,6 +13,8 @@ }; vm.package = {}; + var labels = {}; + function init() { packageResource.getInstalled() .then(function (packs) { @@ -20,6 +22,16 @@ }); vm.installState.status = ""; vm.state = "list"; + + var labelKeys = [ + "packager_installStateUninstalling", + "packager_installStateComplete", + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + labels.installStateUninstalling = values[0]; + labels.installStateComplete = values[1]; + }); } function confirmUninstall(pck) { @@ -28,14 +40,14 @@ } function uninstallPackage(installedPackage) { - vm.installState.status = localizationService.localize("packager_installStateUninstalling"); + vm.installState.status = labels.installStateUninstalling; vm.installState.progress = "0"; packageResource.uninstall(installedPackage.id) .then(function () { if (installedPackage.files.length > 0) { - vm.installState.status = localizationService.localize("packager_installStateComplete"); + vm.installState.status = labels.installStateComplete; vm.installState.progress = "100"; //set this flag so that on refresh it shows the installed packages list diff --git a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs b/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs deleted file mode 100644 index 81cb1e2e39..0000000000 --- a/src/Umbraco.Web/Install/Controllers/InstallPackageController.cs +++ /dev/null @@ -1,196 +0,0 @@ -//using System; -//using System.Linq; -//using System.Net; -//using System.Net.Http; -//using System.Text; -//using System.Threading.Tasks; -//using System.Web; -//using System.Web.Http; -//using Newtonsoft.Json.Linq; -//using umbraco; -//using Umbraco.Core; -//using Umbraco.Web.Cache; -//using Umbraco.Core.Configuration; -//using Umbraco.Core.Models.Packaging; -//using Umbraco.Core.Services; -//using Umbraco.Web.Composing; -//using Umbraco.Web.Install.Models; -//using Umbraco.Web.WebApi; - -//namespace Umbraco.Web.Install.Controllers -//{ -// /// -// /// A controller for the installation process regarding packages -// /// -// /// -// /// Currently this is used for web services however we should/could eventually migrate the whole installer to MVC as it -// /// is a bit of a mess currently. -// /// -// [HttpInstallAuthorize] -// [AngularJsonOnlyConfiguration] -// [Obsolete("This is only used for the legacy way of installing starter kits in the back office")] -// //fixme: Is this used anymore?? -// public class InstallPackageController : ApiController -// { -// private readonly IPackagingService _packagingService; -// private readonly UmbracoContext _umbracoContext; - -// public InstallPackageController(IPackagingService packagingService, UmbracoContext umbracoContext) -// { -// _packagingService = packagingService; -// _umbracoContext = umbracoContext; -// } - -// /// -// /// Empty action, useful for retrieving the base url for this controller -// /// -// /// -// [HttpGet] -// public HttpResponseMessage Index() -// { -// throw new NotImplementedException(); -// } - -// /// -// /// Connects to the repo, downloads the package and creates the definition -// /// -// /// -// /// -// [HttpPost] -// public async Task DownloadPackageFiles(InstallPackageModel model) -// { -// var packageFile = await _packagingService.FetchPackageFileAsync( -// model.KitGuid, -// UmbracoVersion.Current, -// UmbracoContext.Current.Security.CurrentUser.Id); - - -// var packageInfo = _packagingService.GetCompiledPackageInfo(packageFile); -// if (packageInfo == null) throw new InvalidOperationException("Could not read package file " + packageFile); - -// //save to the installedPackages.config -// var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo); -// _packagingService.SaveInstalledPackage(packageDefinition); - -// return Json(new -// { -// success = true, -// packageId = packageDefinition.Id, -// packageFile = packageInfo.PackageFileName, -// percentage = 10, -// message = "Downloading starter kit files..." -// }, HttpStatusCode.OK); -// } - -// /// -// /// Installs the files in the package -// /// -// /// -// [HttpPost] -// public HttpResponseMessage InstallPackageFiles(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// var definition = _packagingService.GetInstalledPackageById(model.PackageId); -// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - -// _packagingService.InstallCompiledPackageFiles(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 20, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Ensures the app pool is restarted -// /// -// /// -// [HttpPost] -// public HttpResponseMessage RestartAppPool() -// { -// Current.RestartAppPool(Request.TryGetHttpContext().Result); -// return Json(new -// { -// success = true, -// percentage = 25, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Checks if the app pool has completed restarted -// /// -// /// -// [HttpPost] -// public HttpResponseMessage CheckAppPoolRestart() -// { -// if (Request.TryGetHttpContext().Result.Application.AllKeys.Contains("AppPoolRestarting")) -// { -// return Request.CreateResponse(HttpStatusCode.BadRequest); -// } - -// return Json(new -// { -// percentage = 30, -// success = true, -// }, HttpStatusCode.OK); -// } - -// /// -// /// Installs the business logic portion of the package after app restart -// /// -// /// -// [HttpPost] -// public HttpResponseMessage InstallBusinessLogic(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// var definition = _packagingService.GetInstalledPackageById(model.PackageId); -// if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.PackageId); - -// _packagingService.InstallCompiledPackageData(definition, model.PackageFile, _umbracoContext.Security.GetUserId().ResultOr(0)); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 70, -// message = "Installing starter kit files" -// }, HttpStatusCode.OK); -// } - -// /// -// /// Cleans up the package installation -// /// -// /// -// [HttpPost] -// public HttpResponseMessage CleanupInstallation(InstallPackageModel model) -// { -// model.PackageFile = HttpUtility.UrlDecode(model.PackageFile); - -// return Json(new -// { -// success = true, -// ManifestId = model.PackageId, -// model.PackageFile, -// percentage = 100, -// message = "Starter kit has been installed" -// }, HttpStatusCode.OK); -// } - -// private HttpResponseMessage Json(object jsonObject, HttpStatusCode status) -// { -// var response = Request.CreateResponse(status); -// var json = JObject.FromObject(jsonObject); -// response.Content = new StringContent(json.ToString(), Encoding.UTF8, "application/json"); -// return response; -// } -// } - -//} diff --git a/src/Umbraco.Web/Install/UmbracoInstallArea.cs b/src/Umbraco.Web/Install/UmbracoInstallArea.cs index 2b44abd4ab..398ed7b245 100644 --- a/src/Umbraco.Web/Install/UmbracoInstallArea.cs +++ b/src/Umbraco.Web/Install/UmbracoInstallArea.cs @@ -32,14 +32,6 @@ namespace Umbraco.Web.Install new { controller = "Install", action = "Index", id = UrlParameter.Optional }, new[] { typeof(InstallController).Namespace }); - //TODO: We can remove this when we re-build the back office package installer - //Create the install routes - context.MapHttpRoute( - "Umbraco_install_packages", - "Install/PackageInstaller/{action}/{id}", - new { controller = "InstallPackage", action = "Index", id = UrlParameter.Optional }, - new[] { typeof(InstallPackageController).Namespace }); - context.MapHttpRoute( "umbraco-install-api", "install/api/{action}/{id}",