Merge remote-tracking branch 'origin/netcore/netcore' into netcore/feature/macros

Signed-off-by: Bjarke Berg <mail@bergmania.dk>

# Conflicts:
#	src/Umbraco.Web.BackOffice/Extensions/UmbracoBackOfficeServiceCollectionExtensions.cs
This commit is contained in:
Bjarke Berg
2020-06-10 12:02:53 +02:00
79 changed files with 881 additions and 1423 deletions

View File

@@ -79,7 +79,7 @@ namespace Umbraco.Tests.Cache.PublishedCache
_umbracoContext = new UmbracoContext(
httpContextAccessor,
publishedSnapshotService.Object,
new WebSecurity(httpContextAccessor, Mock.Of<IUserService>(), globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -74,7 +74,7 @@ namespace Umbraco.Tests.PublishedContent
var umbracoContext = new UmbracoContext(
httpContextAccessor,
publishedSnapshotService.Object,
new WebSecurity(httpContextAccessor, ServiceContext.UserService, globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -123,7 +123,7 @@ namespace Umbraco.Tests.Scoping
var umbracoContext = new UmbracoContext(
httpContextAccessor,
service,
new WebSecurity(httpContextAccessor, ServiceContext.UserService, globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Tests.Security
var umbracoContext = new UmbracoContext(
httpContextAccessor,
Mock.Of<IPublishedSnapshotService>(),
new WebSecurity(httpContextAccessor, ServiceContext.UserService, globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),
@@ -58,7 +58,7 @@ namespace Umbraco.Tests.Security
var umbCtx = new UmbracoContext(
httpContextAccessor,
Mock.Of<IPublishedSnapshotService>(),
new WebSecurity(httpContextAccessor, ServiceContext.UserService, globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -1,278 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Logging;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Moq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.BackOffice;
using Umbraco.Core.Configuration;
using Umbraco.Core.Models.Membership;
using Umbraco.Net;
using Umbraco.Web.Security;
namespace Umbraco.Tests.Security
{
public class UmbracoSecurityStampValidatorTests
{
private Mock<IOwinContext> _mockOwinContext;
private Mock<BackOfficeOwinUserManager> _mockUserManager;
private Mock<BackOfficeSignInManager> _mockSignInManager;
private AuthenticationTicket _testAuthTicket;
private CookieAuthenticationOptions _testOptions;
private BackOfficeIdentityUser _testUser;
private const string _testAuthType = "cookie";
[Test]
public void OnValidateIdentity_When_GetUserIdCallback_Is_Null_Expect_ArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MaxValue, null, null));
}
[Test]
public async Task OnValidateIdentity_When_Validation_Interval_Not_Met_Expect_No_Op()
{
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MaxValue, null, identity => throw new Exception());
_testAuthTicket.Properties.IssuedUtc = DateTimeOffset.UtcNow;
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
await func(context);
Assert.AreEqual(_testAuthTicket.Identity, context.Identity);
}
[Test]
public void OnValidateIdentity_When_Time_To_Validate_But_No_UserManager_Expect_InvalidOperationException()
{
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => throw new Exception());
_mockOwinContext.Setup(x => x.Get<BackOfficeOwinUserManager>(It.IsAny<string>()))
.Returns((BackOfficeOwinUserManager) null);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
Assert.ThrowsAsync<InvalidOperationException>(async () => await func(context));
}
[Test]
public void OnValidateIdentity_When_Time_To_Validate_But_No_SignInManager_Expect_InvalidOperationException()
{
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => throw new Exception());
_mockOwinContext.Setup(x => x.Get<BackOfficeSignInManager>(It.IsAny<string>()))
.Returns((BackOfficeSignInManager) null);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
Assert.ThrowsAsync<InvalidOperationException>(async () => await func(context));
}
[Test]
public async Task OnValidateIdentity_When_Time_To_Validate_And_User_No_Longer_Found_Expect_Rejected()
{
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId))
.ReturnsAsync((BackOfficeIdentityUser) null);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
await func(context);
Assert.IsNull(context.Identity);
_mockOwinContext.Verify(x => x.Authentication.SignOut(_testAuthType), Times.Once);
}
[Test]
public async Task OnValidateIdentity_When_Time_To_Validate_And_User_Exists_And_Does_Not_Support_SecurityStamps_Expect_Rejected()
{
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
_mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(false);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
await func(context);
Assert.IsNull(context.Identity);
_mockOwinContext.Verify(x => x.Authentication.SignOut(_testAuthType), Times.Once);
}
[Test]
public async Task OnValidateIdentity_When_Time_To_Validate_And_SecurityStamp_Has_Changed_Expect_Rejected()
{
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
_mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(true);
_mockUserManager.Setup(x => x.GetSecurityStampAsync(_testUser)).ReturnsAsync(Guid.NewGuid().ToString);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
await func(context);
Assert.IsNull(context.Identity);
_mockOwinContext.Verify(x => x.Authentication.SignOut(_testAuthType), Times.Once);
}
[Test]
public async Task OnValidateIdentity_When_Time_To_Validate_And_SecurityStamp_Has_Not_Changed_Expect_No_Change()
{
var userId = Guid.NewGuid().ToString();
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, null, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
_mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(true);
_mockUserManager.Setup(x => x.GetSecurityStampAsync(_testUser)).ReturnsAsync(_testUser.SecurityStamp);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
await func(context);
Assert.AreEqual(_testAuthTicket.Identity, context.Identity);
}
[Test]
public async Task OnValidateIdentity_When_User_Validated_And_RegenerateIdentityCallback_Present_Expect_User_Refreshed()
{
var userId = Guid.NewGuid().ToString();
var expectedIdentity = new ClaimsIdentity(new List<Claim> {new Claim("sub", "bob")});
var regenFuncCalled = false;
Func<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser, Task<ClaimsIdentity>> regenFunc =
(signInManager, userManager, user) =>
{
regenFuncCalled = true;
return Task.FromResult(expectedIdentity);
};
var func = UmbracoSecurityStampValidator
.OnValidateIdentity<BackOfficeSignInManager, BackOfficeOwinUserManager, BackOfficeIdentityUser>(
TimeSpan.MinValue, regenFunc, identity => userId);
_mockUserManager.Setup(x => x.FindByIdAsync(userId)).ReturnsAsync(_testUser);
_mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(true);
_mockUserManager.Setup(x => x.GetSecurityStampAsync(_testUser)).ReturnsAsync(_testUser.SecurityStamp);
var context = new CookieValidateIdentityContext(
_mockOwinContext.Object,
_testAuthTicket,
_testOptions);
ClaimsIdentity callbackIdentity = null;
_mockOwinContext.Setup(x => x.Authentication.SignIn(context.Properties, It.IsAny<ClaimsIdentity>()))
.Callback((AuthenticationProperties props, ClaimsIdentity[] identities) => callbackIdentity = identities.FirstOrDefault())
.Verifiable();
await func(context);
Assert.True(regenFuncCalled);
Assert.AreEqual(expectedIdentity, callbackIdentity);
Assert.IsNull(context.Properties.IssuedUtc);
Assert.IsNull(context.Properties.ExpiresUtc);
_mockOwinContext.Verify();
}
[SetUp]
public void Setup()
{
var mockGlobalSettings = new Mock<IGlobalSettings>();
mockGlobalSettings.Setup(x => x.DefaultUILanguage).Returns("test");
_testUser = new BackOfficeIdentityUser(mockGlobalSettings.Object, 2, new List<IReadOnlyUserGroup>())
{
UserName = "alice",
Name = "Alice",
Email = "alice@umbraco.test",
SecurityStamp = Guid.NewGuid().ToString()
};
_testAuthTicket = new AuthenticationTicket(
new ClaimsIdentity(
new List<Claim> {new Claim("sub", "alice"), new Claim(Constants.Web.SecurityStampClaimType, _testUser.SecurityStamp)},
_testAuthType),
new AuthenticationProperties());
_testOptions = new CookieAuthenticationOptions { AuthenticationType = _testAuthType };
_mockUserManager = new Mock<BackOfficeOwinUserManager>(
new Mock<IPasswordConfiguration>().Object,
new Mock<IIpResolver>().Object,
new Mock<IUserStore<BackOfficeIdentityUser>>().Object,
null, null, null, null, null, null, null);
_mockUserManager.Setup(x => x.FindByIdAsync(It.IsAny<string>())).ReturnsAsync((BackOfficeIdentityUser) null);
_mockUserManager.Setup(x => x.SupportsUserSecurityStamp).Returns(false);
_mockSignInManager = new Mock<BackOfficeSignInManager>(
_mockUserManager.Object,
new Mock<IUserClaimsPrincipalFactory<BackOfficeIdentityUser>>().Object,
new Mock<IAuthenticationManager>().Object,
new Mock<ILogger>().Object,
new Mock<IGlobalSettings>().Object,
new Mock<IOwinRequest>().Object);
_mockOwinContext = new Mock<IOwinContext>();
_mockOwinContext.Setup(x => x.Get<BackOfficeOwinUserManager>(It.IsAny<string>()))
.Returns(_mockUserManager.Object);
_mockOwinContext.Setup(x => x.Get<BackOfficeSignInManager>(It.IsAny<string>()))
.Returns(_mockSignInManager.Object);
_mockOwinContext.Setup(x => x.Authentication.SignOut(It.IsAny<string>()));
}
}
}

View File

@@ -27,9 +27,9 @@ namespace Umbraco.Tests.TestHelpers.ControllerTesting
{
protected override Task<AuthenticationTicket> AuthenticateCoreAsync()
{
var sessionId = Guid.NewGuid().ToString();
var securityStamp = Guid.NewGuid().ToString();
var identity = new UmbracoBackOfficeIdentity(
-1, "admin", "Admin", new []{-1}, new[] { -1 }, "en-US", sessionId, sessionId, new[] { "content", "media", "members" }, new[] { "admin" });
-1, "admin", "Admin", new []{-1}, new[] { -1 }, "en-US", securityStamp, new[] { "content", "media", "members" }, new[] { "admin" });
return Task.FromResult(new AuthenticationTicket(identity,
new AuthenticationProperties()

View File

@@ -374,8 +374,7 @@ namespace Umbraco.Tests.TestHelpers
var umbracoContext = new UmbracoContext(
httpContextAccessor,
service,
new WebSecurity(httpContextAccessor, Factory.GetInstance<IUserService>(),
Factory.GetInstance<IGlobalSettings>(), HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings ?? Factory.GetInstance<IGlobalSettings>(),
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -149,7 +149,6 @@
<Compile Include="Persistence\Repositories\KeyValueRepositoryTests.cs" />
<Compile Include="Security\BackOfficeOwinUserManagerTests.cs" />
<Compile Include="Security\OwinDataProtectorTokenProviderTests.cs" />
<Compile Include="Security\UmbracoSecurityStampValidatorTests.cs" />
<Compile Include="Services\KeyValueServiceTests.cs" />
<Compile Include="Persistence\Repositories\UserRepositoryTest.cs" />
<Compile Include="UmbracoExamine\ExamineExtensions.cs" />

View File

@@ -60,93 +60,94 @@ namespace Umbraco.Tests.Web.Controllers
}
[Test]
public async System.Threading.Tasks.Task GetCurrentUser_Fips()
{
ApiController CtrlFactory(HttpRequestMessage message, IUmbracoContextAccessor umbracoContextAccessor)
{
//setup some mocks
var userServiceMock = Mock.Get(ServiceContext.UserService);
userServiceMock.Setup(service => service.GetUserById(It.IsAny<int>()))
.Returns(() => null);
if (Thread.GetDomain().GetData(".appPath") != null)
{
HttpContext.Current = new HttpContext(new SimpleWorkerRequest("", "", new StringWriter()));
}
else
{
var baseDir = IOHelper.MapPath("").TrimEnd(Path.DirectorySeparatorChar);
HttpContext.Current = new HttpContext(new SimpleWorkerRequest("/", baseDir, "", "", new StringWriter()));
}
var usersController = new AuthenticationController(
new TestUserPasswordConfig(),
Factory.GetInstance<IGlobalSettings>(),
Factory.GetInstance<IHostingEnvironment>(),
umbracoContextAccessor,
Factory.GetInstance<ISqlContext>(),
Factory.GetInstance<ServiceContext>(),
Factory.GetInstance<AppCaches>(),
Factory.GetInstance<IProfilingLogger>(),
Factory.GetInstance<IRuntimeState>(),
Factory.GetInstance<UmbracoMapper>(),
Factory.GetInstance<ISecuritySettings>(),
Factory.GetInstance<IPublishedUrlProvider>(),
Factory.GetInstance<IRequestAccessor>(),
Factory.GetInstance<IEmailSender>()
);
return usersController;
}
Mock.Get(Current.SqlContext)
.Setup(x => x.Query<IUser>())
.Returns(new Query<IUser>(Current.SqlContext));
var syntax = new SqlCeSyntaxProvider();
Mock.Get(Current.SqlContext)
.Setup(x => x.SqlSyntax)
.Returns(syntax);
var mappers = new MapperCollection(new[]
{
new UserMapper(new Lazy<ISqlContext>(() => Current.SqlContext), new ConcurrentDictionary<Type, ConcurrentDictionary<string, string>>())
});
Mock.Get(Current.SqlContext)
.Setup(x => x.Mappers)
.Returns(mappers);
// Testing what happens if the system were configured to only use FIPS-compliant algorithms
var typ = typeof(CryptoConfig);
var flds = typ.GetFields(BindingFlags.Static | BindingFlags.NonPublic);
var haveFld = flds.FirstOrDefault(f => f.Name == "s_haveFipsAlgorithmPolicy");
var isFld = flds.FirstOrDefault(f => f.Name == "s_fipsAlgorithmPolicy");
var originalFipsValue = CryptoConfig.AllowOnlyFipsAlgorithms;
try
{
if (!originalFipsValue)
{
haveFld.SetValue(null, true);
isFld.SetValue(null, true);
}
var runner = new TestRunner(CtrlFactory);
var response = await runner.Execute("Authentication", "GetCurrentUser", HttpMethod.Get);
var obj = JsonConvert.DeserializeObject<UserDetail>(response.Item2);
Assert.AreEqual(-1, obj.UserId);
}
finally
{
if (!originalFipsValue)
{
haveFld.SetValue(null, false);
isFld.SetValue(null, false);
}
}
}
// TODO Reintroduce when moved to .NET Core
// [Test]
// public async System.Threading.Tasks.Task GetCurrentUser_Fips()
// {
// ApiController CtrlFactory(HttpRequestMessage message, IUmbracoContextAccessor umbracoContextAccessor)
// {
// //setup some mocks
// var userServiceMock = Mock.Get(ServiceContext.UserService);
// userServiceMock.Setup(service => service.GetUserById(It.IsAny<int>()))
// .Returns(() => null);
//
// if (Thread.GetDomain().GetData(".appPath") != null)
// {
// HttpContext.Current = new HttpContext(new SimpleWorkerRequest("", "", new StringWriter()));
// }
// else
// {
// var baseDir = IOHelper.MapPath("").TrimEnd(Path.DirectorySeparatorChar);
// HttpContext.Current = new HttpContext(new SimpleWorkerRequest("/", baseDir, "", "", new StringWriter()));
// }
//
// var usersController = new AuthenticationController(
// new TestUserPasswordConfig(),
// Factory.GetInstance<IGlobalSettings>(),
// Factory.GetInstance<IHostingEnvironment>(),
// umbracoContextAccessor,
// Factory.GetInstance<ISqlContext>(),
// Factory.GetInstance<ServiceContext>(),
// Factory.GetInstance<AppCaches>(),
// Factory.GetInstance<IProfilingLogger>(),
// Factory.GetInstance<IRuntimeState>(),
// Factory.GetInstance<UmbracoMapper>(),
// Factory.GetInstance<ISecuritySettings>(),
// Factory.GetInstance<IPublishedUrlProvider>(),
// Factory.GetInstance<IRequestAccessor>(),
// Factory.GetInstance<IEmailSender>()
// );
// return usersController;
// }
//
// Mock.Get(Current.SqlContext)
// .Setup(x => x.Query<IUser>())
// .Returns(new Query<IUser>(Current.SqlContext));
//
// var syntax = new SqlCeSyntaxProvider();
//
// Mock.Get(Current.SqlContext)
// .Setup(x => x.SqlSyntax)
// .Returns(syntax);
//
// var mappers = new MapperCollection(new[]
// {
// new UserMapper(new Lazy<ISqlContext>(() => Current.SqlContext), new ConcurrentDictionary<Type, ConcurrentDictionary<string, string>>())
// });
//
// Mock.Get(Current.SqlContext)
// .Setup(x => x.Mappers)
// .Returns(mappers);
//
// // Testing what happens if the system were configured to only use FIPS-compliant algorithms
// var typ = typeof(CryptoConfig);
// var flds = typ.GetFields(BindingFlags.Static | BindingFlags.NonPublic);
// var haveFld = flds.FirstOrDefault(f => f.Name == "s_haveFipsAlgorithmPolicy");
// var isFld = flds.FirstOrDefault(f => f.Name == "s_fipsAlgorithmPolicy");
// var originalFipsValue = CryptoConfig.AllowOnlyFipsAlgorithms;
//
// try
// {
// if (!originalFipsValue)
// {
// haveFld.SetValue(null, true);
// isFld.SetValue(null, true);
// }
//
// var runner = new TestRunner(CtrlFactory);
// var response = await runner.Execute("Authentication", "GetCurrentUser", HttpMethod.Get);
//
// var obj = JsonConvert.DeserializeObject<UserDetail>(response.Item2);
// Assert.AreEqual(-1, obj.UserId);
// }
// finally
// {
// if (!originalFipsValue)
// {
// haveFld.SetValue(null, false);
// isFld.SetValue(null, false);
// }
// }
// }
}
}

View File

@@ -438,7 +438,7 @@ namespace Umbraco.Tests.Web.Mvc
var ctx = new UmbracoContext(
httpContextAccessor,
_service,
new WebSecurity(httpContextAccessor, ServiceContext.UserService, globalSettings, HostingEnvironment),
Mock.Of<IWebSecurity>(),
globalSettings,
HostingEnvironment,
new TestVariationContextAccessor(),

View File

@@ -32,7 +32,7 @@ namespace Umbraco.Tests.Web
var umbCtx = new UmbracoContext(
httpContextAccessor,
Mock.Of<IPublishedSnapshotService>(),
new WebSecurity(httpContextAccessor, ServiceContext.UserService, TestObjects.GetGlobalSettings(), HostingEnvironment),
Mock.Of<IWebSecurity>(),
TestObjects.GetGlobalSettings(),
HostingEnvironment,
new TestVariationContextAccessor(),
@@ -53,7 +53,7 @@ namespace Umbraco.Tests.Web
var umbCtx = new UmbracoContext(
httpContextAccessor,
Mock.Of<IPublishedSnapshotService>(),
new WebSecurity(httpContextAccessor, ServiceContext.UserService, TestObjects.GetGlobalSettings(), HostingEnvironment),
Mock.Of<IWebSecurity>(),
TestObjects.GetGlobalSettings(),
HostingEnvironment,
new TestVariationContextAccessor(),
@@ -84,7 +84,7 @@ namespace Umbraco.Tests.Web
var umbCtx = new UmbracoContext(
httpContextAccessor,
Mock.Of<IPublishedSnapshotService>(),
new WebSecurity(httpContextAccessor, ServiceContext.UserService, TestObjects.GetGlobalSettings(), HostingEnvironment),
Mock.Of<IWebSecurity>(),
TestObjects.GetGlobalSettings(),
HostingEnvironment,
new TestVariationContextAccessor(),