Merge branch 'v11/dev' into contrib

This commit is contained in:
Sebastiaan Janssen
2023-03-16 08:07:25 +01:00
30 changed files with 183 additions and 11 deletions

View File

@@ -9,6 +9,7 @@ using Umbraco.Cms.Web.Common.DependencyInjection;
namespace Umbraco.Cms.Core.Configuration.Grid;
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridConfig : IGridConfig
{
public GridConfig(

View File

@@ -158,6 +158,7 @@ public class ContentSettings
internal const bool StaticDisableDeleteWhenReferenced = false;
internal const bool StaticDisableUnpublishWhenReferenced = false;
internal const bool StaticAllowEditInvariantFromNonDefault = false;
internal const bool StaticShowDomainWarnings = true;
/// <summary>
/// Gets or sets a value for the content notification settings.
@@ -262,4 +263,15 @@ public class ContentSettings
/// </summary>
[DefaultValue(StaticDisallowedUploadFiles)]
public string[] DisallowedUploadedFileExtensions { get; set; } = StaticDisallowedUploadFiles.Split(',');
/// <summary>
/// Gets or sets the allowed external host for media. If empty only relative paths are allowed.
/// </summary>
public string[] AllowedMediaHosts { get; set; } = Array.Empty<string>();
/// <summary>
/// Gets or sets a value indicating whether to show domain warnings.
/// </summary>
[DefaultValue(StaticShowDomainWarnings)]
public bool ShowDomainWarnings { get; set; } = StaticShowDomainWarnings;
}

View File

@@ -4,6 +4,7 @@ using Umbraco.Cms.Core.Configuration.Grid;
namespace Umbraco.Cms.Core.PropertyEditors;
[DataContract]
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridEditor : IGridEditorConfig
{
public GridEditor()

View File

@@ -3,6 +3,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration for the media picker value editor.
/// </summary>
[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerConfiguration : IIgnoreUserStartNodesConfig
{
[ConfigurationField("multiPicker", "Pick multiple items", "boolean")]

View File

@@ -11,6 +11,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration editor for the media picker value editor.
/// </summary>
[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerConfigurationEditor : ConfigurationEditor<MediaPickerConfiguration>
{
// Scheduled for removal in v12

View File

@@ -5,6 +5,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration for the nested content value editor.
/// </summary>
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentConfiguration
{
[ConfigurationField("contentTypes", "Element Types", "views/propertyeditors/nestedcontent/nestedcontent.doctypepicker.html", Description = "Select the Element Types to use as models for the items.")]

View File

@@ -11,6 +11,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration editor for the nested content value editor.
/// </summary>
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentConfigurationEditor : ConfigurationEditor<NestedContentConfiguration>
{
// Scheduled for removal in v12

View File

@@ -9,6 +9,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// The media picker property value converter.
/// </summary>
[DefaultPropertyValueConverter]
[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerValueConverter : PropertyValueConverterBase
{
// hard-coding "image" here but that's how it works at UI level too

View File

@@ -169,7 +169,10 @@ public class BackOfficeExamineSearcher : IBackOfficeExamineSearcher
var allLangs = _languageService.GetAllLanguages().Select(x => x.IsoCode.ToLowerInvariant()).ToList();
// the chars [*-_] in the query will mess everything up so let's remove those
query = Regex.Replace(query, "[\\*\\-_]", string.Empty);
// However we cannot just remove - and _ since these signify a space, so we instead replace them with that.
query = Regex.Replace(query, "[\\*]", string.Empty);
query = Regex.Replace(query, "[\\-_]", " ");
//check if text is surrounded by single or double quotes, if so, then exact match
var surroundedByQuotes = Regex.IsMatch(query, "^\".*?\"$")

View File

@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.Deploy;
/// <remarks>
/// These extension methods will be removed in Umbraco 13.
/// </remarks>
[Obsolete("The grid is obsolete, will be removed in V13")]
public static class GridCellValueConnectorExtensions
{
/// <summary>

View File

@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.Models;
/// <summary>
/// A model representing the value saved for the grid
/// </summary>
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridValue
{
[JsonProperty("name")]
@@ -43,6 +44,7 @@ public class GridValue
public JToken? Config { get; set; }
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridArea
{
[JsonProperty("grid")]
@@ -58,6 +60,7 @@ public class GridValue
public JToken? Config { get; set; }
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridControl
{
[JsonProperty("value")]
@@ -73,6 +76,7 @@ public class GridValue
public JToken? Config { get; set; }
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridEditor
{
[JsonProperty("alias")]

View File

@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration for the grid value editor.
/// </summary>
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridConfiguration : IIgnoreUserStartNodesConfig
{
// TODO: Make these strongly typed, for now this works though

View File

@@ -13,6 +13,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// Represents the configuration editor for the grid value editor.
/// </summary>
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridConfigurationEditor : ConfigurationEditor<GridConfiguration>
{
// Scheduled for removal in v12
@@ -31,6 +32,7 @@ public class GridConfigurationEditor : ConfigurationEditor<GridConfiguration>
}
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridValidator : IValueValidator
{
public IEnumerable<ValidationResult> Validate(object? rawValue, string? valueType, object? dataTypeConfiguration)
@@ -51,6 +53,7 @@ public class GridValidator : IValueValidator
}
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridEditorModel
{
public GridEditorTemplateModel[]? Templates { get; set; }
@@ -58,11 +61,13 @@ public class GridEditorModel
public int Columns { get; set; }
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridEditorTemplateModel
{
public GridEditorSectionModel[]? Sections { get; set; }
}
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridEditorSectionModel
{
public int Grid { get; set; }

View File

@@ -31,6 +31,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
Group = Constants.PropertyEditors.Groups.RichContent,
ValueEditorIsReusable = false,
IsDeprecated = true)]
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridPropertyEditor : DataEditor
{
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;

View File

@@ -14,6 +14,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
/// <summary>
/// Parses the grid value into indexable values
/// </summary>
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridPropertyIndexValueFactory : IPropertyIndexValueFactory
{
public IEnumerable<KeyValuePair<string, IEnumerable<object?>>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)

View File

@@ -28,6 +28,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
Icon = Constants.Icons.MediaImage,
IsDeprecated = false,
ValueEditorIsReusable = true)]
[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerPropertyEditor : DataEditor
{
private readonly IEditorConfigurationParser _editorConfigurationParser;

View File

@@ -28,6 +28,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
Icon = "icon-thumbnail-list",
ValueEditorIsReusable = false,
IsDeprecated = true)]
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentPropertyEditor : DataEditor
{
public const string ContentTypeAliasPropertyKey = "ncContentTypeAlias";

View File

@@ -10,6 +10,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
/// <summary>
/// A handler for NestedContent used to bind to notifications
/// </summary>
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentPropertyHandler : ComplexPropertyEditorContentNotificationHandler
{
protected override string EditorAlias => Constants.PropertyEditors.Aliases.NestedContent;

View File

@@ -14,6 +14,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// This ensures that the grid config is merged in with the front-end value
/// </summary>
[DefaultPropertyValueConverter(typeof(JsonValueConverter))] // this shadows the JsonValueConverter
[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridValueConverter : JsonValueConverter
{
private readonly IGridConfig _config;

View File

@@ -16,6 +16,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// content.
/// </summary>
[DefaultPropertyValueConverter(typeof(JsonValueConverter))]
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentManyValueConverter : NestedContentValueConverterBase
{
private readonly IProfilingLogger _proflog;

View File

@@ -15,6 +15,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// content.
/// </summary>
[DefaultPropertyValueConverter(typeof(JsonValueConverter))]
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentSingleValueConverter : NestedContentValueConverterBase
{
private readonly IProfilingLogger _proflog;

View File

@@ -8,6 +8,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
[Obsolete("Nested content is obsolete, will be removed in V13")]
public abstract class NestedContentValueConverterBase : PropertyValueConverterBase
{
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;

View File

@@ -5,8 +5,10 @@ using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.ContentApps;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Cms.Core.Dictionary;
@@ -65,6 +67,7 @@ public class ContentController : ContentControllerBase
private readonly ISqlContext _sqlContext;
private readonly IUmbracoMapper _umbracoMapper;
private readonly IUserService _userService;
private readonly ContentSettings _contentSettings;
[ActivatorUtilitiesConstructor]
public ContentController(
@@ -91,7 +94,8 @@ public class ContentController : ContentControllerBase
ICoreScopeProvider scopeProvider,
IAuthorizationService authorizationService,
IContentVersionService contentVersionService,
ICultureImpactFactory cultureImpactFactory)
ICultureImpactFactory cultureImpactFactory,
IOptions<ContentSettings> contentSettings)
: base(cultureDictionary, loggerFactory, shortStringHelper, eventMessages, localizedTextService, serializer)
{
_propertyEditors = propertyEditors;
@@ -115,7 +119,63 @@ public class ContentController : ContentControllerBase
_logger = loggerFactory.CreateLogger<ContentController>();
_scopeProvider = scopeProvider;
_allLangs = new Lazy<IDictionary<string, ILanguage>>(() =>
_localizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase));
_localizationService.GetAllLanguages().ToDictionary(x => x.IsoCode, x => x, StringComparer.InvariantCultureIgnoreCase));
_contentSettings = contentSettings.Value;
}
[Obsolete("Use constructor that accepts ContentSettings as a parameter, scheduled for removal in V13")]
public ContentController(
ICultureDictionary cultureDictionary,
ILoggerFactory loggerFactory,
IShortStringHelper shortStringHelper,
IEventMessagesFactory eventMessages,
ILocalizedTextService localizedTextService,
PropertyEditorCollection propertyEditors,
IContentService contentService,
IUserService userService,
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
IContentTypeService contentTypeService,
IUmbracoMapper umbracoMapper,
IPublishedUrlProvider publishedUrlProvider,
IDomainService domainService,
IDataTypeService dataTypeService,
ILocalizationService localizationService,
IFileService fileService,
INotificationService notificationService,
ActionCollection actionCollection,
ISqlContext sqlContext,
IJsonSerializer serializer,
ICoreScopeProvider scopeProvider,
IAuthorizationService authorizationService,
IContentVersionService contentVersionService,
ICultureImpactFactory cultureImpactFactory)
: this(
cultureDictionary,
loggerFactory,
shortStringHelper,
eventMessages,
localizedTextService,
propertyEditors,
contentService,
userService,
backofficeSecurityAccessor,
contentTypeService,
umbracoMapper,
publishedUrlProvider,
domainService,
dataTypeService,
localizationService,
fileService,
notificationService,
actionCollection,
sqlContext,
serializer,
scopeProvider,
authorizationService,
contentVersionService,
cultureImpactFactory,
StaticServiceProvider.Instance.GetRequiredService<IOptions<ContentSettings>>())
{
}
[Obsolete("Use constructor that accepts ICultureImpactService as a parameter, scheduled for removal in V12")]
@@ -1710,6 +1770,11 @@ public class ContentController : ContentControllerBase
/// <param name="globalNotifications"></param>
internal void AddDomainWarnings(IContent? persistedContent, string[]? culturesPublished, SimpleNotificationModel globalNotifications)
{
if (_contentSettings.ShowDomainWarnings is false)
{
return;
}
// Don't try to verify if no cultures were published
if (culturesPublished is null)
{

View File

@@ -1,10 +1,14 @@
using System.Web;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.IO;
using Umbraco.Cms.Core.Media;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Web.Common.Attributes;
using Umbraco.Cms.Web.Common.DependencyInjection;
using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.Controllers;
@@ -17,13 +21,31 @@ public class ImagesController : UmbracoAuthorizedApiController
{
private readonly IImageUrlGenerator _imageUrlGenerator;
private readonly MediaFileManager _mediaFileManager;
private ContentSettings _contentSettings;
[Obsolete("Use non obsolete-constructor. Scheduled for removal in Umbraco 13.")]
public ImagesController(
MediaFileManager mediaFileManager,
IImageUrlGenerator imageUrlGenerator)
: this(mediaFileManager,
imageUrlGenerator,
StaticServiceProvider.Instance.GetRequiredService<IOptionsMonitor<ContentSettings>>())
{
}
[ActivatorUtilitiesConstructor]
public ImagesController(
MediaFileManager mediaFileManager,
IImageUrlGenerator imageUrlGenerator,
IOptionsMonitor<ContentSettings> contentSettingsMonitor)
{
_mediaFileManager = mediaFileManager;
_imageUrlGenerator = imageUrlGenerator;
_contentSettings = contentSettingsMonitor.CurrentValue;
contentSettingsMonitor.OnChange(x => _contentSettings = x);
}
/// <summary>
@@ -58,7 +80,7 @@ public class ImagesController : UmbracoAuthorizedApiController
var ext = Path.GetExtension(encodedImagePath);
// check if imagePath is local to prevent open redirect
if (!Uri.IsWellFormedUriString(encodedImagePath, UriKind.Relative))
if (!IsAllowed(encodedImagePath))
{
return Unauthorized();
}
@@ -90,12 +112,33 @@ public class ImagesController : UmbracoAuthorizedApiController
ImageCropMode = ImageCropMode.Max,
CacheBusterValue = rnd
});
if (Url.IsLocalUrl(imageUrl))
if (imageUrl is not null)
{
return new LocalRedirectResult(imageUrl, false);
return new RedirectResult(imageUrl, false);
}
return Unauthorized();
return NotFound();
}
private bool IsAllowed(string encodedImagePath)
{
if(Uri.IsWellFormedUriString(encodedImagePath, UriKind.Relative))
{
return true;
}
var builder = new UriBuilder(encodedImagePath);
foreach (var allowedMediaHost in _contentSettings.AllowedMediaHosts)
{
if (string.Equals(builder.Host, allowedMediaHost, StringComparison.InvariantCultureIgnoreCase))
{
return true;
}
}
return false;
}
/// <summary>

View File

@@ -12,6 +12,7 @@ using Umbraco.Extensions;
namespace Umbraco.Cms.Web.BackOffice.PropertyEditors;
[PluginController(Constants.Web.Mvc.BackOfficeApiArea)]
[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentController : UmbracoAuthorizedJsonController
{
private readonly IContentTypeService _contentTypeService;

View File

@@ -1,6 +1,7 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.Filters;
using Umbraco.Cms.Core.Routing;
using Umbraco.Cms.Web.Common.ActionsResults;
using Umbraco.Cms.Web.Common.Routing;
namespace Umbraco.Cms.Web.Common.Controllers;
@@ -15,9 +16,11 @@ internal class PublishedRequestFilterAttribute : ResultFilterAttribute
/// </summary>
public override void OnResultExecuting(ResultExecutingContext context)
{
if (context.Result is not null)
if (context.Result is MaintenanceResult)
{
// If the result is already set, we just skip the execution
// If the result is already set to a maintenance result we can't do anything
// Since the umbraco pipeline has not run.
// Fortunately we don't need to either.
return;
}

View File

@@ -4,6 +4,7 @@ using Umbraco.Cms.Core.Models.PublishedContent;
namespace Umbraco.Extensions;
[Obsolete("The grid is obsolete, will be removed in V13")]
public static class GridTemplateExtensions
{
public static IHtmlContent GetGridHtml(this IHtmlHelper html, IPublishedProperty property, string framework = "bootstrap3")

View File

@@ -3,7 +3,7 @@ angular.module("umbraco.install").controller("Umbraco.Install.UserController", f
$scope.majorVersion = Umbraco.Sys.ServerVariables.application.version;
$scope.passwordPattern = /.*/;
$scope.installer.current.model.subscribeToNewsLetter = $scope.installer.current.model.subscribeToNewsLetter || false;
setTelemetryLevelAndDescription($scope.installer.current.model.telemetryIndex ?? 1);
setTelemetryLevelAndDescription($scope.installer.current.model.telemetryIndex ?? 2);
if ($scope.installer.current.model.minNonAlphaNumericLength > 0) {
var exp = "";

View File

@@ -38,6 +38,8 @@ public class UmbLoginStatusController : SurfaceController
return CurrentUmbracoPage();
}
MergeRouteValuesToModel(model);
var isLoggedIn = HttpContext.User.Identity?.IsAuthenticated ?? false;
if (isLoggedIn)
@@ -56,4 +58,16 @@ public class UmbLoginStatusController : SurfaceController
// Redirect to current page by default.
return RedirectToCurrentUmbracoPage();
}
/// <summary>
/// We pass in values via encrypted route values so they cannot be tampered with and merge them into the model for use
/// </summary>
/// <param name="model"></param>
private void MergeRouteValuesToModel(PostRedirectModel model)
{
if (RouteData.Values.TryGetValue(nameof(PostRedirectModel.RedirectUrl), out var redirectUrl) && redirectUrl is not null)
{
model.RedirectUrl = redirectUrl.ToString();
}
}
}

View File

@@ -4,9 +4,11 @@ using System.Globalization;
using System.Linq;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Actions;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Dictionary;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Mapping;
@@ -266,7 +268,8 @@ public class ContentControllerTests
Mock.Of<ICoreScopeProvider>(),
Mock.Of<IAuthorizationService>(),
Mock.Of<IContentVersionService>(),
Mock.Of<ICultureImpactFactory>());
Mock.Of<ICultureImpactFactory>(),
new OptionsWrapper<ContentSettings>(new ContentSettings()));
return controller;
}