using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Moq; using NUnit.Framework; using Umbraco.Cms.Core.Cache; using Umbraco.Cms.Core.Configuration.Models; using Umbraco.Cms.Core.Mapping; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Net; using Umbraco.Cms.Core.PublishedCache; using Umbraco.Cms.Core.Scoping; using Umbraco.Cms.Core.Security; using Umbraco.Cms.Core.Services; using Umbraco.Cms.Tests.Common; using Umbraco.Cms.Tests.Common.Builders; using Umbraco.Cms.Tests.Common.Builders.Extensions; using Umbraco.Cms.Web.Common.Security; namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security { [TestFixture] public class MemberManagerTests { private MemberUserStore _fakeMemberStore; private Mock> _mockIdentityOptions; private Mock> _mockPasswordHasher; private Mock _mockMemberService; private Mock _mockServiceProviders; private Mock> _mockPasswordConfiguration; public MemberManager CreateSut() { IScopeProvider scopeProvider = new Mock().Object; _mockMemberService = new Mock(); var mapDefinitions = new List() { new IdentityMapDefinition( Mock.Of(), Mock.Of(), new TestOptionsSnapshot(new GlobalSettings()), AppCaches.Disabled), }; _fakeMemberStore = new MemberUserStore( _mockMemberService.Object, new UmbracoMapper(new MapDefinitionCollection(() => mapDefinitions), scopeProvider), scopeProvider, new IdentityErrorDescriber(), Mock.Of(), Mock.Of(), Mock.Of()); _mockIdentityOptions = new Mock>(); var idOptions = new IdentityOptions { Lockout = { AllowedForNewUsers = false } }; _mockIdentityOptions.Setup(o => o.Value).Returns(idOptions); _mockPasswordHasher = new Mock>(); var userValidators = new List>(); var validator = new Mock>(); userValidators.Add(validator.Object); _mockServiceProviders = new Mock(); _mockPasswordConfiguration = new Mock>(); _mockPasswordConfiguration.Setup(x => x.Value).Returns(() => new MemberPasswordConfigurationSettings() { }); var pwdValidators = new List> { new PasswordValidator() }; var userManager = new MemberManager( new Mock().Object, _fakeMemberStore, _mockIdentityOptions.Object, _mockPasswordHasher.Object, userValidators, pwdValidators, new MembersErrorDescriber(Mock.Of()), _mockServiceProviders.Object, new Mock>>().Object, _mockPasswordConfiguration.Object, Mock.Of(), Mock.Of()); validator.Setup(v => v.ValidateAsync( userManager, It.IsAny())) .Returns(Task.FromResult(IdentityResult.Success)).Verifiable(); return userManager; } [Test] public async Task GivenICreateUser_AndTheIdentityResultFailed_ThenIShouldGetAFailedResultAsync() { //arrange MemberManager sut = CreateSut(); var fakeUser = new MemberIdentityUser() { PasswordConfig = "testConfig" }; //act IdentityResult identityResult = await sut.CreateAsync(fakeUser); //assert Assert.IsFalse(identityResult.Succeeded); Assert.IsFalse(!identityResult.Errors.Any()); } [Test] public async Task GivenICreateUser_AndTheUserIsNull_ThenIShouldGetAFailedResultAsync() { //arrange MemberManager sut = CreateSut(); IdentityError[] identityErrors = { new IdentityError() { Code = "IdentityError1", Description = "There was an identity error when creating a user" } }; //act Assert.ThrowsAsync(async () => await sut.CreateAsync(null)); } [Test] public async Task GivenICreateANewUser_AndTheUserIsPopulatedCorrectly_ThenIShouldGetASuccessResultAsync() { //arrange MemberManager sut = CreateSut(); MemberIdentityUser fakeUser = CreateValidUser(); IMember fakeMember = CreateMember(fakeUser); MockMemberServiceForCreateMember(fakeMember); //act IdentityResult identityResult = await sut.CreateAsync(fakeUser); //assert Assert.IsTrue(identityResult.Succeeded); Assert.IsTrue(!identityResult.Errors.Any()); } [Test] public async Task GivenAUserExists_AndTheCorrectCredentialsAreProvided_ThenACheckOfCredentialsShouldSucceed() { //arrange var password = "password"; MemberManager sut = CreateSut(); MemberIdentityUser fakeUser = CreateValidUser(); IMember fakeMember = CreateMember(fakeUser); MockMemberServiceForCreateMember(fakeMember); _mockMemberService.Setup(x => x.GetByUsername(It.Is(y => y == fakeUser.UserName))).Returns(fakeMember); _mockPasswordHasher.Setup(x => x.VerifyHashedPassword(It.IsAny(), It.IsAny(), It.IsAny())).Returns(PasswordVerificationResult.Success); //act await sut.CreateAsync(fakeUser); var result = await sut.ValidateCredentialsAsync(fakeUser.UserName, password); //assert Assert.IsTrue(result); } [Test] public async Task GivenAUserExists_AndIncorrectCredentialsAreProvided_ThenACheckOfCredentialsShouldFail() { //arrange var password = "password"; MemberManager sut = CreateSut(); MemberIdentityUser fakeUser = CreateValidUser(); IMember fakeMember = CreateMember(fakeUser); MockMemberServiceForCreateMember(fakeMember); _mockMemberService.Setup(x => x.GetByUsername(It.Is(y => y == fakeUser.UserName))).Returns(fakeMember); _mockPasswordHasher.Setup(x => x.VerifyHashedPassword(It.IsAny(), It.IsAny(), It.IsAny())).Returns(PasswordVerificationResult.Failed); //act await sut.CreateAsync(fakeUser); var result = await sut.ValidateCredentialsAsync(fakeUser.UserName, password); //assert Assert.IsFalse(result); } [Test] public async Task GivenAUserDoesExists_AndCredentialsAreProvided_ThenACheckOfCredentialsShouldFail() { //arrange var password = "password"; MemberManager sut = CreateSut(); _mockMemberService.Setup(x => x.GetByUsername(It.Is(y => y == "testUser"))).Returns((IMember)null); //act var result = await sut.ValidateCredentialsAsync("testUser", password); //assert Assert.IsFalse(result); } private static MemberIdentityUser CreateValidUser() => new MemberIdentityUser(777) { UserName = "testUser", Email = "test@test.com", Name = "Test", MemberTypeAlias = "Anything", PasswordConfig = "testConfig", PasswordHash = "hashedPassword" }; private static IMember CreateMember(MemberIdentityUser fakeUser) { var builder = new MemberTypeBuilder(); MemberType memberType = builder.BuildSimpleMemberType(); return new Member(memberType) { Id = 777, Username = fakeUser.UserName, }; } private void MockMemberServiceForCreateMember(IMember fakeMember) { _mockMemberService.Setup(x => x.CreateMember(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).Returns(fakeMember); _mockMemberService.Setup(x => x.Save(fakeMember)); } } }