Files
Umbraco-CMS/src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs

390 lines
16 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
2014-08-18 20:42:56 +02:00
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Models.ContentEditing;
using Umbraco.Cms.Core.Models.Packaging;
using Umbraco.Cms.Core.Packaging;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Semver;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Core.WebAssets;
using Umbraco.Cms.Web.Common.ActionsResults;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.Authorization;
using Umbraco.Extensions;
Merge remote-tracking branch 'origin/v8/dev' into netcore/dev # Conflicts: # build/NuSpecs/UmbracoCms.Core.nuspec # build/NuSpecs/UmbracoCms.Web.nuspec # src/SolutionInfo.cs # src/Umbraco.Core/Cache/CacheKeys.cs # src/Umbraco.Core/Composing/TypeFinder.cs # src/Umbraco.Core/Configuration/GlobalSettings.cs # src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs # src/Umbraco.Core/Configuration/IGlobalSettings.cs # src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs # src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs # src/Umbraco.Core/Constants-AppSettings.cs # src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs # src/Umbraco.Core/Extensions/StringExtensions.cs # src/Umbraco.Core/Extensions/UriExtensions.cs # src/Umbraco.Core/IO/IOHelper.cs # src/Umbraco.Core/IO/PhysicalFileSystem.cs # src/Umbraco.Core/Media/Exif/MathEx.cs # src/Umbraco.Core/Media/UploadAutoFillProperties.cs # src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs # src/Umbraco.Core/Models/Membership/User.cs # src/Umbraco.Core/Models/UserExtensions.cs # src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs # src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs # src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs # src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs # src/Umbraco.Core/Routing/AliasUrlProvider.cs # src/Umbraco.Core/Routing/DefaultUrlProvider.cs # src/Umbraco.Core/Routing/UriUtility.cs # src/Umbraco.Core/Routing/UrlProviderExtensions.cs # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Core/RuntimeOptions.cs # src/Umbraco.Core/RuntimeState.cs # src/Umbraco.Core/Security/BackOfficeUserStore.cs # src/Umbraco.Core/Security/ContentPermissions.cs # src/Umbraco.Core/Sync/ApplicationUrlHelper.cs # src/Umbraco.Core/Trees/TreeNode.cs # src/Umbraco.Core/Udi.cs # src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs # src/Umbraco.Examine/Umbraco.Examine.csproj # src/Umbraco.Infrastructure/Examine/ContentValueSetValidator.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs # src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs # src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs # src/Umbraco.Infrastructure/Scoping/Scope.cs # src/Umbraco.Infrastructure/Search/ExamineComponent.cs # src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs # src/Umbraco.Infrastructure/Services/Implement/ContentService.cs # src/Umbraco.Infrastructure/Services/Implement/MediaService.cs # src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs # src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs # src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/LocksTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/UserExtensionsTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelperTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Examine/UmbracoContentValueSetValidatorTests.cs # src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs # src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config # src/Umbraco.Tests/TestHelpers/SettingsForTests.cs # src/Umbraco.Tests/Testing/TestDatabase.cs # src/Umbraco.Tests/Web/Controllers/ContentControllerUnitTests.cs # src/Umbraco.Tests/Web/Controllers/FilterAllowedOutgoingContentAttributeTests.cs # src/Umbraco.Tests/Web/Controllers/MediaControllerUnitTests.cs # src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs # src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs # src/Umbraco.Web.BackOffice/Controllers/ContentController.cs # src/Umbraco.Web.BackOffice/Controllers/EntityController.cs # src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs # src/Umbraco.Web.BackOffice/Controllers/MediaController.cs # src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs # src/Umbraco.Web.BackOffice/Controllers/TourController.cs # src/Umbraco.Web.BackOffice/Controllers/UserGroupEditorAuthorizationHelper.cs # src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs # src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs # src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs # src/Umbraco.Web.BackOffice/Services/IconService.cs # src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs # src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs # src/Umbraco.Web.BackOffice/Trees/FileSystemTreeController.cs # src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs # src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs # src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js # src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html # src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml # src/Umbraco.Web.UI/config/umbracoSettings.Release.config # src/Umbraco.Web/Cache/MemberCacheRefresher.cs # src/Umbraco.Web/Composing/ModuleInjector.cs # src/Umbraco.Web/Editors/BackOfficeController.cs # src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs # src/Umbraco.Web/Editors/ContentTypeController.cs # src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs # src/Umbraco.Web/Editors/Filters/MediaItemSaveValidationAttribute.cs # src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs # src/Umbraco.Web/Editors/TinyMceController.cs # src/Umbraco.Web/Editors/UserGroupsController.cs # src/Umbraco.Web/Editors/UsersController.cs # src/Umbraco.Web/ImageCropperTemplateExtensions.cs # src/Umbraco.Web/Logging/WebProfiler.cs # src/Umbraco.Web/Logging/WebProfilerProvider.cs # src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs # src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs # src/Umbraco.Web/Mvc/JsonNetResult.cs # src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs # src/Umbraco.Web/Mvc/RenderRouteHandler.cs # src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs # src/Umbraco.Web/RoutableDocumentFilter.cs # src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs # src/Umbraco.Web/Routing/NotFoundHandlerHelper.cs # src/Umbraco.Web/Routing/PublishedRouter.cs # src/Umbraco.Web/Runtime/WebInitialComposer.cs # src/Umbraco.Web/Scheduling/KeepAlive.cs # src/Umbraco.Web/Security/AppBuilderExtensions.cs # src/Umbraco.Web/Security/BackOfficeClaimsIdentityFactory.cs # src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs # src/Umbraco.Web/Trees/DictionaryTreeController.cs # src/Umbraco.Web/Trees/LanguageTreeController.cs # src/Umbraco.Web/Trees/LogViewerTreeController.cs # src/Umbraco.Web/Trees/PackagesTreeController.cs # src/Umbraco.Web/UmbracoApplication.cs # src/Umbraco.Web/UmbracoApplicationBase.cs # src/Umbraco.Web/UmbracoInjectedModule.cs # src/Umbraco.Web/WebApi/Filters/AdminUsersAuthorizeAttribute.cs # src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs # src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs # src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs # src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs
2021-03-05 15:36:27 +01:00
using Umbraco.Cms.Core;
namespace Umbraco.Cms.Web.BackOffice.Controllers
2014-08-18 20:42:56 +02:00
{
/// <summary>
/// A controller used for installing packages and managing all of the data in the packages section in the back office
/// </summary>
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Authorize(Policy = AuthorizationPolicies.SectionAccessPackages)]
2014-08-18 20:42:56 +02:00
public class PackageInstallController : UmbracoAuthorizedJsonController
{
2019-11-19 23:15:11 +00:00
private readonly IUmbracoVersion _umbracoVersion;
private readonly IHostingEnvironment _hostingEnvironment;
2020-02-27 10:41:43 +01:00
private readonly IUmbracoApplicationLifetime _umbracoApplicationLifetime;
private readonly IRuntimeMinifier _runtimeMinifier;
private readonly IPackagingService _packagingService;
private readonly ILogger<PackageInstallController> _logger;
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
private readonly ILocalizedTextService _localizedTextService;
public PackageInstallController(
IUmbracoVersion umbracoVersion,
IHostingEnvironment hostingEnvironment,
IUmbracoApplicationLifetime umbracoApplicationLifetime,
IRuntimeMinifier runtimeMinifier,
IPackagingService packagingService,
ILogger<PackageInstallController> logger,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
ILocalizedTextService localizedTextService)
{
_umbracoVersion = umbracoVersion ?? throw new ArgumentNullException(nameof(umbracoVersion));
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
_umbracoApplicationLifetime = umbracoApplicationLifetime ?? throw new ArgumentNullException(nameof(umbracoApplicationLifetime));
_runtimeMinifier = runtimeMinifier ?? throw new ArgumentNullException(nameof(runtimeMinifier));
_packagingService = packagingService ?? throw new ArgumentNullException(nameof(packagingService));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
_backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor));
_localizedTextService = localizedTextService ?? throw new ArgumentNullException(nameof(localizedTextService));
}
/// <summary>
/// This checks if this package & version is already installed
/// </summary>
/// <param name="name"></param>
/// <param name="version"></param>
/// <returns></returns>
[HttpPost]
public IActionResult ValidateInstalled(string name, string version)
{
var installType = _packagingService.GetPackageInstallType(name, SemVersion.Parse(version), out _);
if (installType == PackageInstallType.AlreadyInstalled)
return BadRequest();
return Ok();
}
2016-06-13 19:43:04 +02:00
[HttpPost]
public IActionResult Uninstall(int packageId)
2016-06-13 19:43:04 +02:00
{
2017-05-30 10:50:09 +02:00
try
{
var package = _packagingService.GetInstalledPackageById(packageId);
if (package == null) return NotFound();
2016-06-13 19:43:04 +02:00
var summary = _packagingService.UninstallPackage(package.Name, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
2016-06-13 19:43:04 +02:00
2017-05-30 10:50:09 +02:00
//now get all other packages by this name since we'll uninstall all versions
foreach (var installed in _packagingService.GetAllInstalledPackages()
.Where(x => x.Name == package.Name && x.Id != package.Id))
2017-05-30 10:50:09 +02:00
{
//remove from the xml
_packagingService.DeleteInstalledPackage(installed.Id, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
2017-05-30 10:50:09 +02:00
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to uninstall.");
2017-05-30 10:50:09 +02:00
throw;
}
2016-06-13 19:43:04 +02:00
return Ok();
}
2016-06-14 14:12:10 +02:00
private void PopulateFromPackageData(LocalPackageInstallModel model)
{
var zipFile = new FileInfo(Path.Combine(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Packages), model.ZipFileName));
2019-01-15 22:08:08 +11:00
var ins = _packagingService.GetCompiledPackageInfo(zipFile);
2016-06-14 14:12:10 +02:00
model.Name = ins.Name;
model.Author = ins.Author;
model.AuthorUrl = ins.AuthorUrl;
2019-02-14 16:00:58 +01:00
model.Contributors = ins.Contributors;
model.IconUrl = ins.IconUrl;
2016-06-14 14:12:10 +02:00
model.License = ins.License;
model.LicenseUrl = ins.LicenseUrl;
model.Readme = ins.Readme;
model.ConflictingMacroAliases = ins.Warnings.ConflictingMacros.ToDictionary(x => x.Name, x => x.Alias);
2020-02-02 01:43:15 +00:00
model.ConflictingStyleSheetNames = ins.Warnings.ConflictingStylesheets.ToDictionary(x => x.Name, x => x.Alias);
model.ConflictingTemplateAliases = ins.Warnings.ConflictingTemplates.ToDictionary(x => x.Name, x => x.Alias);
model.ContainsUnsecureFiles = ins.Warnings.UnsecureFiles.Any();
2016-06-14 14:12:10 +02:00
model.Url = ins.Url;
model.Version = ins.Version;
model.UmbracoVersion = ins.UmbracoVersionRequirementsType == RequirementsType.Strict
? ins.UmbracoVersion.ToString(3)
2016-06-14 14:12:10 +02:00
: string.Empty;
2016-07-20 12:44:15 +02:00
2016-06-14 14:12:10 +02:00
//now we need to check for version comparison
model.IsCompatible = true;
if (ins.UmbracoVersionRequirementsType == RequirementsType.Strict)
2016-06-14 14:12:10 +02:00
{
var packageMinVersion = ins.UmbracoVersion;
if (_umbracoVersion.Version < packageMinVersion)
2016-06-14 14:12:10 +02:00
{
model.IsCompatible = false;
}
}
}
[HttpPost]
public async Task<ActionResult<LocalPackageInstallModel>> UploadLocalPackage(List<IFormFile> file)
{
//must have a file
if (file.Count == 0)
return NotFound();
var model = new LocalPackageInstallModel
{
2019-01-15 22:08:08 +11:00
//Generate a new package Id for this, we'll use this later for tracking, when persisting, saving the file, etc...
PackageGuid = Guid.NewGuid()
};
//get the files
foreach (var formFile in file)
{
Merge remote-tracking branch 'origin/v8/dev' into netcore/dev # Conflicts: # build/NuSpecs/UmbracoCms.Core.nuspec # build/NuSpecs/UmbracoCms.Web.nuspec # src/SolutionInfo.cs # src/Umbraco.Core/Cache/CacheKeys.cs # src/Umbraco.Core/Composing/TypeFinder.cs # src/Umbraco.Core/Configuration/GlobalSettings.cs # src/Umbraco.Core/Configuration/GlobalSettingsExtensions.cs # src/Umbraco.Core/Configuration/IGlobalSettings.cs # src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs # src/Umbraco.Core/Configuration/UmbracoSettings/ContentSectionExtensions.cs # src/Umbraco.Core/Constants-AppSettings.cs # src/Umbraco.Core/Editors/UserEditorAuthorizationHelper.cs # src/Umbraco.Core/Extensions/StringExtensions.cs # src/Umbraco.Core/Extensions/UriExtensions.cs # src/Umbraco.Core/IO/IOHelper.cs # src/Umbraco.Core/IO/PhysicalFileSystem.cs # src/Umbraco.Core/Media/Exif/MathEx.cs # src/Umbraco.Core/Media/UploadAutoFillProperties.cs # src/Umbraco.Core/Models/Mapping/UserMapDefinition.cs # src/Umbraco.Core/Models/Membership/User.cs # src/Umbraco.Core/Models/UserExtensions.cs # src/Umbraco.Core/Packaging/PackageDefinitionXmlParser.cs # src/Umbraco.Core/PropertyEditors/ListViewConfiguration.cs # src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs # src/Umbraco.Core/PropertyEditors/ValueConverters/MultiNodeTreePickerValueConverter.cs # src/Umbraco.Core/Routing/AliasUrlProvider.cs # src/Umbraco.Core/Routing/DefaultUrlProvider.cs # src/Umbraco.Core/Routing/UriUtility.cs # src/Umbraco.Core/Routing/UrlProviderExtensions.cs # src/Umbraco.Core/Runtime/CoreRuntime.cs # src/Umbraco.Core/RuntimeOptions.cs # src/Umbraco.Core/RuntimeState.cs # src/Umbraco.Core/Security/BackOfficeUserStore.cs # src/Umbraco.Core/Security/ContentPermissions.cs # src/Umbraco.Core/Sync/ApplicationUrlHelper.cs # src/Umbraco.Core/Trees/TreeNode.cs # src/Umbraco.Core/Udi.cs # src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs # src/Umbraco.Examine/Umbraco.Examine.csproj # src/Umbraco.Infrastructure/Examine/ContentValueSetValidator.cs # src/Umbraco.Infrastructure/Migrations/Install/DatabaseBuilder.cs # src/Umbraco.Infrastructure/Packaging/PackageDataInstallation.cs # src/Umbraco.Infrastructure/Persistence/SqlSyntax/SqlServerSyntaxProvider.cs # src/Umbraco.Infrastructure/Scoping/Scope.cs # src/Umbraco.Infrastructure/Search/ExamineComponent.cs # src/Umbraco.Infrastructure/Security/IdentityMapDefinition.cs # src/Umbraco.Infrastructure/Services/Implement/ContentService.cs # src/Umbraco.Infrastructure/Services/Implement/MediaService.cs # src/Umbraco.Infrastructure/Services/Implement/NotificationService.cs # src/Umbraco.Persistence.SqlCe/SqlCeSyntaxProvider.cs # src/Umbraco.Tests.Integration/Umbraco.Infrastructure/Persistence/LocksTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Core/Models/UserExtensionsTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Editors/UserEditorAuthorizationHelperTests.cs # src/Umbraco.Tests.UnitTests/Umbraco.Infrastructure/Examine/UmbracoContentValueSetValidatorTests.cs # src/Umbraco.Tests/Configurations/UmbracoSettings/ContentElementTests.cs # src/Umbraco.Tests/Configurations/UmbracoSettings/umbracoSettings.config # src/Umbraco.Tests/TestHelpers/SettingsForTests.cs # src/Umbraco.Tests/Testing/TestDatabase.cs # src/Umbraco.Tests/Web/Controllers/ContentControllerUnitTests.cs # src/Umbraco.Tests/Web/Controllers/FilterAllowedOutgoingContentAttributeTests.cs # src/Umbraco.Tests/Web/Controllers/MediaControllerUnitTests.cs # src/Umbraco.Web.BackOffice/Controllers/BackOfficeServerVariables.cs # src/Umbraco.Web.BackOffice/Controllers/CodeFileController.cs # src/Umbraco.Web.BackOffice/Controllers/ContentController.cs # src/Umbraco.Web.BackOffice/Controllers/EntityController.cs # src/Umbraco.Web.BackOffice/Controllers/MacrosController.cs # src/Umbraco.Web.BackOffice/Controllers/MediaController.cs # src/Umbraco.Web.BackOffice/Controllers/PackageInstallController.cs # src/Umbraco.Web.BackOffice/Controllers/TourController.cs # src/Umbraco.Web.BackOffice/Controllers/UserGroupEditorAuthorizationHelper.cs # src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingContentAttribute.cs # src/Umbraco.Web.BackOffice/Filters/FilterAllowedOutgoingMediaAttribute.cs # src/Umbraco.Web.BackOffice/Mapping/ContentMapDefinition.cs # src/Umbraco.Web.BackOffice/Services/IconService.cs # src/Umbraco.Web.BackOffice/Trees/ContentTreeController.cs # src/Umbraco.Web.BackOffice/Trees/ContentTreeControllerBase.cs # src/Umbraco.Web.BackOffice/Trees/FileSystemTreeController.cs # src/Umbraco.Web.BackOffice/Trees/MediaTreeController.cs # src/Umbraco.Web.Common/Extensions/FormCollectionExtensions.cs # src/Umbraco.Web.UI.Client/src/common/resources/content.resource.js # src/Umbraco.Web.UI.Client/src/views/content/overlays/publish.html # src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/editors/media.controller.js # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/da.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en.xml # src/Umbraco.Web.UI.NetCore/umbraco/config/lang/en_us.xml # src/Umbraco.Web.UI/config/umbracoSettings.Release.config # src/Umbraco.Web/Cache/MemberCacheRefresher.cs # src/Umbraco.Web/Composing/ModuleInjector.cs # src/Umbraco.Web/Editors/BackOfficeController.cs # src/Umbraco.Web/Editors/Binders/ContentModelBinderHelper.cs # src/Umbraco.Web/Editors/ContentTypeController.cs # src/Umbraco.Web/Editors/Filters/ContentSaveValidationAttribute.cs # src/Umbraco.Web/Editors/Filters/MediaItemSaveValidationAttribute.cs # src/Umbraco.Web/Editors/Filters/UserGroupAuthorizationAttribute.cs # src/Umbraco.Web/Editors/TinyMceController.cs # src/Umbraco.Web/Editors/UserGroupsController.cs # src/Umbraco.Web/Editors/UsersController.cs # src/Umbraco.Web/ImageCropperTemplateExtensions.cs # src/Umbraco.Web/Logging/WebProfiler.cs # src/Umbraco.Web/Logging/WebProfilerProvider.cs # src/Umbraco.Web/Macros/PublishedContentHashtableConverter.cs # src/Umbraco.Web/Mvc/EnsurePublishedContentRequestAttribute.cs # src/Umbraco.Web/Mvc/JsonNetResult.cs # src/Umbraco.Web/Mvc/MemberAuthorizeAttribute.cs # src/Umbraco.Web/Mvc/RenderRouteHandler.cs # src/Umbraco.Web/PropertyEditors/MediaPickerPropertyEditor.cs # src/Umbraco.Web/PropertyEditors/MultiNodeTreePickerPropertyEditor.cs # src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs # src/Umbraco.Web/RoutableDocumentFilter.cs # src/Umbraco.Web/Routing/ContentFinderByUrlAlias.cs # src/Umbraco.Web/Routing/NotFoundHandlerHelper.cs # src/Umbraco.Web/Routing/PublishedRouter.cs # src/Umbraco.Web/Runtime/WebInitialComposer.cs # src/Umbraco.Web/Scheduling/KeepAlive.cs # src/Umbraco.Web/Security/AppBuilderExtensions.cs # src/Umbraco.Web/Security/BackOfficeClaimsIdentityFactory.cs # src/Umbraco.Web/Security/Providers/UmbracoMembershipProvider.cs # src/Umbraco.Web/Trees/DictionaryTreeController.cs # src/Umbraco.Web/Trees/LanguageTreeController.cs # src/Umbraco.Web/Trees/LogViewerTreeController.cs # src/Umbraco.Web/Trees/PackagesTreeController.cs # src/Umbraco.Web/UmbracoApplication.cs # src/Umbraco.Web/UmbracoApplicationBase.cs # src/Umbraco.Web/UmbracoInjectedModule.cs # src/Umbraco.Web/WebApi/Filters/AdminUsersAuthorizeAttribute.cs # src/Umbraco.Web/WebApi/Filters/CheckIfUserTicketDataIsStaleAttribute.cs # src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForContentAttribute.cs # src/Umbraco.Web/WebApi/Filters/EnsureUserPermissionForMediaAttribute.cs # src/Umbraco.Web/WebApi/MemberAuthorizeAttribute.cs
2021-03-05 15:36:27 +01:00
var fileName = formFile.FileName.Trim(Constants.CharArrays.DoubleQuote);
var ext = fileName.Substring(fileName.LastIndexOf('.') + 1).ToLower();
if (ext.InvariantEquals("zip") || ext.InvariantEquals("umb"))
{
2019-01-15 22:08:08 +11:00
//we always save package files to /App_Data/packages/package-guid.umb for processing as a standard so lets copy.
var packagesFolder = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Packages);
2019-01-15 22:08:08 +11:00
Directory.CreateDirectory(packagesFolder);
var packageFile = Path.Combine(packagesFolder, model.PackageGuid + ".umb");
2016-07-20 12:44:15 +02:00
using (var stream = System.IO.File.Create(packageFile))
2019-01-15 22:08:08 +11:00
{
await formFile.CopyToAsync(stream);
}
model.ZipFileName = Path.GetFileName(packageFile);
2016-06-14 14:12:10 +02:00
//Populate the model from the metadata in the package file (zip file)
PopulateFromPackageData(model);
2014-08-18 20:42:56 +02:00
var installType = _packagingService.GetPackageInstallType(model.Name, SemVersion.Parse(model.Version), out var alreadyInstalled);
2016-07-20 12:44:15 +02:00
if (installType == PackageInstallType.AlreadyInstalled)
{
//this package is already installed
return ValidationErrorResult.CreateNotificationValidationErrorResult(
_localizedTextService.Localize("packager/packageAlreadyInstalled"));
}
2016-07-20 12:44:15 +02:00
model.OriginalVersion = installType == PackageInstallType.Upgrade ? alreadyInstalled.Version : null;
}
else
{
2020-01-20 11:37:19 +01:00
model.Notifications.Add(new BackOfficeNotification(
_localizedTextService.Localize("speechBubbles/operationFailedHeader"),
_localizedTextService.Localize("media/disallowedFileType"),
NotificationStyle.Warning));
}
2016-07-20 12:44:15 +02:00
}
return model;
}
/// <summary>
/// Gets the package from Our to install
/// </summary>
/// <param name="packageGuid"></param>
/// <returns></returns>
2014-08-18 20:42:56 +02:00
[HttpGet]
public async Task<ActionResult<LocalPackageInstallModel>> Fetch(string packageGuid)
2014-08-18 20:42:56 +02:00
{
//Default path
2019-01-15 22:08:08 +11:00
string fileName = packageGuid + ".umb";
if (System.IO.File.Exists(Path.Combine(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Packages), fileName)) == false)
2014-08-18 20:42:56 +02:00
{
var packageFile = await _packagingService.FetchPackageFileAsync(
2019-01-15 22:08:08 +11:00
Guid.Parse(packageGuid),
_umbracoVersion.Version,
_backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
2019-01-15 22:08:08 +11:00
fileName = packageFile.Name;
2014-08-18 20:42:56 +02:00
}
2016-06-14 14:12:10 +02:00
var model = new LocalPackageInstallModel
{
PackageGuid = Guid.Parse(packageGuid),
2019-01-15 22:08:08 +11:00
ZipFileName = fileName
2016-06-14 14:12:10 +02:00
};
//Populate the model from the metadata in the package file (zip file)
PopulateFromPackageData(model);
var installType = _packagingService.GetPackageInstallType(model.Name, SemVersion.Parse(model.Version), out var alreadyInstalled);
if (installType == PackageInstallType.AlreadyInstalled)
{
return ValidationErrorResult.CreateNotificationValidationErrorResult(
_localizedTextService.Localize("packager/packageAlreadyInstalled"));
}
model.OriginalVersion = installType == PackageInstallType.Upgrade ? alreadyInstalled.Version : null;
2016-06-14 14:12:10 +02:00
return model;
2014-08-18 20:42:56 +02:00
}
/// <summary>
/// Extracts the package zip and gets the packages information
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
2014-08-18 20:42:56 +02:00
[HttpPost]
public ActionResult<PackageInstallModel> Import(PackageInstallModel model)
2014-08-18 20:42:56 +02:00
{
var zipFile = new FileInfo(Path.Combine(_hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.Packages), model.ZipFileName));
2019-01-15 22:08:08 +11:00
var packageInfo = _packagingService.GetCompiledPackageInfo(zipFile);
2016-06-14 14:12:10 +02:00
//now we need to check for version comparison
if (packageInfo.UmbracoVersionRequirementsType == RequirementsType.Strict)
2016-06-14 14:12:10 +02:00
{
var packageMinVersion = packageInfo.UmbracoVersion;
if (_umbracoVersion.Version < packageMinVersion)
return ValidationErrorResult.CreateNotificationValidationErrorResult(
_localizedTextService.Localize("packager/targetVersionMismatch", new[] {packageMinVersion.ToString()}));
2016-06-14 14:12:10 +02:00
}
var installType = _packagingService.GetPackageInstallType(packageInfo.Name, SemVersion.Parse(packageInfo.Version), out var alreadyInstalled);
var packageDefinition = PackageDefinition.FromCompiledPackage(packageInfo);
2019-01-15 22:08:08 +11:00
packageDefinition.PackagePath = zipFile.FullName;
packageDefinition.PackageId = model.PackageGuid; //We must re-map the original package GUID that was generated
switch (installType)
{
case PackageInstallType.AlreadyInstalled:
throw new InvalidOperationException("The package is already installed");
case PackageInstallType.NewInstall:
case PackageInstallType.Upgrade:
//save to the installedPackages.config, this will create a new entry with a new Id
if (!_packagingService.SaveInstalledPackage(packageDefinition))
return ValidationErrorResult.CreateNotificationValidationErrorResult("Could not save the package");
model.Id = packageDefinition.Id;
break;
default:
throw new ArgumentOutOfRangeException();
}
2014-08-18 20:42:56 +02:00
return model;
}
/// <summary>
/// Installs the package files
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
2014-08-18 20:42:56 +02:00
[HttpPost]
public PackageInstallModel InstallFiles(PackageInstallModel model)
{
var definition = _packagingService.GetInstalledPackageById(model.Id);
if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id);
2019-01-15 22:08:08 +11:00
var zipFile = new FileInfo(definition.PackagePath);
var installedFiles = _packagingService.InstallCompiledPackageFiles(definition, zipFile, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
2017-09-12 16:22:16 +02:00
//set a restarting marker and reset the app pool
2020-02-27 10:41:43 +01:00
_umbracoApplicationLifetime.Restart();
2017-09-23 10:08:18 +02:00
2017-09-12 16:22:16 +02:00
model.IsRestarting = true;
2017-09-12 16:22:16 +02:00
return model;
}
[HttpPost]
public PackageInstallModel CheckRestart(PackageInstallModel model)
{
if (model.IsRestarting == false) return model;
2020-02-27 10:41:43 +01:00
model.IsRestarting = _umbracoApplicationLifetime.IsRestarting;
2014-08-18 20:42:56 +02:00
return model;
}
/// <summary>
/// Installs the packages data/business logic
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
2014-08-18 20:42:56 +02:00
[HttpPost]
public PackageInstallModel InstallData(PackageInstallModel model)
{
var definition = _packagingService.GetInstalledPackageById(model.Id);
if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id);
2019-01-15 22:08:08 +11:00
var zipFile = new FileInfo(definition.PackagePath);
var installSummary = _packagingService.InstallCompiledPackageData(definition, zipFile, _backofficeSecurityAccessor.BackOfficeSecurity.GetUserId().ResultOr(0));
2019-01-15 22:08:08 +11:00
2014-08-18 20:42:56 +02:00
return model;
}
/// <summary>
/// Cleans up the package installation
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
2014-08-18 20:42:56 +02:00
[HttpPost]
public PackageInstallResult CleanUp(PackageInstallModel model)
2014-08-18 20:42:56 +02:00
{
var definition = _packagingService.GetInstalledPackageById(model.Id);
2019-01-15 22:08:08 +11:00
if (definition == null) throw new InvalidOperationException("Not package definition found with id " + model.Id);
var zipFile = new FileInfo(definition.PackagePath);
var packageInfo = _packagingService.GetCompiledPackageInfo(zipFile);
zipFile.Delete();
//bump cdf to be safe
_runtimeMinifier.Reset();
2016-06-14 14:12:10 +02:00
var redirectUrl = "";
if (!packageInfo.PackageView.IsNullOrWhiteSpace())
2016-06-14 14:12:10 +02:00
{
redirectUrl = $"/packages/packages/options/{model.Id}";
2016-06-14 14:12:10 +02:00
}
return new PackageInstallResult
{
Id = model.Id,
2019-01-15 22:08:08 +11:00
ZipFileName = model.ZipFileName,
PackageGuid = model.PackageGuid,
2016-06-14 14:12:10 +02:00
PostInstallationPath = redirectUrl
};
2016-06-14 14:12:10 +02:00
2014-08-18 20:42:56 +02:00
}
}
}