diff --git a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
index be13776da8..d4cfcb9f37 100644
--- a/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
+++ b/src/Umbraco.Core/Configuration/Grid/GridConfig.cs
@@ -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(
diff --git a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs
index 5a82d860bb..290836d31e 100644
--- a/src/Umbraco.Core/Configuration/Models/ContentSettings.cs
+++ b/src/Umbraco.Core/Configuration/Models/ContentSettings.cs
@@ -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;
///
/// Gets or sets a value for the content notification settings.
@@ -262,4 +263,15 @@ public class ContentSettings
///
[DefaultValue(StaticDisallowedUploadFiles)]
public string[] DisallowedUploadedFileExtensions { get; set; } = StaticDisallowedUploadFiles.Split(',');
+
+ ///
+ /// Gets or sets the allowed external host for media. If empty only relative paths are allowed.
+ ///
+ public string[] AllowedMediaHosts { get; set; } = Array.Empty();
+
+ ///
+ /// Gets or sets a value indicating whether to show domain warnings.
+ ///
+ [DefaultValue(StaticShowDomainWarnings)]
+ public bool ShowDomainWarnings { get; set; } = StaticShowDomainWarnings;
}
diff --git a/src/Umbraco.Core/PropertyEditors/GridEditor.cs b/src/Umbraco.Core/PropertyEditors/GridEditor.cs
index d661fa9704..2ce26bdb79 100644
--- a/src/Umbraco.Core/PropertyEditors/GridEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/GridEditor.cs
@@ -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()
diff --git a/src/Umbraco.Core/PropertyEditors/MediaPickerConfiguration.cs b/src/Umbraco.Core/PropertyEditors/MediaPickerConfiguration.cs
index 055f4fea4d..92a206065b 100644
--- a/src/Umbraco.Core/PropertyEditors/MediaPickerConfiguration.cs
+++ b/src/Umbraco.Core/PropertyEditors/MediaPickerConfiguration.cs
@@ -3,6 +3,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration for the media picker value editor.
///
+[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerConfiguration : IIgnoreUserStartNodesConfig
{
[ConfigurationField("multiPicker", "Pick multiple items", "boolean")]
diff --git a/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs
index e4fa6f5c71..bd32f0067b 100644
--- a/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/MediaPickerConfigurationEditor.cs
@@ -11,6 +11,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration editor for the media picker value editor.
///
+[Obsolete("Please use the MediaPicker3 instead, will be removed in V13")]
public class MediaPickerConfigurationEditor : ConfigurationEditor
{
// Scheduled for removal in v12
diff --git a/src/Umbraco.Core/PropertyEditors/NestedContentConfiguration.cs b/src/Umbraco.Core/PropertyEditors/NestedContentConfiguration.cs
index fdef902b58..01656fe78f 100644
--- a/src/Umbraco.Core/PropertyEditors/NestedContentConfiguration.cs
+++ b/src/Umbraco.Core/PropertyEditors/NestedContentConfiguration.cs
@@ -5,6 +5,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration for the nested content value editor.
///
+[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.")]
diff --git a/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs b/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs
index cef30f3f4f..aad5529e1f 100644
--- a/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs
+++ b/src/Umbraco.Core/PropertyEditors/NestedContentConfigurationEditor.cs
@@ -11,6 +11,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration editor for the nested content value editor.
///
+[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentConfigurationEditor : ConfigurationEditor
{
// Scheduled for removal in v12
diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs
index 06269ef8e8..5eac35e67d 100644
--- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs
+++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs
@@ -9,6 +9,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// The media picker property value converter.
///
[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
diff --git a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
index 71c0929e39..e843d7954b 100644
--- a/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
+++ b/src/Umbraco.Examine.Lucene/BackOfficeExamineSearcher.cs
@@ -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, "^\".*?\"$")
diff --git a/src/Umbraco.Infrastructure/Deploy/GridCellValueConnectorExtensions.cs b/src/Umbraco.Infrastructure/Deploy/GridCellValueConnectorExtensions.cs
index fec3c07e3c..d421dcd771 100644
--- a/src/Umbraco.Infrastructure/Deploy/GridCellValueConnectorExtensions.cs
+++ b/src/Umbraco.Infrastructure/Deploy/GridCellValueConnectorExtensions.cs
@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.Deploy;
///
/// These extension methods will be removed in Umbraco 13.
///
+[Obsolete("The grid is obsolete, will be removed in V13")]
public static class GridCellValueConnectorExtensions
{
///
diff --git a/src/Umbraco.Infrastructure/Models/GridValue.cs b/src/Umbraco.Infrastructure/Models/GridValue.cs
index 29e88ea564..e8eca571ce 100644
--- a/src/Umbraco.Infrastructure/Models/GridValue.cs
+++ b/src/Umbraco.Infrastructure/Models/GridValue.cs
@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.Models;
///
/// A model representing the value saved for the grid
///
+[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")]
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridConfiguration.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridConfiguration.cs
index cd1ba4e412..ea72156a12 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/GridConfiguration.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/GridConfiguration.cs
@@ -8,6 +8,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration for the grid value editor.
///
+[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridConfiguration : IIgnoreUserStartNodesConfig
{
// TODO: Make these strongly typed, for now this works though
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs
index aadd25273d..d2b8fba42d 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/GridConfigurationEditor.cs
@@ -13,6 +13,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// Represents the configuration editor for the grid value editor.
///
+[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridConfigurationEditor : ConfigurationEditor
{
// Scheduled for removal in v12
@@ -31,6 +32,7 @@ public class GridConfigurationEditor : ConfigurationEditor
}
}
+[Obsolete("The grid is obsolete, will be removed in V13")]
public class GridValidator : IValueValidator
{
public IEnumerable 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; }
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs
index ed8ef423cf..4fc868256b 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs
@@ -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;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyIndexValueFactory.cs b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyIndexValueFactory.cs
index 70eb9e3b7b..e0a13d2e9d 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyIndexValueFactory.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/GridPropertyIndexValueFactory.cs
@@ -14,6 +14,7 @@ namespace Umbraco.Cms.Core.PropertyEditors
///
/// Parses the grid value into indexable values
///
+ [Obsolete("The grid is obsolete, will be removed in V13")]
public class GridPropertyIndexValueFactory : IPropertyIndexValueFactory
{
public IEnumerable>> GetIndexValues(IProperty property, string? culture, string? segment, bool published)
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs
index 6a037cda11..2eed35c8aa 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/MediaPickerPropertyEditor.cs
@@ -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;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
index e30c400254..bf5781079a 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyEditor.cs
@@ -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";
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyHandler.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyHandler.cs
index b42dc2d155..c46d680273 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyHandler.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedContentPropertyHandler.cs
@@ -10,6 +10,7 @@ namespace Umbraco.Cms.Core.PropertyEditors;
///
/// A handler for NestedContent used to bind to notifications
///
+[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentPropertyHandler : ComplexPropertyEditorContentNotificationHandler
{
protected override string EditorAlias => Constants.PropertyEditors.Aliases.NestedContent;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs
index 48aa8ccf4f..41eb196ff1 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/GridValueConverter.cs
@@ -14,6 +14,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// This ensures that the grid config is merged in with the front-end value
///
[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;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
index aa449cb259..bbe1c92892 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentManyValueConverter.cs
@@ -16,6 +16,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// content.
///
[DefaultPropertyValueConverter(typeof(JsonValueConverter))]
+[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentManyValueConverter : NestedContentValueConverterBase
{
private readonly IProfilingLogger _proflog;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
index 501aa5b024..1ee2759932 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentSingleValueConverter.cs
@@ -15,6 +15,7 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters;
/// content.
///
[DefaultPropertyValueConverter(typeof(JsonValueConverter))]
+[Obsolete("Nested content is obsolete, will be removed in V13")]
public class NestedContentSingleValueConverter : NestedContentValueConverterBase
{
private readonly IProfilingLogger _proflog;
diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
index 07abcb722a..ec4c62d297 100644
--- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
+++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/NestedContentValueConverterBase.cs
@@ -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;
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
index 6c124c14a9..5aab77ed47 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ContentController.cs
@@ -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)
: base(cultureDictionary, loggerFactory, shortStringHelper, eventMessages, localizedTextService, serializer)
{
_propertyEditors = propertyEditors;
@@ -115,7 +119,63 @@ public class ContentController : ContentControllerBase
_logger = loggerFactory.CreateLogger();
_scopeProvider = scopeProvider;
_allLangs = new Lazy>(() =>
- _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>())
+ {
}
[Obsolete("Use constructor that accepts ICultureImpactService as a parameter, scheduled for removal in V12")]
@@ -1710,6 +1770,11 @@ public class ContentController : ContentControllerBase
///
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)
{
diff --git a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs
index 8f7901b2b4..e718696ae3 100644
--- a/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs
+++ b/src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs
@@ -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>())
+ {
+
+ }
+
+ [ActivatorUtilitiesConstructor]
+ public ImagesController(
+ MediaFileManager mediaFileManager,
+ IImageUrlGenerator imageUrlGenerator,
+ IOptionsMonitor contentSettingsMonitor)
{
_mediaFileManager = mediaFileManager;
_imageUrlGenerator = imageUrlGenerator;
+ _contentSettings = contentSettingsMonitor.CurrentValue;
+
+ contentSettingsMonitor.OnChange(x => _contentSettings = x);
+
}
///
@@ -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;
}
///
diff --git a/src/Umbraco.Web.BackOffice/PropertyEditors/NestedContentController.cs b/src/Umbraco.Web.BackOffice/PropertyEditors/NestedContentController.cs
index 6cb8deb71b..3b2124d560 100644
--- a/src/Umbraco.Web.BackOffice/PropertyEditors/NestedContentController.cs
+++ b/src/Umbraco.Web.BackOffice/PropertyEditors/NestedContentController.cs
@@ -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;
diff --git a/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs b/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs
index 10986d3882..9cd0a975a1 100644
--- a/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs
+++ b/src/Umbraco.Web.Common/Controllers/PublishedRequestFilterAttribute.cs
@@ -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
///
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;
}
diff --git a/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs b/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs
index 2c959ab441..8edabf8363 100644
--- a/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs
+++ b/src/Umbraco.Web.Common/Extensions/GridTemplateExtensions.cs
@@ -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")
diff --git a/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js b/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js
index 28a781a8ec..8b42bdbe27 100644
--- a/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js
+++ b/src/Umbraco.Web.UI.Client/src/installer/steps/user.controller.js
@@ -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 = "";
diff --git a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
index d57a9345af..d4fd13489b 100644
--- a/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
+++ b/src/Umbraco.Web.Website/Controllers/UmbLoginStatusController.cs
@@ -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();
}
+
+ ///
+ /// We pass in values via encrypted route values so they cannot be tampered with and merge them into the model for use
+ ///
+ ///
+ private void MergeRouteValuesToModel(PostRedirectModel model)
+ {
+ if (RouteData.Values.TryGetValue(nameof(PostRedirectModel.RedirectUrl), out var redirectUrl) && redirectUrl is not null)
+ {
+ model.RedirectUrl = redirectUrl.ToString();
+ }
+ }
}
diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/ContentControllerTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/ContentControllerTests.cs
index 7046972d83..0a1b2f3240 100644
--- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/ContentControllerTests.cs
+++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/ContentControllerTests.cs
@@ -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(),
Mock.Of(),
Mock.Of(),
- Mock.Of());
+ Mock.Of(),
+ new OptionsWrapper(new ContentSettings()));
return controller;
}