Merge branch 'v10/dev' into v10/feature/nullable-reference-types-in-Umbraco.Web.Backoffice

# Conflicts:
#	src/Umbraco.Core/Cache/MacroCacheRefresher.cs
#	src/Umbraco.Core/Services/MacroService.cs
#	src/Umbraco.Core/StaticApplicationLogging.cs
#	src/Umbraco.Infrastructure/Migrations/Install/DatabaseDataCreator.cs
#	src/Umbraco.Infrastructure/Persistence/Repositories/Implement/MacroRepository.cs
#	src/Umbraco.Infrastructure/Persistence/Repositories/Implement/TrackedReferencesRepository.cs
#	src/Umbraco.Infrastructure/PropertyEditors/GridPropertyEditor.cs
#	src/Umbraco.Infrastructure/Security/UmbracoPasswordHasher.cs
#	src/Umbraco.Web.BackOffice/Controllers/ImagesController.cs
This commit is contained in:
Nikolaj Geisle
2022-04-05 08:51:08 +02:00
76 changed files with 2021 additions and 571 deletions

View File

@@ -9,6 +9,11 @@ using System.Data.Common;
using System.Diagnostics;
using System.Threading;
using Microsoft.Extensions.Logging;
using Moq;
using Umbraco.Cms.Core;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Infrastructure.Persistence;
namespace Umbraco.Cms.Tests.Integration.Testing

View File

@@ -6,9 +6,11 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Core.Migrations;
using Umbraco.Cms.Core.Scoping;

View File

@@ -1,6 +1,9 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Events;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Tests.Common.Testing;
@@ -23,7 +26,7 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Persistence
using (ScopeProvider.CreateScope(autoComplete: true))
{
var schema = new DatabaseSchemaCreator(ScopeAccessor.AmbientScope.Database, LoggerFactory.CreateLogger<DatabaseSchemaCreator>(), LoggerFactory, UmbracoVersion, EventAggregator);
var schema = new DatabaseSchemaCreator(ScopeAccessor.AmbientScope.Database, LoggerFactory.CreateLogger<DatabaseSchemaCreator>(), LoggerFactory, UmbracoVersion, EventAggregator, Mock.Of<IOptionsMonitor<InstallDefaultDataSettings>>(x => x.CurrentValue == new InstallDefaultDataSettings()));
schema.InitializeDatabaseSchema();
result = schema.ValidateSchema(DatabaseSchemaCreator.OrderedTables);
}

View File

@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
@@ -25,7 +24,8 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
public class MacroServiceTests : UmbracoIntegrationTest
{
private IMacroService MacroService => GetRequiredService<IMacroService>();
[Obsolete("After merging IMacroWithAliasService interface with IMacroService in Umbraco 11, this should go back to just being GetRequiredService<IMacroService>()")]
private IMacroWithAliasService MacroService => GetRequiredService<IMacroService>() as IMacroWithAliasService;
[SetUp]
public void SetupTest()
@@ -53,6 +53,19 @@ namespace Umbraco.Cms.Tests.Integration.Umbraco.Infrastructure.Services
Assert.AreEqual("Test1", macro.Name);
}
[Test]
public void Can_Get_By_Aliases()
{
// Act
IEnumerable<IMacro> macros = MacroService.GetAll("test1", "test2");
// Assert
Assert.IsNotNull(macros);
Assert.AreEqual(2, macros.Count());
Assert.AreEqual("Test1", macros.ToArray()[0].Name);
Assert.AreEqual("Test2", macros.ToArray()[1].Name);
}
[Test]
public void Can_Get_All()
{

View File

@@ -12,6 +12,7 @@ using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Hosting;
using Umbraco.Cms.Core.Security;
using Umbraco.Cms.Core.Services;
using Umbraco.Cms.Infrastructure.Migrations.Install;
using Umbraco.Cms.Web.BackOffice.Controllers;
using Umbraco.Cms.Web.BackOffice.Install;
using Umbraco.Cms.Web.BackOffice.Routing;
@@ -34,7 +35,8 @@ namespace Umbraco.Cms.Tests.UnitTests.AutoFixture.Customizations
.Customize(new ConstructorCustomization(typeof(MemberController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeController), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(BackOfficeUserManager), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(MemberManager), new GreedyConstructorQuery()));
.Customize(new ConstructorCustomization(typeof(MemberManager), new GreedyConstructorQuery()))
.Customize(new ConstructorCustomization(typeof(DatabaseSchemaCreatorFactory), new GreedyConstructorQuery()));
// When requesting an IUserStore ensure we actually uses a IUserLockoutStore
fixture.Customize<IUserStore<BackOfficeIdentityUser>>(cc => cc.FromFactory(Mock.Of<IUserLockoutStore<BackOfficeIdentityUser>>));

View File

@@ -58,7 +58,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Components
Mock.Of<IOptionsMonitor<ConnectionStrings>>(x => x.Get(It.IsAny<string>()) == connectionStrings),
new MapperCollection(() => Enumerable.Empty<BaseMapper>()),
Mock.Of<IDbProviderFactoryCreator>(),
new DatabaseSchemaCreatorFactory(loggerFactory.CreateLogger<DatabaseSchemaCreator>(), loggerFactory, new UmbracoVersion(), Mock.Of<IEventAggregator>()),
new DatabaseSchemaCreatorFactory(loggerFactory.CreateLogger<DatabaseSchemaCreator>(), loggerFactory, new UmbracoVersion(), Mock.Of<IEventAggregator>(), Mock.Of<IOptionsMonitor<InstallDefaultDataSettings>>()),
mapperCollection);
var fs = new FileSystems(loggerFactory, IOHelper, Options.Create(globalSettings), Mock.Of<IHostingEnvironment>());

