diff --git a/Directory.Build.props b/Directory.Build.props index 6def71bb1b..7d9f7ed111 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -29,7 +29,7 @@ - false + true true 11.0.0 true diff --git a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDatabaseProviderMetadata.cs b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDatabaseProviderMetadata.cs index edb44700d8..89612b3603 100644 --- a/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDatabaseProviderMetadata.cs +++ b/src/Umbraco.Cms.Persistence.SqlServer/Services/SqlServerDatabaseProviderMetadata.cs @@ -50,7 +50,7 @@ public class SqlServerDatabaseProviderMetadata : IDatabaseProviderMetadata public bool RequiresConnectionTest => true; /// - public bool ForceCreateDatabase => false; + public bool ForceCreateDatabase => true; /// public bool CanRecognizeConnectionString(string? connectionString) diff --git a/src/Umbraco.Core/Actions/ActionToPublish.cs b/src/Umbraco.Core/Actions/ActionToPublish.cs index e7af16bc99..25719e30fc 100644 --- a/src/Umbraco.Core/Actions/ActionToPublish.cs +++ b/src/Umbraco.Core/Actions/ActionToPublish.cs @@ -6,6 +6,7 @@ namespace Umbraco.Cms.Core.Actions; /// /// This action is invoked when children to a document is being sent to published (by an editor without publishrights). /// +[Obsolete("Scheduled for removal in v13")] public class ActionToPublish : IAction { /// diff --git a/src/Umbraco.Core/Events/UserNotificationsHandler.cs b/src/Umbraco.Core/Events/UserNotificationsHandler.cs index 042355630f..4b581788e8 100644 --- a/src/Umbraco.Core/Events/UserNotificationsHandler.cs +++ b/src/Umbraco.Core/Events/UserNotificationsHandler.cs @@ -107,6 +107,7 @@ public sealed class UserNotificationsHandler : _notifier.Notify(_actions.GetAction(), updatedEntities.ToArray()); } + [Obsolete("Scheduled for removal in v13")] public void Handle(ContentSentToPublishNotification notification) => _notifier.Notify(_actions.GetAction(), notification.Entity); diff --git a/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs b/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs index 1dd2fef124..1164b02753 100644 --- a/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs +++ b/src/Umbraco.Core/Models/PublishedContent/NoopPublishedValueFallback.cs @@ -7,7 +7,15 @@ namespace Umbraco.Cms.Core.Models.PublishedContent; /// This is for tests etc - does not implement fallback at all. /// public class NoopPublishedValueFallback : IPublishedValueFallback + { + /// + public IVariationContextAccessor VariationContextAccessor + { + get => new ThreadCultureVariationContextAccessor(); + set { } + } + /// public bool TryGetValue(IPublishedProperty property, string? culture, string? segment, Fallback fallback, object? defaultValue, out object? value) { diff --git a/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs b/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs index c4715d5aad..582a682609 100644 --- a/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs +++ b/src/Umbraco.Core/PropertyEditors/ValueConverters/MediaPickerValueConverter.cs @@ -122,7 +122,7 @@ public class MediaPickerValueConverter : PropertyValueConverterBase, IDeliveryAp return source; } - public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Elements; public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); diff --git a/src/Umbraco.Core/Services/MetricsConsentService.cs b/src/Umbraco.Core/Services/MetricsConsentService.cs index a3140c4f61..be30458af6 100644 --- a/src/Umbraco.Core/Services/MetricsConsentService.cs +++ b/src/Umbraco.Core/Services/MetricsConsentService.cs @@ -60,7 +60,7 @@ public class MetricsConsentService : IMetricsConsentService if (analyticsLevelString is null || Enum.TryParse(analyticsLevelString, out TelemetryLevel analyticsLevel) is false) { - return TelemetryLevel.Basic; + return TelemetryLevel.Detailed; } return analyticsLevel; diff --git a/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs index fa3ae836c1..4eb7051745 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/NestedPropertyIndexValueFactoryBase.cs @@ -38,7 +38,7 @@ internal abstract class NestedPropertyIndexValueFactoryBase var propertyTypeDictionary = contentType - .PropertyGroups + .CompositionPropertyGroups .SelectMany(x => x.PropertyTypes!) .Select(propertyType => { diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs index f19e4bff29..98a48c0a8e 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/BlockGridPropertyValueConverter.cs @@ -1,7 +1,9 @@ // Copyright (c) Umbraco. // See LICENSE for more details. +using Microsoft.Extensions.DependencyInjection; using Umbraco.Cms.Core.DeliveryApi; +using Umbraco.Cms.Core.DependencyInjection; using Umbraco.Cms.Core.Logging; using Umbraco.Cms.Core.Models.Blocks; using Umbraco.Cms.Core.Models.DeliveryApi; @@ -20,9 +22,20 @@ namespace Umbraco.Cms.Core.PropertyEditors.ValueConverters private readonly IJsonSerializer _jsonSerializer; private readonly IApiElementBuilder _apiElementBuilder; + [Obsolete("Please use non-obsolete cconstrutor. This will be removed in Umbraco 14.")] + public BlockGridPropertyValueConverter( + IProfilingLogger proflog, + BlockEditorConverter blockConverter, + IJsonSerializer jsonSerializer) + : this(proflog, blockConverter, jsonSerializer, StaticServiceProvider.Instance.GetRequiredService()) + { + + } + // Niels, Change: I would love if this could be general, so we don't need a specific one for each block property editor.... public BlockGridPropertyValueConverter( - IProfilingLogger proflog, BlockEditorConverter blockConverter, + IProfilingLogger proflog, + BlockEditorConverter blockConverter, IJsonSerializer jsonSerializer, IApiElementBuilder apiElementBuilder) : base(blockConverter) diff --git a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerWithCropsValueConverter.cs b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerWithCropsValueConverter.cs index ef183089e9..a33bb9870d 100644 --- a/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerWithCropsValueConverter.cs +++ b/src/Umbraco.Infrastructure/PropertyEditors/ValueConverters/MediaPickerWithCropsValueConverter.cs @@ -120,7 +120,7 @@ public class MediaPickerWithCropsValueConverter : PropertyValueConverterBase, ID return isMultiple ? mediaItems : mediaItems.FirstOrDefault(); } - public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Element; + public PropertyCacheLevel GetDeliveryApiPropertyCacheLevel(IPublishedPropertyType propertyType) => PropertyCacheLevel.Elements; public Type GetDeliveryApiPropertyValueType(IPublishedPropertyType propertyType) => typeof(IEnumerable); diff --git a/src/Umbraco.New.Cms.Core/Models/Installer/InstallData.cs b/src/Umbraco.New.Cms.Core/Models/Installer/InstallData.cs index 2283cf2482..77d0c07477 100644 --- a/src/Umbraco.New.Cms.Core/Models/Installer/InstallData.cs +++ b/src/Umbraco.New.Cms.Core/Models/Installer/InstallData.cs @@ -8,5 +8,5 @@ public class InstallData public DatabaseInstallData Database { get; set; } = null!; - public TelemetryLevel TelemetryLevel { get; set; } = TelemetryLevel.Basic; + public TelemetryLevel TelemetryLevel { get; set; } = TelemetryLevel.Detailed; } diff --git a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs index 5269d3d0d7..f4a09e1a60 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/CurrentUserController.cs @@ -278,7 +278,7 @@ public class CurrentUserController : UmbracoAuthorizedJsonController // all current users have access to reset/manually change their password Attempt passwordChangeResult = - await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _backOfficeUserManager); + await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _backOfficeUserManager, currentUser); if (passwordChangeResult.Success) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs index 1c2d9f8039..d619653740 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/MemberController.cs @@ -623,7 +623,7 @@ public class MemberController : ContentControllerBase // Change and persist the password Attempt passwordChangeResult = - await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _memberManager); + await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _memberManager, _backOfficeSecurityAccessor.BackOfficeSecurity?.CurrentUser); if (!passwordChangeResult.Success) { diff --git a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs index 9b400af00d..2a16066707 100644 --- a/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs +++ b/src/Umbraco.Web.BackOffice/Controllers/UsersController.cs @@ -759,7 +759,7 @@ public class UsersController : BackOfficeNotificationsController } Attempt passwordChangeResult = - await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _userManager); + await _passwordChanger.ChangePasswordWithIdentityAsync(changingPasswordModel, _userManager, currentUser); if (passwordChangeResult.Success) { diff --git a/src/Umbraco.Web.BackOffice/Security/IPasswordChanger.cs b/src/Umbraco.Web.BackOffice/Security/IPasswordChanger.cs index 66c69d4d70..3bc5f35abf 100644 --- a/src/Umbraco.Web.BackOffice/Security/IPasswordChanger.cs +++ b/src/Umbraco.Web.BackOffice/Security/IPasswordChanger.cs @@ -1,12 +1,19 @@ using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Security; namespace Umbraco.Cms.Web.Common.Security; public interface IPasswordChanger where TUser : UmbracoIdentityUser { + [Obsolete("Please use method that also takes a nullable IUser, scheduled for removal in v13")] public Task> ChangePasswordWithIdentityAsync( ChangingPasswordModel passwordModel, IUmbracoUserManager userMgr); + + public Task> ChangePasswordWithIdentityAsync( + ChangingPasswordModel passwordModel, + IUmbracoUserManager userMgr, + IUser? currentUser) => ChangePasswordWithIdentityAsync(passwordModel, userMgr); } diff --git a/src/Umbraco.Web.BackOffice/Security/PasswordChanger.cs b/src/Umbraco.Web.BackOffice/Security/PasswordChanger.cs index 27956cb544..59f0835ad4 100644 --- a/src/Umbraco.Web.BackOffice/Security/PasswordChanger.cs +++ b/src/Umbraco.Web.BackOffice/Security/PasswordChanger.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Umbraco.Cms.Core; using Umbraco.Cms.Core.Models; +using Umbraco.Cms.Core.Models.Membership; using Umbraco.Cms.Core.Security; using Umbraco.Extensions; @@ -22,16 +23,20 @@ internal class PasswordChanger : IPasswordChanger where TUser : Um /// Logger for this class public PasswordChanger(ILogger> logger) => _logger = logger; + public Task> ChangePasswordWithIdentityAsync(ChangingPasswordModel passwordModel, IUmbracoUserManager userMgr) => ChangePasswordWithIdentityAsync(passwordModel, userMgr, null); + /// /// Changes the password for a user based on the many different rules and config options /// - /// The changing password model - /// The identity manager to use to update the password + /// The changing password model. + /// The identity manager to use to update the password. + /// The user performing the operation. /// Create an adapter to pass through everything - adapting the member into a user for this functionality /// The outcome of the password changed model public async Task> ChangePasswordWithIdentityAsync( ChangingPasswordModel changingPasswordModel, - IUmbracoUserManager userMgr) + IUmbracoUserManager userMgr, + IUser? currentUser) { if (changingPasswordModel == null) { @@ -65,6 +70,14 @@ internal class PasswordChanger : IPasswordChanger where TUser : Um // Are we just changing another user/member's password? if (changingPasswordModel.OldPassword.IsNullOrWhiteSpace()) { + if (changingPasswordModel.Id == currentUser?.Id) + { + return Attempt.Fail(new PasswordChangedModel + { + ChangeError = new ValidationResult("Cannot change the password of current user without the old password", new[] { "value" }), + }); + } + // ok, we should be able to reset it var resetToken = await userMgr.GeneratePasswordResetTokenAsync(identityUser); diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/TelemetryServiceTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/TelemetryServiceTests.cs index fb66f80731..efc66bd8d5 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/TelemetryServiceTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Core/Telemetry/TelemetryServiceTests.cs @@ -81,7 +81,7 @@ public class TelemetryServiceTests }; var packageManifestService = CreatePackageManifestService(manifests); var metricsConsentService = new Mock(); - metricsConsentService.Setup(x => x.GetConsentLevel()).Returns(TelemetryLevel.Basic); + metricsConsentService.Setup(x => x.GetConsentLevel()).Returns(TelemetryLevel.Detailed); var sut = new TelemetryService( version, CreateSiteIdentifierService(), @@ -116,7 +116,7 @@ public class TelemetryServiceTests }; var packageManifestService = CreatePackageManifestService(manifests); var metricsConsentService = new Mock(); - metricsConsentService.Setup(x => x.GetConsentLevel()).Returns(TelemetryLevel.Basic); + metricsConsentService.Setup(x => x.GetConsentLevel()).Returns(TelemetryLevel.Detailed); var sut = new TelemetryService( version, CreateSiteIdentifierService(), diff --git a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs index 15788cf007..e9fa70dc1d 100644 --- a/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs +++ b/tests/Umbraco.Tests.UnitTests/Umbraco.Web.BackOffice/Controllers/MemberControllerUnitTests.cs @@ -358,7 +358,8 @@ public class MemberControllerUnitTests Mock.Get(passwordChanger) .Setup(x => x.ChangePasswordWithIdentityAsync( It.IsAny(), - umbracoMembersUserManager)) + umbracoMembersUserManager, + null)) .ReturnsAsync(() => attempt); } else @@ -367,7 +368,8 @@ public class MemberControllerUnitTests Mock.Get(passwordChanger) .Setup(x => x.ChangePasswordWithIdentityAsync( It.IsAny(), - umbracoMembersUserManager)) + umbracoMembersUserManager, + null)) .ReturnsAsync(() => attempt); } }