Merge remote-tracking branch 'origin/v10/dev' into v11/dev

This commit is contained in:
Nikolaj
2023-08-22 10:24:26 +02:00
15 changed files with 464 additions and 92 deletions

View File

@@ -48,9 +48,43 @@ public class CurrentUserController : UmbracoAuthorizedJsonController
private readonly IShortStringHelper _shortStringHelper;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IUserDataService _userDataService;
private readonly IFileStreamSecurityValidator? _fileStreamSecurityValidator; // make non nullable in v14
private readonly IUserService _userService;
[ActivatorUtilitiesConstructor]
public CurrentUserController(
MediaFileManager mediaFileManager,
IOptionsSnapshot<ContentSettings> contentSettings,
IHostingEnvironment hostingEnvironment,
IImageUrlGenerator imageUrlGenerator,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
IUserService userService,
IUmbracoMapper umbracoMapper,
IBackOfficeUserManager backOfficeUserManager,
ILocalizedTextService localizedTextService,
AppCaches appCaches,
IShortStringHelper shortStringHelper,
IPasswordChanger<BackOfficeIdentityUser> passwordChanger,
IUserDataService userDataService,
IFileStreamSecurityValidator fileStreamSecurityValidator)
{
_mediaFileManager = mediaFileManager;
_contentSettings = contentSettings.Value;
_hostingEnvironment = hostingEnvironment;
_imageUrlGenerator = imageUrlGenerator;
_backofficeSecurityAccessor = backofficeSecurityAccessor;
_userService = userService;
_umbracoMapper = umbracoMapper;
_backOfficeUserManager = backOfficeUserManager;
_localizedTextService = localizedTextService;
_appCaches = appCaches;
_shortStringHelper = shortStringHelper;
_passwordChanger = passwordChanger;
_userDataService = userDataService;
_fileStreamSecurityValidator = fileStreamSecurityValidator;
}
[Obsolete("Use constructor overload that has fileStreamSecurityValidator, scheduled for removal in v14")]
public CurrentUserController(
MediaFileManager mediaFileManager,
IOptionsSnapshot<ContentSettings> contentSettings,
@@ -254,6 +288,7 @@ public class CurrentUserController : UmbracoAuthorizedJsonController
_contentSettings,
_hostingEnvironment,
_imageUrlGenerator,
_fileStreamSecurityValidator,
_backofficeSecurityAccessor.BackOfficeSecurity?.GetUserId().Result ?? 0);
}

View File