View File

@@ -1,10 +1,14 @@
// Copyright (c) Umbraco.
// See LICENSE for more details.
using System;
using System.Security.Cryptography;
using System.Text;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Configuration;
using Umbraco.Cms.Core.Security;
using Umbraco.Extensions;
using Constants = Umbraco.Cms.Core.Constants;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security
@@ -15,7 +19,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security
[Test]
public void Check_Password_Hashed_Non_KeyedHashAlgorithm()
{
IPasswordConfiguration passwordConfiguration = Mock.Of<IPasswordConfiguration>(x => x.HashAlgorithmType == "SHA256");
IPasswordConfiguration passwordConfiguration = Mock.Of<IPasswordConfiguration>(x => x.HashAlgorithmType == "SHA1");
var passwordSecurity = new LegacyPasswordSecurity();
var pass = "ThisIsAHashedPassword";
@@ -45,14 +49,12 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.Security
[Test]
public void Check_Password_Legacy_v4_SHA1()
{
IPasswordConfiguration passwordConfiguration = Mock.Of<IPasswordConfiguration>(x => x.HashAlgorithmType == Constants.Security.AspNetUmbraco4PasswordHashAlgorithmName);
var passwordSecurity = new LegacyPasswordSecurity();
const string clearText = "ThisIsAHashedPassword";
var clearTextUnicodeBytes = Encoding.Unicode.GetBytes(clearText);
using var algorithm = new HMACSHA1(clearTextUnicodeBytes);
var dbPassword = Convert.ToBase64String(algorithm.ComputeHash(clearTextUnicodeBytes));
var pass = "ThisIsAHashedPassword";
var hashed = passwordSecurity.HashNewPassword(passwordConfiguration.HashAlgorithmType, pass, out string salt);
var storedPassword = passwordSecurity.FormatPasswordForStorage(passwordConfiguration.HashAlgorithmType, hashed, salt);
var result = passwordSecurity.VerifyPassword(passwordConfiguration.HashAlgorithmType, "ThisIsAHashedPassword", storedPassword);
var result = new LegacyPasswordSecurity().VerifyLegacyHashedPassword(clearText, dbPassword);
Assert.IsTrue(result);
}

View File

@@ -1,5 +1,9 @@
using System;
using System.Security.Cryptography;
using System.Text;
using AutoFixture.NUnit3;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Moq;
using NUnit.Framework;
using Umbraco.Cms.Core.Models.Membership;
@@ -15,9 +19,8 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
// Technically MD5, HMACSHA384 & HMACSHA512 were also possible but opt in as opposed to historic defaults.
[Test]
[InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "uB/pLEhhe1W7EtWMv/pSgg==1y8+aso9+h3AKRtJXlVYeg2TZKJUr64hccj82ZZ7Ksk=")] // Actually HMACSHA256
[InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")] // v4 site legacy password, with incorrect algorithm specified in database actually HMACSHA1 with password used as key.
[InlineAutoMoqData("SHA1", "Umbraco9Rocks!", "6tZGfG9NTxJJYp19Fac9og==zzRggqANxhb+CbD/VabEt8cIde8=")] // When SHA1 is set on machine key.
public void VerifyHashedPassword_WithValidLegacyPasswordHash_ReturnsSuccessRehashNeeded(
public void VerifyHashedPassword_ValidHashWithoutLegacyEncoding_ReturnsSuccessRehashNeeded(
string algorithm,
string providedPassword,
string hashedPassword,
@@ -34,10 +37,13 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result);
}
[Test]
[InlineAutoMoqData("PBKDF2.ASPNETCORE.V3", "Umbraco9Rocks!", "AQAAAAEAACcQAAAAEDCrYcnIhHKr38yuchsDu6AFqqmLNvRooKObV25GC1LC1tLY+gWGU4xNug0lc17PHA==")]
public void VerifyHashedPassword_WithValidModernPasswordHash_ReturnsSuccess(
[InlineAutoMoqData("HMACSHA1", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")]
[InlineAutoMoqData("HMACSHA256", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")]
[InlineAutoMoqData("FOOBARBAZQUX", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")]
[InlineAutoMoqData("", "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")]
[InlineAutoMoqData(null, "Umbraco9Rocks!", "t0U8atXTX/efNCtTafukwZeIpr8=")]
public void VerifyHashedPassword_ValidHashWithLegacyEncoding_ReturnsSuccessRehashNeeded(
string algorithm,
string providedPassword,
string hashedPassword,
@@ -51,7 +57,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
var result = sut.VerifyHashedPassword(aUser, hashedPassword, providedPassword);
Assert.AreEqual(PasswordVerificationResult.Success, result);
Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result);
}
[Test]
@@ -73,6 +79,46 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
Assert.AreEqual(PasswordVerificationResult.Failed, result);
}
[Test]
[AutoMoqData]
public void VerifyHashedPassword_WithIdentityV1OrV2StyleHash_ReturnsSuccessRehashNeeded(
TestUserStub aUser,
UmbracoPasswordHasher<TestUserStub> sut)
{
var options = Options.Create(new PasswordHasherOptions
{
CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV2
});
var upstreamHasher = new PasswordHasher<TestUserStub>(options);
const string password = "Umbraco9Rocks!";
var identityV1Or2StyleHash = upstreamHasher.HashPassword(aUser, password);
var result = sut.VerifyHashedPassword(aUser, identityV1Or2StyleHash, password);
Assert.AreEqual(PasswordVerificationResult.SuccessRehashNeeded, result);
}
[Test]
[AutoMoqData]
public void VerifyHashedPassword_WithIdentityV3StyleHash_ReturnsSuccess(
TestUserStub aUser,
UmbracoPasswordHasher<TestUserStub> sut)
{
var options = Options.Create(new PasswordHasherOptions
{
CompatibilityMode = PasswordHasherCompatibilityMode.IdentityV3
});
var upstreamHasher = new PasswordHasher<TestUserStub>(options);
const string password = "Umbraco9Rocks!";
var identityV1Or2StyleHash = upstreamHasher.HashPassword(aUser, password);
var result = sut.VerifyHashedPassword(aUser, identityV1Or2StyleHash, password);
Assert.AreEqual(PasswordVerificationResult.Success, result);
}
public class TestUserStub : UmbracoIdentityUser
{
public TestUserStub() => PasswordConfig = "not null or empty";

View File

@@ -323,6 +323,7 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.PublishedCache.NuCache
}
[Test]
[Retry(5)] // TODO make this test non-flaky.
public async Task EventuallyCollectNulls()
{
var d = new SnapDictionary<int, string>();