Gets package uninstall working, fixes other UI issues with packages

This commit is contained in:
Shannon
2019-01-15 22:59:13 +11:00
parent 44ab0991ce
commit a5ff29ccc7
9 changed files with 67 additions and 244 deletions

View File

@@ -149,37 +149,50 @@ namespace Umbraco.Core.Packaging
return path;
}
/// <summary>
/// Parses the package actions stored in the package definition
/// </summary>
/// <param name="actionsElement"></param>
/// <param name="packageName"></param>
/// <returns></returns>
public IEnumerable<PackageAction> GetPackageActions(XElement actionsElement, string packageName)
{
if (actionsElement == null) { return new PackageAction[0]; }
if (actionsElement == null) return Enumerable.Empty<PackageAction>();
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 \"<actions>\" as root");
return actionsElement.Elements("Action")
.Select(elemet =>
if (!actionsElement.HasElements) return Enumerable.Empty<PackageAction>();
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 \"<action\" as element");
return actionsElement.Elements(actionElementName)
.Select(e =>
{
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();
}

View File

@@ -105,5 +105,7 @@ namespace Umbraco.Core.Packaging
return packageXml;
}
}
}

View File

@@ -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

View File

@@ -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");

View File

@@ -1,28 +1,24 @@
<div data-element="editor-packages" ng-controller="Umbraco.Editors.Packages.OverviewController as vm" class="clearfix">
<form name="packagesForm" ng-submit="save()" novalidate val-form-manager>
<umb-editor-view footer="false">
<umb-editor-view footer="false">
<umb-editor-header
name="vm.page.name"
name-locked="true"
hide-icon="true"
hide-description="true"
navigation="vm.page.navigation"
hide-alias="true">
</umb-editor-header>
<umb-editor-header
name="vm.page.name"
name-locked="true"
hide-icon="true"
hide-description="true"
navigation="vm.page.navigation"
hide-alias="true">
</umb-editor-header>
<umb-editor-container>
<umb-editor-container>
<umb-editor-sub-views
sub-views="vm.page.navigation" model="vm.page">
</umb-editor-sub-views>
<umb-editor-sub-views
sub-views="vm.page.navigation" model="vm.page">
</umb-editor-sub-views>
</umb-editor-container>
</umb-editor-container>
</umb-editor-view>
</form>
</umb-editor-view>
</div>

View File

@@ -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";

View File

@@ -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

View File

@@ -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
//{
// /// <summary>
// /// A controller for the installation process regarding packages
// /// </summary>
// /// <remarks>
// /// 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.
// /// </remarks>
// [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;
// }
// /// <summary>
// /// Empty action, useful for retrieving the base url for this controller
// /// </summary>
// /// <returns></returns>
// [HttpGet]
// public HttpResponseMessage Index()
// {
// throw new NotImplementedException();
// }
// /// <summary>
// /// Connects to the repo, downloads the package and creates the definition
// /// </summary>
// /// <param name="model"></param>
// /// <returns></returns>
// [HttpPost]
// public async Task<HttpResponseMessage> 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);
// }
// /// <summary>
// /// Installs the files in the package
// /// </summary>
// /// <returns></returns>
// [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);
// }
// /// <summary>
// /// Ensures the app pool is restarted
// /// </summary>
// /// <returns></returns>
// [HttpPost]
// public HttpResponseMessage RestartAppPool()
// {
// Current.RestartAppPool(Request.TryGetHttpContext().Result);
// return Json(new
// {
// success = true,
// percentage = 25,
// message = "Installing starter kit files"
// }, HttpStatusCode.OK);
// }
// /// <summary>
// /// Checks if the app pool has completed restarted
// /// </summary>
// /// <returns></returns>
// [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);
// }
// /// <summary>
// /// Installs the business logic portion of the package after app restart
// /// </summary>
// /// <returns></returns>
// [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);
// }
// /// <summary>
// /// Cleans up the package installation
// /// </summary>
// /// <returns></returns>
// [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;
// }
// }
//}

View File

@@ -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}",