Merge branch 'v8/dev' into v8/feature/10613-distributed-locks

This commit is contained in:
Mole
2021-03-11 13:43:07 +01:00
16 changed files with 330 additions and 54 deletions

View File

@@ -0,0 +1,114 @@
using System.Collections.Specialized;
using System.Web.Security;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Sync;
using Umbraco.Tests.Integration;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
using Umbraco.Web;
using Umbraco.Web.Cache;
using Umbraco.Web.Security.Providers;
namespace Umbraco.Tests.Membership
{
[TestFixture]
[UmbracoTest(Database = UmbracoTestOptions.Database.NewSchemaPerFixture)]
public class MembersMembershipProviderTests : TestWithDatabaseBase
{
private MembersMembershipProvider MembersMembershipProvider { get; set; }
private IDistributedCacheBinder DistributedCacheBinder { get; set; }
public IMemberService MemberService => Current.Factory.GetInstance<IMemberService>();
public IMemberTypeService MemberTypeService => Current.Factory.GetInstance<IMemberTypeService>();
public ILogger Logger => Current.Factory.GetInstance<ILogger>();
public override void SetUp()
{
base.SetUp();
MembersMembershipProvider = new MembersMembershipProvider(MemberService, MemberTypeService);
MembersMembershipProvider.Initialize("test", new NameValueCollection { { "passwordFormat", MembershipPasswordFormat.Clear.ToString() } });
DistributedCacheBinder = new DistributedCacheBinder(new DistributedCache(), Mock.Of<IUmbracoContextFactory>(), Logger);
DistributedCacheBinder.BindEvents(true);
}
[TearDown]
public void Teardown()
{
DistributedCacheBinder?.UnbindEvents();
DistributedCacheBinder = null;
}
protected override void Compose()
{
base.Compose();
// the cache refresher component needs to trigger to refresh caches
// but then, it requires a lot of plumbing ;(
// FIXME: and we cannot inject a DistributedCache yet
// so doing all this mess
Composition.RegisterUnique<IServerMessenger, ContentEventsTests.LocalServerMessenger>();
Composition.RegisterUnique(f => Mock.Of<IServerRegistrar>());
Composition.WithCollectionBuilder<CacheRefresherCollectionBuilder>()
.Add(() => Composition.TypeLoader.GetCacheRefreshers());
}
protected override AppCaches GetAppCaches()
{
// this is what's created core web runtime
return new AppCaches(
new DeepCloneAppCache(new ObjectCacheAppCache()),
NoAppCache.Instance,
new IsolatedCaches(type => new DeepCloneAppCache(new ObjectCacheAppCache())));
}
/// <summary>
/// MembersMembershipProvider.ValidateUser is expected to increase the number of failed attempts and also read that same number.
/// </summary>
/// <remarks>
/// This test requires the caching to be enabled, as it already is correct in the database.
/// Shows the error described here: https://github.com/umbraco/Umbraco-CMS/issues/9861
/// </remarks>
[Test]
public void ValidateUser__must_lock_out_users_after_max_attempts_of_wrong_password()
{
// Arrange
IMemberType memberType = MockedContentTypes.CreateSimpleMemberType();
ServiceContext.MemberTypeService.Save(memberType);
var member = MockedMember.CreateSimpleMember(memberType, "test", "test@test.com", "password","test");
ServiceContext.MemberService.Save(member);
var wrongPassword = "wrongPassword";
var numberOfFailedAttempts = MembersMembershipProvider.MaxInvalidPasswordAttempts+2;
// Act
var memberBefore = ServiceContext.MemberService.GetById(member.Id);
for (int i = 0; i < numberOfFailedAttempts; i++)
{
MembersMembershipProvider.ValidateUser(member.Username, wrongPassword);
}
var memberAfter = ServiceContext.MemberService.GetById(member.Id);
// Assert
Assert.Multiple(() =>
{
Assert.AreEqual(0 , memberBefore.FailedPasswordAttempts, "Expected 0 failed password attempts before");
Assert.IsFalse(memberBefore.IsLockedOut, "Expected the member NOT to be locked out before");
Assert.AreEqual(MembersMembershipProvider.MaxInvalidPasswordAttempts, memberAfter.FailedPasswordAttempts, "Expected exactly the max possible failed password attempts after");
Assert.IsTrue(memberAfter.IsLockedOut, "Expected the member to be locked out after");
});
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core.Composing;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Serialization;
using Umbraco.Tests.TestHelpers;
namespace Umbraco.Tests.Models
{
[TestFixture]
public class UserGroupTests
{
[SetUp]
public void Setup()
{
Current.Reset();
Current.UnlockConfigs();
Current.Configs.Add(SettingsForTests.GetDefaultGlobalSettings);
Current.Configs.Add(SettingsForTests.GetDefaultUmbracoSettings);
}
[Test]
public void Can_Deep_Clone()
{
var item = Build();
var clone = (UserGroup)item.DeepClone();
Assert.AreNotSame(clone, item);
Assert.AreEqual(clone, item);
Assert.AreEqual(clone.AllowedSections.Count(), item.AllowedSections.Count());
Assert.AreNotSame(clone.AllowedSections, item.AllowedSections);
//Verify normal properties with reflection
var allProps = clone.GetType().GetProperties();
foreach (var propertyInfo in allProps)
{
Assert.AreEqual(propertyInfo.GetValue(clone, null), propertyInfo.GetValue(item, null));
}
}
[Test]
public void Can_Serialize_Without_Error()
{
var ss = new SerializationService(new JsonNetSerializer());
var item = Build();
var result = ss.ToStream(item);
var json = result.ResultStream.ToJsonString();
Debug.Print(json);
}
private UserGroup Build()
{
var item = new UserGroup()
{
Id = 3,
Key = Guid.NewGuid(),
UpdateDate = DateTime.Now,
CreateDate = DateTime.Now,
Name = "Test",
Alias = "alias",
Icon = "icon",
Permissions = new []{"a", "b", "c"},
DeleteDate = null,
StartContentId = null,
StartMediaId = null,
};
item.AddAllowedSection("A");
item.AddAllowedSection("B");
return item;
}
}
}

View File

@@ -132,6 +132,7 @@
<Compile Include="Logging\LogviewerTests.cs" />
<Compile Include="Manifest\ManifestContentAppTests.cs" />
<Compile Include="Mapping\MappingTests.cs" />
<Compile Include="Membership\MembersMembershipProviderTests.cs" />
<Compile Include="Migrations\MigrationPlanTests.cs" />
<Compile Include="Migrations\MigrationTests.cs" />
<Compile Include="ModelsBuilder\BuilderTests.cs" />
@@ -144,6 +145,7 @@
<Compile Include="Models\PathValidationTests.cs" />
<Compile Include="Models\PropertyTests.cs" />
<Compile Include="Models\RangeTests.cs" />
<Compile Include="Models\UserGroupTests.cs" />
<Compile Include="Models\VariationTests.cs" />
<Compile Include="Persistence\Mappers\MapperTestBase.cs" />
<Compile Include="Persistence\Repositories\DocumentRepositoryTest.cs" />

View File

@@ -116,6 +116,37 @@ namespace Umbraco.Tests.Web.Controllers
Assert.IsTrue(result.Success);
}
[Test]
[TestCase(Constants.Security.AdminGroupAlias, Constants.Security.AdminGroupAlias, ExpectedResult = true)]
[TestCase(Constants.Security.AdminGroupAlias, "SomethingElse", ExpectedResult = true)]
[TestCase(Constants.Security.EditorGroupAlias, Constants.Security.AdminGroupAlias, ExpectedResult = false)]
[TestCase(Constants.Security.EditorGroupAlias, "SomethingElse", ExpectedResult = false)]
[TestCase(Constants.Security.EditorGroupAlias, Constants.Security.EditorGroupAlias, ExpectedResult = true)]
public bool Can_only_add_user_groups_you_are_part_of_yourself_unless_you_are_admin(string groupAlias, string groupToAdd)
{
var currentUser = Mock.Of<IUser>(user => user.Groups == new[]
{
new ReadOnlyUserGroup(1, "CurrentUser", "icon-user", null, null, groupAlias, new string[0], new string[0])
});
IUser savingUser = null; // This means it is a new created user
var contentService = new Mock<IContentService>();
var mediaService = new Mock<IMediaService>();
var userService = new Mock<IUserService>();
var entityService = new Mock<IEntityService>();
var authHelper = new UserEditorAuthorizationHelper(
contentService.Object,
mediaService.Object,
userService.Object,
entityService.Object,
AppCaches.Disabled);
var result = authHelper.IsAuthorized(currentUser, savingUser, new int[0], new int[0], new[] { groupToAdd });
return result.Success;
}
[Test]
public void Can_Add_Another_Content_Start_Node_On_User_With_Access()
{