From 9f357173c3d88dcd1e437dec0b2dcd2200b9a057 Mon Sep 17 00:00:00 2001 From: Kenn Jacobsen Date: Mon, 3 Feb 2025 12:50:23 +0100 Subject: [PATCH] Enforce user start nodes for media uploads through the RTE (#18204) --- .../RichTextEditorPastedImages.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs b/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs index 8dbe6ad5b3..64e349c245 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/RichTextEditorPastedImages.cs @@ -8,12 +8,14 @@ using HtmlAgilityPack; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; +using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Exceptions; using Umbraco.Cms.Core.Hosting; using Umbraco.Cms.Core.IO; using Umbraco.Cms.Core.Media; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Models.PublishedContent; using Umbraco.Cms.Core.Routing; using Umbraco.Cms.Core.Services; @@ -38,6 +40,9 @@ public sealed class RichTextEditorPastedImages private readonly IUmbracoContextAccessor _umbracoContextAccessor; private readonly string _tempFolderAbsolutePath; private readonly IImageUrlGenerator _imageUrlGenerator; + private readonly IEntityService _entityService; + private readonly IUserService _userService; + private readonly AppCaches _appCaches; private readonly ContentSettings _contentSettings; private readonly Dictionary _uploadedImages = new(); @@ -67,6 +72,7 @@ public sealed class RichTextEditorPastedImages { } + [Obsolete("Use the non-obsolete constructor. Scheduled for removal in v14")] public RichTextEditorPastedImages( IUmbracoContextAccessor umbracoContextAccessor, ILogger logger, @@ -79,6 +85,39 @@ public sealed class RichTextEditorPastedImages IPublishedUrlProvider publishedUrlProvider, IImageUrlGenerator imageUrlGenerator, IOptions contentSettings) + : this( + umbracoContextAccessor, + logger, + hostingEnvironment, + mediaService, + contentTypeBaseServiceProvider, + mediaFileManager, + mediaUrlGenerators, + shortStringHelper, + publishedUrlProvider, + imageUrlGenerator, + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), + StaticServiceProvider.Instance.GetRequiredService(), + contentSettings) + { + } + + public RichTextEditorPastedImages( + IUmbracoContextAccessor umbracoContextAccessor, + ILogger logger, + IHostingEnvironment hostingEnvironment, + IMediaService mediaService, + IContentTypeBaseServiceProvider contentTypeBaseServiceProvider, + MediaFileManager mediaFileManager, + MediaUrlGeneratorCollection mediaUrlGenerators, + IShortStringHelper shortStringHelper, + IPublishedUrlProvider publishedUrlProvider, + IImageUrlGenerator imageUrlGenerator, + IEntityService entityService, + IUserService userService, + AppCaches appCaches, + IOptions contentSettings) { _umbracoContextAccessor = umbracoContextAccessor ?? throw new ArgumentNullException(nameof(umbracoContextAccessor)); @@ -92,6 +131,9 @@ public sealed class RichTextEditorPastedImages _shortStringHelper = shortStringHelper; _publishedUrlProvider = publishedUrlProvider; _imageUrlGenerator = imageUrlGenerator; + _entityService = entityService; + _userService = userService; + _appCaches = appCaches; _contentSettings = contentSettings.Value; _tempFolderAbsolutePath = _hostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempImageUploads); @@ -270,7 +312,7 @@ public sealed class RichTextEditorPastedImages : Constants.Conventions.MediaTypes.Image; IMedia mediaFile = mediaParentFolder == Guid.Empty - ? _mediaService.CreateMedia(mediaItemName, Constants.System.Root, mediaType, userId) + ? _mediaService.CreateMedia(mediaItemName, GetDefaultMediaRoot(userId), mediaType, userId) : _mediaService.CreateMedia(mediaItemName, mediaParentFolder, mediaType, userId); var fileInfo = new FileInfo(absoluteTempImagePath); @@ -354,4 +396,11 @@ public sealed class RichTextEditorPastedImages } private bool IsValidPath(string imagePath) => imagePath.StartsWith(_tempFolderAbsolutePath); + + private int GetDefaultMediaRoot(int userId) + { + IUser user = _userService.GetUserById(userId) ?? throw new ArgumentException("User could not be found"); + var userStartNodes = user.CalculateMediaStartNodeIds(_entityService, _appCaches); + return userStartNodes?.FirstOrDefault() ?? Constants.System.Root; + } }