@@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
@@ -51,6 +52,7 @@ public class MediaController : ContentControllerBase
{
private static readonly Semaphore _postAddFileSemaphore = new(1, 1);
private readonly AppCaches _appCaches;
private readonly IFileStreamSecurityValidator? _fileStreamSecurityValidator; // make non nullable in v14
private readonly IAuthorizationService _authorizationService;
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
private readonly ContentSettings _contentSettings;
@@ -67,6 +69,58 @@ public class MediaController : ContentControllerBase
private readonly ISqlContext _sqlContext;
private readonly IUmbracoMapper _umbracoMapper;
[ActivatorUtilitiesConstructor]
public MediaController(
ICultureDictionary cultureDictionary,
ILoggerFactory loggerFactory,
IShortStringHelper shortStringHelper,
IEventMessagesFactory eventMessages,
ILocalizedTextService localizedTextService,
IOptionsSnapshot<ContentSettings> contentSettings,
IMediaTypeService mediaTypeService,
IMediaService mediaService,
IEntityService entityService,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
IUmbracoMapper umbracoMapper,
IDataTypeService dataTypeService,
ISqlContext sqlContext,
IContentTypeBaseServiceProvider contentTypeBaseServiceProvider,
IRelationService relationService,
PropertyEditorCollection propertyEditors,
MediaFileManager mediaFileManager,
MediaUrlGeneratorCollection mediaUrlGenerators,
IHostingEnvironment hostingEnvironment,
IImageUrlGenerator imageUrlGenerator,
IJsonSerializer serializer,
IAuthorizationService authorizationService,
AppCaches appCaches,
IFileStreamSecurityValidator streamSecurityValidator)
: base(cultureDictionary, loggerFactory, shortStringHelper, eventMessages, localizedTextService, serializer)
{
_shortStringHelper = shortStringHelper;
_contentSettings = contentSettings.Value;
_mediaTypeService = mediaTypeService;
_mediaService = mediaService;
_entityService = entityService;
_backofficeSecurityAccessor = backofficeSecurityAccessor;
_umbracoMapper = umbracoMapper;
_dataTypeService = dataTypeService;
_localizedTextService = localizedTextService;
_sqlContext = sqlContext;
_contentTypeBaseServiceProvider = contentTypeBaseServiceProvider;
_relationService = relationService;
_propertyEditors = propertyEditors;
_mediaFileManager = mediaFileManager;
_mediaUrlGenerators = mediaUrlGenerators;
_hostingEnvironment = hostingEnvironment;
_logger = loggerFactory.CreateLogger<MediaController>();
_imageUrlGenerator = imageUrlGenerator;
_authorizationService = authorizationService;
_appCaches = appCaches;
_fileStreamSecurityValidator = streamSecurityValidator;
}
[Obsolete("Use constructor overload that has fileStreamSecurityValidator, scheduled for removal in v14")]
public MediaController(
ICultureDictionary cultureDictionary,
ILoggerFactory loggerFactory,
@@ -731,6 +785,17 @@ public class MediaController : ContentControllerBase
continue;
}
using var stream = new MemoryStream();
await formFile.CopyToAsync(stream);
if (_fileStreamSecurityValidator != null && _fileStreamSecurityValidator.IsConsideredSafe(stream) == false)
{
tempFiles.Notifications.Add(new BackOfficeNotification(
_localizedTextService.Localize("speechBubbles", "operationFailedHeader"),
_localizedTextService.Localize("media", "fileSecurityValidationFailure"),
NotificationStyle.Warning));
continue;
}
if (string.IsNullOrEmpty(mediaTypeAlias))
{
mediaTypeAlias = Constants.Conventions.MediaTypes.File;
@@ -808,11 +873,8 @@ public class MediaController : ContentControllerBase
IMedia createdMediaItem = _mediaService.CreateMedia(mediaItemName, parentId.Value, mediaTypeAlias,
_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.Id ?? -1);
await using (Stream stream = formFile.OpenReadStream())
{
createdMediaItem.SetValue(_mediaFileManager, _mediaUrlGenerators, _shortStringHelper,
_contentTypeBaseServiceProvider, Constants.Conventions.Media.File, fileName, stream);
}
Attempt<OperationResult?> saveResult = _mediaService.Save(createdMediaItem,
_backofficeSecurityAccessor.BackOfficeSecurity?.CurrentUser?.Id ?? -1);

View File

@@ -55,6 +55,7 @@ public class UsersController : BackOfficeNotificationsController
private readonly GlobalSettings _globalSettings;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IFileStreamSecurityValidator? _fileStreamSecurityValidator; // make non nullable in v14
private readonly IImageUrlGenerator _imageUrlGenerator;
private readonly LinkGenerator _linkGenerator;
private readonly ILocalizedTextService _localizedTextService;
@@ -72,6 +73,58 @@ public class UsersController : BackOfficeNotificationsController
private readonly WebRoutingSettings _webRoutingSettings;
[ActivatorUtilitiesConstructor]
public UsersController(
MediaFileManager mediaFileManager,
IOptionsSnapshot<ContentSettings> contentSettings,
IHostingEnvironment hostingEnvironment,
ISqlContext sqlContext,
IImageUrlGenerator imageUrlGenerator,
IOptionsSnapshot<SecuritySettings> securitySettings,
IEmailSender emailSender,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
AppCaches appCaches,
IShortStringHelper shortStringHelper,
IUserService userService,
ILocalizedTextService localizedTextService,
IUmbracoMapper umbracoMapper,
IOptionsSnapshot<GlobalSettings> globalSettings,
IBackOfficeUserManager backOfficeUserManager,
ILoggerFactory loggerFactory,
LinkGenerator linkGenerator,
IBackOfficeExternalLoginProviders externalLogins,
UserEditorAuthorizationHelper userEditorAuthorizationHelper,
IPasswordChanger<BackOfficeIdentityUser> passwordChanger,
IHttpContextAccessor httpContextAccessor,
IOptions<WebRoutingSettings> webRoutingSettings,
IFileStreamSecurityValidator fileStreamSecurityValidator)
{
_mediaFileManager = mediaFileManager;
_contentSettings = contentSettings.Value;
_hostingEnvironment = hostingEnvironment;
_sqlContext = sqlContext;
_imageUrlGenerator = imageUrlGenerator;
_securitySettings = securitySettings.Value;
_emailSender = emailSender;
_backofficeSecurityAccessor = backofficeSecurityAccessor;
_appCaches = appCaches;
_shortStringHelper = shortStringHelper;
_userService = userService;
_localizedTextService = localizedTextService;
_umbracoMapper = umbracoMapper;
_globalSettings = globalSettings.Value;
_userManager = backOfficeUserManager;
_loggerFactory = loggerFactory;
_linkGenerator = linkGenerator;
_externalLogins = externalLogins;
_userEditorAuthorizationHelper = userEditorAuthorizationHelper;
_passwordChanger = passwordChanger;
_logger = _loggerFactory.CreateLogger<UsersController>();
_httpContextAccessor = httpContextAccessor;
_fileStreamSecurityValidator = fileStreamSecurityValidator;
_webRoutingSettings = webRoutingSettings.Value;
}
[Obsolete("Use constructor overload that has fileStreamSecurityValidator, scheduled for removal in v14")]
public UsersController(
MediaFileManager mediaFileManager,
IOptionsSnapshot<ContentSettings> contentSettings,
@@ -139,13 +192,15 @@ public class UsersController : BackOfficeNotificationsController
[AppendUserModifiedHeader("id")]
[Authorize(Policy = AuthorizationPolicies.AdminUserEditsRequireAdmin)]
public IActionResult PostSetAvatar(int id, IList<IFormFile> file) => PostSetAvatarInternal(file, _userService,
public IActionResult PostSetAvatar(int id, IList<IFormFile> file)
=> PostSetAvatarInternal(file, _userService,
_appCaches.RuntimeCache, _mediaFileManager, _shortStringHelper, _contentSettings, _hostingEnvironment,
_imageUrlGenerator, id);
_imageUrlGenerator,_fileStreamSecurityValidator, id);
internal static IActionResult PostSetAvatarInternal(IList<IFormFile> files, IUserService userService,
IAppCache cache, MediaFileManager mediaFileManager, IShortStringHelper shortStringHelper,
ContentSettings contentSettings, IHostingEnvironment hostingEnvironment, IImageUrlGenerator imageUrlGenerator,
IFileStreamSecurityValidator? fileStreamSecurityValidator,
int id)
{
if (files is null)
@@ -187,9 +242,14 @@ public class UsersController : BackOfficeNotificationsController
//generate a path of known data, we don't want this path to be guessable
user.Avatar = "UserAvatars/" + (user.Id + safeFileName).GenerateHash<SHA1>() + "." + ext;
using (Stream fs = file.OpenReadStream())
//todo implement Filestreamsecurity
using (var ms = new MemoryStream())
{
mediaFileManager.FileSystem.AddFile(user.Avatar, fs, true);
file.CopyTo(ms);
if(fileStreamSecurityValidator != null && fileStreamSecurityValidator.IsConsideredSafe(ms) == false)
return new ValidationErrorResult("One or more file security analyzers deemed the contents of the file to be unsafe");
mediaFileManager.FileSystem.AddFile(user.Avatar, ms, true);
}
userService.Save(user);