Adhered to linting rules for authorization policy handlers, requirements and tests.
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -32,8 +35,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Missing_QueryString_Value_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringName: "xxx");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
AdminUsersHandler sut = CreateHandler(queryStringName: "xxx");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -43,8 +46,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Non_Integer_QueryString_Value_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: "xxx");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
AdminUsersHandler sut = CreateHandler(queryStringValue: "xxx");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -54,8 +57,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Single_Admin_User_By_Admin_User_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: Admin2UserId.ToString(), editingWithAdmin: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
AdminUsersHandler sut = CreateHandler(queryStringValue: Admin2UserId.ToString(), editingWithAdmin: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -65,8 +68,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Single_Admin_User_By_Non_Admin_User_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: Admin2UserId.ToString());
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
AdminUsersHandler sut = CreateHandler(queryStringValue: Admin2UserId.ToString());
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -76,8 +79,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Single_Non_Admin_User_By_Non_Admin_User_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: NonAdmin2UserId.ToString());
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
AdminUsersHandler sut = CreateHandler(queryStringValue: NonAdmin2UserId.ToString());
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -87,8 +90,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Multiple_Users_Including_Admins_By_Admin_User_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
var sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{Admin2UserId},{NonAdmin2UserId}", editingWithAdmin: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
AdminUsersHandler sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{Admin2UserId},{NonAdmin2UserId}", editingWithAdmin: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -98,8 +101,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Multiple_Users_Including_Admins_By_Non_Admin_User_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
var sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{Admin2UserId},{NonAdmin2UserId}");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
AdminUsersHandler sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{Admin2UserId},{NonAdmin2UserId}");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -109,8 +112,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Editing_Multiple_Users_Not_Including_Admins_By_Non_Admin_User_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
var sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{NonAdmin2UserId},{NonAdmin3UserId}");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(queryStringName: MultipleUserEditQueryStringName);
|
||||
AdminUsersHandler sut = CreateHandler(queryStringName: MultipleUserEditQueryStringName, queryStringValue: $"{NonAdmin2UserId},{NonAdmin3UserId}");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -121,15 +124,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new AdminUsersRequirement(queryStringName);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private AdminUsersHandler CreateHandler(string queryStringName = SingleUserEditQueryStringName, string queryStringValue = "", bool editingWithAdmin = false)
|
||||
{
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName, queryStringValue);
|
||||
CreateMockUserServiceAndSecurityAccessor(editingWithAdmin, out var mockUserService, out var mockBackOfficeSecurityAccessor);
|
||||
var userEditorAuthorizationHelper = CreateUserEditorAuthorizationHelper();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName, queryStringValue);
|
||||
CreateMockUserServiceAndSecurityAccessor(editingWithAdmin, out Mock<IUserService> mockUserService, out Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor);
|
||||
UserEditorAuthorizationHelper userEditorAuthorizationHelper = CreateUserEditorAuthorizationHelper();
|
||||
return new AdminUsersHandler(mockHttpContextAccessor.Object, mockUserService.Object, mockBackOfficeSecurityAccessor.Object, userEditorAuthorizationHelper);
|
||||
}
|
||||
|
||||
@@ -152,11 +155,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
mockUserService = new Mock<IUserService>();
|
||||
var globalSettings = new GlobalSettings();
|
||||
var adminUser1 = CreateUser(Admin1UserId, mockUserService, true);
|
||||
var adminUser2 = CreateUser(Admin2UserId, mockUserService, true);
|
||||
var nonAdminUser1 = CreateUser(NonAdmin1UserId, mockUserService);
|
||||
var nonAdminUser2 = CreateUser(NonAdmin2UserId, mockUserService);
|
||||
var nonAdminUser3 = CreateUser(NonAdmin3UserId, mockUserService);
|
||||
User adminUser1 = CreateUser(Admin1UserId, mockUserService, true);
|
||||
User adminUser2 = CreateUser(Admin2UserId, mockUserService, true);
|
||||
User nonAdminUser1 = CreateUser(NonAdmin1UserId, mockUserService);
|
||||
User nonAdminUser2 = CreateUser(NonAdmin2UserId, mockUserService);
|
||||
User nonAdminUser3 = CreateUser(NonAdmin3UserId, mockUserService);
|
||||
|
||||
// Single user requests have been setup in the create user operations, but
|
||||
// we also need to mock the responses when multiple users are being editing.
|
||||
@@ -175,7 +178,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static User CreateUser(int id, Mock<IUserService> mockUserService, bool isAdmin = false)
|
||||
{
|
||||
var user = new UserBuilder()
|
||||
User user = new UserBuilder()
|
||||
.WithId(id)
|
||||
.AddUserGroup()
|
||||
.WithAlias(isAdmin ? Constants.Security.AdminGroupAlias : Constants.Security.EditorGroupAlias)
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
@@ -17,8 +20,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Runtime_State_Install_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(runtimeLevel: RuntimeLevel.Install);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
BackOfficeHandler sut = CreateHandler(runtimeLevel: RuntimeLevel.Install);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -28,8 +31,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Runtime_State_Upgrade_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(runtimeLevel: RuntimeLevel.Upgrade);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
BackOfficeHandler sut = CreateHandler(runtimeLevel: RuntimeLevel.Upgrade);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -39,8 +42,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Unauthenticated_User_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler();
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
BackOfficeHandler sut = CreateHandler();
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -50,8 +53,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Authenticated_User_Is_Not_Authorized_When_Not_Approved_And_Approval_Required()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(requireApproval: true);
|
||||
var sut = CreateHandler(currentUserIsAuthenticated: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(requireApproval: true);
|
||||
BackOfficeHandler sut = CreateHandler(currentUserIsAuthenticated: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -61,8 +64,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Authenticated_User_Is_Authorized_When_Not_Approved_And_Approval_Not_Required()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(currentUserIsAuthenticated: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
BackOfficeHandler sut = CreateHandler(currentUserIsAuthenticated: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -72,8 +75,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Authenticated_User_Is_Authorized_When_Approved_And_Approval_Required()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(requireApproval: true);
|
||||
var sut = CreateHandler(currentUserIsAuthenticated: true, currentUserIsApproved: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(requireApproval: true);
|
||||
BackOfficeHandler sut = CreateHandler(currentUserIsAuthenticated: true, currentUserIsApproved: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -84,20 +87,20 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new BackOfficeRequirement(requireApproval);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private BackOfficeHandler CreateHandler(RuntimeLevel runtimeLevel = RuntimeLevel.Run, bool currentUserIsAuthenticated = false, bool currentUserIsApproved = false)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(currentUserIsAuthenticated, currentUserIsApproved);
|
||||
var mockRuntimeState = CreateMockRuntimeState(runtimeLevel);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(currentUserIsAuthenticated, currentUserIsApproved);
|
||||
Mock<IRuntimeState> mockRuntimeState = CreateMockRuntimeState(runtimeLevel);
|
||||
return new BackOfficeHandler(mockBackOfficeSecurityAccessor.Object, mockRuntimeState.Object);
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(bool currentUserIsAuthenticated, bool currentUserIsApproved)
|
||||
{
|
||||
var user = new UserBuilder()
|
||||
global::Umbraco.Core.Models.Membership.User user = new UserBuilder()
|
||||
.WithIsApproved(currentUserIsApproved)
|
||||
.Build();
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -25,13 +28,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_With_Access_To_All_Descendent_Nodes_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IUserService> mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
{
|
||||
{ DescendentNodeId1, new string[] { "A" } },
|
||||
{ DescendentNodeId2, new string[] { "A" } }
|
||||
});
|
||||
var sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
ContentPermissionsPublishBranchHandler sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -42,13 +45,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Without_Access_To_One_Descendent_Node_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IUserService> mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
{
|
||||
{ DescendentNodeId1, new string[] { "A" } },
|
||||
{ DescendentNodeId2, new string[] { "B" } }
|
||||
});
|
||||
var sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
ContentPermissionsPublishBranchHandler sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -59,13 +62,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Without_Access_To_First_Descendent_Node_Is_Not_Authorized_And_Checks_Exit_Early()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IUserService> mockUserService = CreateMockUserService(NodeId, new Dictionary<int, string[]>
|
||||
{
|
||||
{ DescendentNodeId1, new string[] { "B" } },
|
||||
{ DescendentNodeId2, new string[] { "A" } }
|
||||
});
|
||||
var sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
ContentPermissionsPublishBranchHandler sut = CreateHandler(mockUserService.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -77,7 +80,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new ContentPermissionsPublishBranchRequirement('A');
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = CreateContent(NodeId);
|
||||
IContent resource = CreateContent(NodeId);
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
@@ -97,9 +100,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private ContentPermissionsPublishBranchHandler CreateHandler(IUserService userService, int nodeId)
|
||||
{
|
||||
var mockEntityService = CreateMockEntityService();
|
||||
var contentPermissions = CreateContentPermissions(mockEntityService.Object, userService, nodeId);
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
Mock<IEntityService> mockEntityService = CreateMockEntityService();
|
||||
ContentPermissions contentPermissions = CreateContentPermissions(mockEntityService.Object, userService, nodeId);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
return new ContentPermissionsPublishBranchHandler(mockEntityService.Object, contentPermissions, mockBackOfficeSecurityAccessor.Object);
|
||||
}
|
||||
|
||||
@@ -129,13 +132,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static IContent CreateContent(int nodeId)
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
ContentType contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
return ContentBuilder.CreateBasicContent(contentType, nodeId);
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
|
||||
{
|
||||
var user = CreateUser();
|
||||
User user = CreateUser();
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -143,10 +146,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser()
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser() =>
|
||||
new UserBuilder()
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
@@ -21,15 +24,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
private const string QueryStringName = "id";
|
||||
private const int NodeId = 1000;
|
||||
private static readonly Guid NodeGuid = Guid.NewGuid();
|
||||
private static readonly Udi NodeUdi = UdiParser.Parse($"umb://document/{NodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
|
||||
private static readonly Guid s_nodeGuid = Guid.NewGuid();
|
||||
private static readonly Udi s_nodeUdi = UdiParser.Parse($"umb://document/{s_nodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
|
||||
|
||||
[Test]
|
||||
public async Task Node_Id_From_Requirement_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor();
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor();
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -39,9 +42,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Id_From_Requirement_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor();
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor();
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -52,9 +55,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Id_Missing_From_Requirement_And_QueryString_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName: "xxx");
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName: "xxx");
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -64,9 +67,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Integer_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -77,9 +80,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Integer_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -90,9 +93,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Udi_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeUdi.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -103,9 +106,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Udi_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeUdi.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -116,9 +119,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Guid_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeGuid.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -129,9 +132,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Guid_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeGuid.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -142,9 +145,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Invalid_Id_From_QueryString_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
|
||||
ContentPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -154,11 +157,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
private static AuthorizationHandlerContext CreateAuthorizationHandlerContext(int? nodeId = null)
|
||||
{
|
||||
const char Permission = 'A';
|
||||
var requirement = nodeId.HasValue
|
||||
ContentPermissionsQueryStringRequirement requirement = nodeId.HasValue
|
||||
? new ContentPermissionsQueryStringRequirement(nodeId.Value, Permission)
|
||||
: new ContentPermissionsQueryStringRequirement(Permission, QueryStringName);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
@@ -180,9 +183,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private ContentPermissionsQueryStringHandler CreateHandler(IHttpContextAccessor httpContextAccessor, int nodeId, string[] permissionsForPath)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
var mockEntityService = CreateMockEntityService();
|
||||
var contentPermissions = CreateContentPermissions(mockEntityService.Object, nodeId, permissionsForPath);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
Mock<IEntityService> mockEntityService = CreateMockEntityService();
|
||||
ContentPermissions contentPermissions = CreateContentPermissions(mockEntityService.Object, nodeId, permissionsForPath);
|
||||
return new ContentPermissionsQueryStringHandler(mockBackOfficeSecurityAccessor.Object, httpContextAccessor, mockEntityService.Object, contentPermissions);
|
||||
}
|
||||
|
||||
@@ -190,17 +193,17 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var mockEntityService = new Mock<IEntityService>();
|
||||
mockEntityService
|
||||
.Setup(x => x.GetId(It.Is<Udi>(y => y == NodeUdi)))
|
||||
.Setup(x => x.GetId(It.Is<Udi>(y => y == s_nodeUdi)))
|
||||
.Returns(Attempt<int>.Succeed(NodeId));
|
||||
mockEntityService
|
||||
.Setup(x => x.GetId(It.Is<Guid>(y => y == NodeGuid), It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
|
||||
.Setup(x => x.GetId(It.Is<Guid>(y => y == s_nodeGuid), It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
|
||||
.Returns(Attempt<int>.Succeed(NodeId));
|
||||
return mockEntityService;
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
|
||||
{
|
||||
var user = CreateUser();
|
||||
User user = CreateUser();
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -208,11 +211,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser()
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser() =>
|
||||
new UserBuilder()
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static ContentPermissions CreateContentPermissions(IEntityService entityService, int nodeId, string[] permissionsForPath)
|
||||
{
|
||||
@@ -232,13 +233,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static IContent CreateContent(int nodeId)
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
ContentType contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
return ContentBuilder.CreateBasicContent(contentType, nodeId);
|
||||
}
|
||||
|
||||
private static void AssertContentCached(Mock<IHttpContextAccessor> mockHttpContextAccessor)
|
||||
{
|
||||
private static void AssertContentCached(Mock<IHttpContextAccessor> mockHttpContextAccessor) =>
|
||||
Assert.AreEqual(NodeId, ((IContent)mockHttpContextAccessor.Object.HttpContext.Items[typeof(IContent).ToString()]).Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -21,8 +24,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Node_Id_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
var sut = CreateHandler(NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
ContentPermissionsResourceHandler sut = CreateHandler(NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -32,8 +35,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Content_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var sut = CreateHandler(NodeId, new string[] { "A" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
ContentPermissionsResourceHandler sut = CreateHandler(NodeId, new string[] { "A" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -43,8 +46,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Node_Id_Withou_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
var sut = CreateHandler(NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
ContentPermissionsResourceHandler sut = CreateHandler(NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -54,8 +57,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Content_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var sut = CreateHandler(NodeId, new string[] { "B" });
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
ContentPermissionsResourceHandler sut = CreateHandler(NodeId, new string[] { "B" });
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -66,9 +69,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new ContentPermissionsResourceRequirement();
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var content = CreateContent(nodeId);
|
||||
var permissions = new List<char> { 'A' }.AsReadOnly();
|
||||
var resource = createWithNodeId
|
||||
IContent content = CreateContent(nodeId);
|
||||
System.Collections.ObjectModel.ReadOnlyCollection<char> permissions = new List<char> { 'A' }.AsReadOnly();
|
||||
ContentPermissionsResource resource = createWithNodeId
|
||||
? new ContentPermissionsResource(content, nodeId, permissions)
|
||||
: new ContentPermissionsResource(content, permissions);
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
@@ -76,20 +79,20 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static IContent CreateContent(int nodeId)
|
||||
{
|
||||
var contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
ContentType contentType = ContentTypeBuilder.CreateBasicContentType();
|
||||
return ContentBuilder.CreateBasicContent(contentType, nodeId);
|
||||
}
|
||||
|
||||
private ContentPermissionsResourceHandler CreateHandler(int nodeId, string[] permissionsForPath)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
var contentPermissions = CreateContentPermissions(nodeId, permissionsForPath);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor();
|
||||
ContentPermissions contentPermissions = CreateContentPermissions(nodeId, permissionsForPath);
|
||||
return new ContentPermissionsResourceHandler(mockBackOfficeSecurityAccessor.Object, contentPermissions);
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor()
|
||||
{
|
||||
var user = CreateUser();
|
||||
User user = CreateUser();
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -97,11 +100,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser()
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser() =>
|
||||
new UserBuilder()
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static ContentPermissions CreateContentPermissions(int nodeId, string[] permissionsForPath)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -6,7 +9,6 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Web.BackOffice.Authorization;
|
||||
using Umbraco.Web.BackOffice.Security;
|
||||
using Umbraco.Web.Common.Security;
|
||||
|
||||
namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -15,8 +17,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task With_Deny_Local_Login_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(denyLocalLogin: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
DenyLocalLoginHandler sut = CreateHandler(denyLocalLogin: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -26,8 +28,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Without_Deny_Local_Login_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler();
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
DenyLocalLoginHandler sut = CreateHandler();
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -38,13 +40,13 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new DenyLocalLoginRequirement();
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private DenyLocalLoginHandler CreateHandler(bool denyLocalLogin = false)
|
||||
{
|
||||
var mockBackOfficeExternalLoginProviders = CreateMockBackOfficeExternalLoginProviders(denyLocalLogin);
|
||||
Mock<IBackOfficeExternalLoginProviders> mockBackOfficeExternalLoginProviders = CreateMockBackOfficeExternalLoginProviders(denyLocalLogin);
|
||||
|
||||
return new DenyLocalLoginHandler(mockBackOfficeExternalLoginProviders.Object);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
@@ -21,15 +24,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
private const string QueryStringName = "id";
|
||||
private const int NodeId = 1000;
|
||||
private static readonly Guid NodeGuid = Guid.NewGuid();
|
||||
private static readonly Udi NodeUdi = UdiParser.Parse($"umb://document/{NodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
|
||||
private static readonly Guid s_nodeGuid = Guid.NewGuid();
|
||||
private static readonly Udi s_nodeUdi = UdiParser.Parse($"umb://document/{s_nodeGuid.ToString().ToLowerInvariant().Replace("-", string.Empty)}");
|
||||
|
||||
[Test]
|
||||
public async Task Node_Id_Missing_From_QueryString_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName: "xxx");
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringName: "xxx");
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -39,9 +42,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Integer_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -52,9 +55,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Integer_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeId.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -65,9 +68,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Udi_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeUdi.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -78,9 +81,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Udi_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeUdi.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeUdi.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -91,9 +94,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Guid_Id_From_QueryString_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeGuid.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -104,9 +107,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Guid_Id_From_QueryString_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: NodeGuid.ToString());
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: s_nodeGuid.ToString());
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId, startMediaId: 1001);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -117,9 +120,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Node_Invalid_Id_From_QueryString_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
|
||||
var sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue: "invalid");
|
||||
MediaPermissionsQueryStringHandler sut = CreateHandler(mockHttpContextAccessor.Object, NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -130,7 +133,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new MediaPermissionsQueryStringRequirement(QueryStringName);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
@@ -152,9 +155,9 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private MediaPermissionsQueryStringHandler CreateHandler(IHttpContextAccessor httpContextAccessor, int nodeId, int startMediaId = -1)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
|
||||
var mockEntityService = CreateMockEntityService();
|
||||
var mediaPermissions = CreateMediaPermissions(mockEntityService.Object, nodeId);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
|
||||
Mock<IEntityService> mockEntityService = CreateMockEntityService();
|
||||
MediaPermissions mediaPermissions = CreateMediaPermissions(mockEntityService.Object, nodeId);
|
||||
return new MediaPermissionsQueryStringHandler(mockBackOfficeSecurityAccessor.Object, httpContextAccessor, mockEntityService.Object, mediaPermissions);
|
||||
}
|
||||
|
||||
@@ -162,17 +165,17 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var mockEntityService = new Mock<IEntityService>();
|
||||
mockEntityService
|
||||
.Setup(x => x.GetId(It.Is<Udi>(y => y == NodeUdi)))
|
||||
.Setup(x => x.GetId(It.Is<Udi>(y => y == s_nodeUdi)))
|
||||
.Returns(Attempt<int>.Succeed(NodeId));
|
||||
mockEntityService
|
||||
.Setup(x => x.GetId(It.Is<Guid>(y => y == NodeGuid), It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
|
||||
.Setup(x => x.GetId(It.Is<Guid>(y => y == s_nodeGuid), It.Is<UmbracoObjectTypes>(y => y == UmbracoObjectTypes.Document)))
|
||||
.Returns(Attempt<int>.Succeed(NodeId));
|
||||
return mockEntityService;
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(int startMediaId)
|
||||
{
|
||||
var user = CreateUser(startMediaId);
|
||||
User user = CreateUser(startMediaId);
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -180,12 +183,10 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser(int startMediaId)
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser(int startMediaId) =>
|
||||
new UserBuilder()
|
||||
.WithStartMediaId(startMediaId)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static MediaPermissions CreateMediaPermissions(IEntityService entityService, int nodeId)
|
||||
{
|
||||
@@ -199,13 +200,11 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static IMedia CreateMedia(int nodeId)
|
||||
{
|
||||
var mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
|
||||
MediaType mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
|
||||
return MediaBuilder.CreateSimpleMedia(mediaType, "Test image", -1, nodeId);
|
||||
}
|
||||
|
||||
private static void AssertMediaCached(Mock<IHttpContextAccessor> mockHttpContextAccessor)
|
||||
{
|
||||
private static void AssertMediaCached(Mock<IHttpContextAccessor> mockHttpContextAccessor) =>
|
||||
Assert.AreEqual(NodeId, ((IMedia)mockHttpContextAccessor.Object.HttpContext.Items[typeof(IMedia).ToString()]).Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -20,8 +23,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Node_Id_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
var sut = CreateHandler(NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
MediaPermissionsResourceHandler sut = CreateHandler(NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -31,8 +34,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Media_With_Permission_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var sut = CreateHandler(NodeId);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
MediaPermissionsResourceHandler sut = CreateHandler(NodeId);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -42,8 +45,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Node_Id_Withou_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
var sut = CreateHandler(NodeId, startMediaId: 1001);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId, createWithNodeId: true);
|
||||
MediaPermissionsResourceHandler sut = CreateHandler(NodeId, startMediaId: 1001);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -53,8 +56,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Resource_With_Media_Without_Permission_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
var sut = CreateHandler(NodeId, startMediaId: 1001);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext(NodeId);
|
||||
MediaPermissionsResourceHandler sut = CreateHandler(NodeId, startMediaId: 1001);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -65,8 +68,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new MediaPermissionsResourceRequirement();
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var media = CreateMedia(nodeId);
|
||||
var resource = createWithNodeId
|
||||
IMedia media = CreateMedia(nodeId);
|
||||
MediaPermissionsResource resource = createWithNodeId
|
||||
? new MediaPermissionsResource(nodeId)
|
||||
: new MediaPermissionsResource(media);
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
@@ -74,20 +77,20 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static IMedia CreateMedia(int nodeId)
|
||||
{
|
||||
var mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
|
||||
MediaType mediaType = MediaTypeBuilder.CreateSimpleMediaType("image", "Image");
|
||||
return MediaBuilder.CreateSimpleMedia(mediaType, "Test image", -1, nodeId);
|
||||
}
|
||||
|
||||
private MediaPermissionsResourceHandler CreateHandler(int nodeId, int startMediaId = -1)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
|
||||
var contentPermissions = CreateMediaPermissions(nodeId, new string[0]);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(startMediaId);
|
||||
MediaPermissions contentPermissions = CreateMediaPermissions(nodeId);
|
||||
return new MediaPermissionsResourceHandler(mockBackOfficeSecurityAccessor.Object, contentPermissions);
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(int startMediaId)
|
||||
{
|
||||
var user = CreateUser(startMediaId);
|
||||
User user = CreateUser(startMediaId);
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -95,14 +98,12 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser(int startMediaId)
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser(int startMediaId) =>
|
||||
new UserBuilder()
|
||||
.WithStartMediaId(startMediaId)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static MediaPermissions CreateMediaPermissions(int nodeId, string[] permissionsForPath)
|
||||
private static MediaPermissions CreateMediaPermissions(int nodeId)
|
||||
{
|
||||
var mockMediaService = new Mock<IMediaService>();
|
||||
mockMediaService
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -17,8 +20,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Unauthorized_User_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler();
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
SectionHandler sut = CreateHandler();
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -28,8 +31,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_With_Section_Access_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(userIsAuthorized: true, userCanAccessContentSection: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
SectionHandler sut = CreateHandler(userIsAuthorized: true, userCanAccessContentSection: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -39,8 +42,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Without_Section_Access_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(userIsAuthorized: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
SectionHandler sut = CreateHandler(userIsAuthorized: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -51,20 +54,20 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new SectionRequirement(Constants.Applications.Content, Constants.Applications.Media);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private SectionHandler CreateHandler(bool userIsAuthorized = false, bool userCanAccessContentSection = false)
|
||||
{
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
|
||||
|
||||
return new SectionHandler(mockBackOfficeSecurityAccessor.Object);
|
||||
}
|
||||
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(bool userIsAuthorized, bool userCanAccessContentSection)
|
||||
{
|
||||
var user = CreateUser();
|
||||
User user = CreateUser();
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(userIsAuthorized ? user : null);
|
||||
mockBackOfficeSecurity
|
||||
@@ -78,10 +81,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser()
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser() =>
|
||||
new UserBuilder()
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -23,8 +26,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Unauthorized_User_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler();
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
TreeHandler sut = CreateHandler();
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -34,8 +37,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_With_Access_To_Tree_Section_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(userIsAuthorized: true, userCanAccessContentSection: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
TreeHandler sut = CreateHandler(userIsAuthorized: true, userCanAccessContentSection: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -45,8 +48,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Without_Access_To_Tree_Section_Is_Not_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(userIsAuthorized: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
TreeHandler sut = CreateHandler(userIsAuthorized: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -57,14 +60,14 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new TreeRequirement(Tree1Alias, Tree2Alias);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private TreeHandler CreateHandler(bool userIsAuthorized = false, bool userCanAccessContentSection = false)
|
||||
{
|
||||
var mockTreeService = CreateMockTreeService();
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
|
||||
Mock<ITreeService> mockTreeService = CreateMockTreeService();
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAuthorized, userCanAccessContentSection);
|
||||
|
||||
return new TreeHandler(mockTreeService.Object, mockBackOfficeSecurityAccessor.Object);
|
||||
}
|
||||
@@ -81,17 +84,15 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockTreeService;
|
||||
}
|
||||
|
||||
private static Tree CreateTree(string alias, string sectionAlias)
|
||||
{
|
||||
return new TreeBuilder()
|
||||
private static Tree CreateTree(string alias, string sectionAlias) =>
|
||||
new TreeBuilder()
|
||||
.WithAlias(alias)
|
||||
.WithSectionAlias(sectionAlias)
|
||||
.Build();
|
||||
}
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(bool userIsAuthorized, bool userCanAccessContentSection)
|
||||
{
|
||||
var user = CreateUser();
|
||||
User user = CreateUser();
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(userIsAuthorized ? user : null);
|
||||
mockBackOfficeSecurity
|
||||
@@ -105,10 +106,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser()
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser() => new UserBuilder()
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
@@ -30,8 +33,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Missing_QueryString_Value_Is_Authorized()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler();
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler();
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -41,8 +44,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task Admin_User_Is_Authorised()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: Group1Id.ToString(), userIsAdmin: true);
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler(queryStringValue: Group1Id.ToString(), userIsAdmin: true);
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -52,8 +55,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Matching_Single_Requested_Group_Id_Is_Authorised()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: Group1Id.ToString());
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler(queryStringValue: Group1Id.ToString());
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -63,8 +66,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Matching_One_Of_Requested_Group_Ids_Is_Authorised()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: $"{Group1Id},{Group2Id}");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler(queryStringValue: $"{Group1Id},{Group2Id}");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -74,8 +77,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Not_Matching_Single_Requested_Group_Id_Is_Not_Authorised()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: Group2Id.ToString());
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler(queryStringValue: Group2Id.ToString());
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -85,8 +88,8 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
[Test]
|
||||
public async Task User_Not_Matching_Any_Of_Requested_Group_Ids_Is_Not_Authorised()
|
||||
{
|
||||
var authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
var sut = CreateHandler(queryStringValue: $"{Group2Id},{Group3Id}");
|
||||
AuthorizationHandlerContext authHandlerContext = CreateAuthorizationHandlerContext();
|
||||
UserGroupHandler sut = CreateHandler(queryStringValue: $"{Group2Id},{Group3Id}");
|
||||
|
||||
await sut.HandleAsync(authHandlerContext);
|
||||
|
||||
@@ -97,21 +100,21 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
var requirement = new UserGroupRequirement(QueryStringName);
|
||||
var user = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>()));
|
||||
var resource = new object();
|
||||
object resource = new object();
|
||||
return new AuthorizationHandlerContext(new List<IAuthorizationRequirement> { requirement }, user, resource);
|
||||
}
|
||||
|
||||
private UserGroupHandler CreateHandler(string queryStringValue = "", bool userIsAdmin = false)
|
||||
{
|
||||
var mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue);
|
||||
Mock<IHttpContextAccessor> mockHttpContextAccessor = CreateMockHttpContextAccessor(queryStringValue);
|
||||
|
||||
var mockUserService = CreateMockUserService();
|
||||
Mock<IUserService> mockUserService = CreateMockUserService();
|
||||
|
||||
var mockContentService = new Mock<IContentService>();
|
||||
var mockMediaService = new Mock<IMediaService>();
|
||||
var mockEntityService = new Mock<IEntityService>();
|
||||
|
||||
var mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAdmin);
|
||||
Mock<IBackOfficeSecurityAccessor> mockBackOfficeSecurityAccessor = CreateMockBackOfficeSecurityAccessor(userIsAdmin);
|
||||
|
||||
return new UserGroupHandler(mockHttpContextAccessor.Object, mockUserService.Object, mockContentService.Object, mockMediaService.Object, mockEntityService.Object, mockBackOfficeSecurityAccessor.Object);
|
||||
}
|
||||
@@ -151,7 +154,7 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
private static Mock<IBackOfficeSecurityAccessor> CreateMockBackOfficeSecurityAccessor(bool userIsAdmin)
|
||||
{
|
||||
var user = CreateUser(userIsAdmin);
|
||||
User user = CreateUser(userIsAdmin);
|
||||
var mockBackOfficeSecurity = new Mock<IBackOfficeSecurity>();
|
||||
mockBackOfficeSecurity.SetupGet(x => x.CurrentUser).Returns(user);
|
||||
var mockBackOfficeSecurityAccessor = new Mock<IBackOfficeSecurityAccessor>();
|
||||
@@ -159,21 +162,17 @@ namespace Umbraco.Tests.UnitTests.Umbraco.Web.BackOffice.Authorization
|
||||
return mockBackOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
private static User CreateUser(bool isAdmin = false)
|
||||
{
|
||||
return new UserBuilder()
|
||||
private static User CreateUser(bool isAdmin = false) =>
|
||||
new UserBuilder()
|
||||
.AddUserGroup()
|
||||
.WithAlias(isAdmin ? Constants.Security.AdminGroupAlias : Group1Alias)
|
||||
.Done()
|
||||
.Build();
|
||||
}
|
||||
|
||||
private IUserGroup CreateUserGroup(int id, string alias)
|
||||
{
|
||||
return new UserGroupBuilder()
|
||||
private IUserGroup CreateUserGroup(int id, string alias) =>
|
||||
new UserGroupBuilder()
|
||||
.WithId(id)
|
||||
.WithAlias(alias)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
using System.Linq;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -14,25 +19,34 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class AdminUsersHandler : MustSatisfyRequirementAuthorizationHandler<AdminUsersRequirement>
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAcessor;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
private readonly UserEditorAuthorizationHelper _userEditorAuthorizationHelper;
|
||||
|
||||
public AdminUsersHandler(IHttpContextAccessor httpContextAcessor,
|
||||
IUserService userService,
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
UserEditorAuthorizationHelper userEditorAuthorizationHelper)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AdminUsersHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpContextAccessor">Accessor for the HTTP context of the current request.</param>
|
||||
/// <param name="userService">Service for user related operations.</param>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="userEditorAuthorizationHelper">Helper for user authorization checks.</param>
|
||||
public AdminUsersHandler(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IUserService userService,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
UserEditorAuthorizationHelper userEditorAuthorizationHelper)
|
||||
{
|
||||
_httpContextAcessor = httpContextAcessor;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userService = userService;
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
_userEditorAuthorizationHelper = userEditorAuthorizationHelper;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, AdminUsersRequirement requirement)
|
||||
{
|
||||
var queryString = _httpContextAcessor.HttpContext?.Request.Query[requirement.QueryStringName];
|
||||
StringValues? queryString = _httpContextAccessor.HttpContext?.Request.Query[requirement.QueryStringName];
|
||||
if (!queryString.HasValue || !queryString.Value.Any())
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it.
|
||||
@@ -46,12 +60,13 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
}
|
||||
else
|
||||
{
|
||||
var ids = _httpContextAcessor.HttpContext.Request.Query.Where(x => x.Key == requirement.QueryStringName).ToList();
|
||||
var ids = _httpContextAccessor.HttpContext.Request.Query.Where(x => x.Key == requirement.QueryStringName).ToList();
|
||||
if (ids.Count == 0)
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it.
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
userIds = ids
|
||||
.Select(x => x.Value.ToString())
|
||||
.Select(x => x.TryConvertTo<int>()).Where(x => x.Success).Select(x => x.Result).ToArray();
|
||||
@@ -63,8 +78,8 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
var users = _userService.GetUsersById(userIds);
|
||||
var isAuth = users.All(user => _userEditorAuthorizationHelper.IsAuthorized(_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser, user, null, null, null) != false);
|
||||
IEnumerable<Core.Models.Membership.IUser> users = _userService.GetUsersById(userIds);
|
||||
var isAuth = users.All(user => _userEditorAuthorizationHelper.IsAuthorized(_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser, user, null, null, null) != false);
|
||||
|
||||
return Task.FromResult(isAuth);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -7,11 +10,15 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class AdminUsersRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public AdminUsersRequirement(string queryStringName = "id")
|
||||
{
|
||||
QueryStringName = queryStringName;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AdminUsersRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="queryStringName">Query string name from which to authorize values.</param>
|
||||
public AdminUsersRequirement(string queryStringName = "id") => QueryStringName = queryStringName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query string name from which to authorize values.
|
||||
/// </summary>
|
||||
public string QueryStringName { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core;
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -7,11 +10,15 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class BackOfficeRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public BackOfficeRequirement(bool requireApproval = true)
|
||||
{
|
||||
RequireApproval = requireApproval;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="BackOfficeRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="requireApproval">Flag for whether back-office user approval is required.</param>
|
||||
public BackOfficeRequirement(bool requireApproval = true) => RequireApproval = requireApproval;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether back-office user approval is required.
|
||||
/// </summary>
|
||||
public bool RequireApproval { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
@@ -11,7 +14,7 @@ using Umbraco.Core.Services;
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// The user must have access to all descendant nodes of the content item in order to continue
|
||||
/// The user must have access to all descendant nodes of the content item in order to continue.
|
||||
/// </summary>
|
||||
public class ContentPermissionsPublishBranchHandler : MustSatisfyRequirementAuthorizationHandler<ContentPermissionsPublishBranchRequirement, IContent>
|
||||
{
|
||||
@@ -19,6 +22,12 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
private readonly ContentPermissions _contentPermissions;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsPublishBranchHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="entityService">Service for entity operations.</param>
|
||||
/// <param name="contentPermissions">per for user content authorization checks.</param>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
public ContentPermissionsPublishBranchHandler(
|
||||
IEntityService entityService,
|
||||
ContentPermissions contentPermissions,
|
||||
@@ -29,9 +38,10 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, ContentPermissionsPublishBranchRequirement requirement, IContent resource)
|
||||
{
|
||||
var currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
|
||||
Core.Models.Membership.IUser currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
|
||||
|
||||
var denied = new List<IUmbracoEntity>();
|
||||
var page = 0;
|
||||
@@ -40,16 +50,22 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
|
||||
while (page * pageSize < total)
|
||||
{
|
||||
var descendants = _entityService.GetPagedDescendants(resource.Id, UmbracoObjectTypes.Document, page++, pageSize, out total,
|
||||
// Order by shallowest to deepest, this allows us to check permissions from top to bottom so we can exit
|
||||
// early if a permission higher up fails.
|
||||
ordering: Ordering.By("path", Direction.Ascending));
|
||||
// Order descendents by shallowest to deepest, this allows us to check permissions from top to bottom so we can exit
|
||||
// early if a permission higher up fails.
|
||||
IEnumerable<IEntitySlim> descendants = _entityService.GetPagedDescendants(
|
||||
resource.Id,
|
||||
UmbracoObjectTypes.Document,
|
||||
page++,
|
||||
pageSize,
|
||||
out total,
|
||||
ordering: Ordering.By("path", Direction.Ascending));
|
||||
|
||||
foreach (var c in descendants)
|
||||
foreach (IEntitySlim c in descendants)
|
||||
{
|
||||
// If this item's path has already been denied or if the user doesn't have access to it, add to the deny list.
|
||||
if (denied.Any(x => c.Path.StartsWith($"{x.Path},"))
|
||||
|| (_contentPermissions.CheckPermissions(c,
|
||||
if (denied.Any(x => c.Path.StartsWith($"{x.Path},")) ||
|
||||
(_contentPermissions.CheckPermissions(
|
||||
c,
|
||||
currentUser,
|
||||
requirement.Permission) == ContentPermissions.ContentAccess.Denied))
|
||||
{
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -7,11 +10,15 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class ContentPermissionsPublishBranchRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public ContentPermissionsPublishBranchRequirement(char permission)
|
||||
{
|
||||
Permission = permission;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsPublishBranchRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="permission">Permission to check.</param>
|
||||
public ContentPermissionsPublishBranchRequirement(char permission) => Permission = permission;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value for the permission to check.
|
||||
/// </summary>
|
||||
public char Permission { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Umbraco.Core;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -10,28 +12,33 @@ using Umbraco.Core.Services;
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to authorize if the user has the correct permission access to the content for the content id specified in a query string
|
||||
/// Used to authorize if the user has the correct permission access to the content for the content id specified in a query string.
|
||||
/// </summary>
|
||||
public class ContentPermissionsQueryStringHandler : PermissionsQueryStringHandler<ContentPermissionsQueryStringRequirement>
|
||||
{
|
||||
private readonly ContentPermissions _contentPermissions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsQueryStringHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="httpContextAccessor">Accessor for the HTTP context of the current request.</param>
|
||||
/// <param name="entityService">Service for entity operations.</param>
|
||||
/// <param name="contentPermissions">Helper for content authorization checks.</param>
|
||||
public ContentPermissionsQueryStringHandler(
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IEntityService entityService,
|
||||
ContentPermissions contentPermissions)
|
||||
: base(backofficeSecurityAccessor, httpContextAccessor, entityService)
|
||||
{
|
||||
_contentPermissions = contentPermissions;
|
||||
}
|
||||
: base(backOfficeSecurityAccessor, httpContextAccessor, entityService) => _contentPermissions = contentPermissions;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, ContentPermissionsQueryStringRequirement requirement)
|
||||
{
|
||||
int nodeId;
|
||||
if (requirement.NodeId.HasValue == false)
|
||||
{
|
||||
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out var routeVal))
|
||||
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it
|
||||
return Task.FromResult(true);
|
||||
@@ -52,8 +59,9 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
nodeId = requirement.NodeId.Value;
|
||||
}
|
||||
|
||||
var permissionResult = _contentPermissions.CheckPermissions(nodeId,
|
||||
BackofficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
ContentPermissions.ContentAccess permissionResult = _contentPermissions.CheckPermissions(
|
||||
nodeId,
|
||||
BackOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
out IContent contentItem,
|
||||
new[] { requirement.PermissionToCheck });
|
||||
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An authorization requirement for <see cref="ContentPermissionsQueryStringHandler"/>
|
||||
/// </summary>
|
||||
public class ContentPermissionsQueryStringRequirement : IAuthorizationRequirement
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Create an authorization requirement for a specific node id
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsQueryStringRequirement"/> class for a specific node id.
|
||||
/// </summary>
|
||||
/// <param name="nodeId"></param>
|
||||
/// <param name="permissionToCheck"></param>
|
||||
/// <param name="nodeId">The node Id.</param>
|
||||
/// <param name="permissionToCheck">The permission to authorize the current user against.</param>
|
||||
public ContentPermissionsQueryStringRequirement(int nodeId, char permissionToCheck)
|
||||
{
|
||||
NodeId = nodeId;
|
||||
@@ -21,18 +22,30 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create an authorization requirement for a node id based on a query string parameter
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsQueryStringRequirement"/> class for a
|
||||
/// node id based on a query string parameter.
|
||||
/// </summary>
|
||||
/// <param name="paramName"></param>
|
||||
/// <param name="permissionToCheck"></param>
|
||||
/// <param name="paramName">The querystring parameter name.</param>
|
||||
/// <param name="permissionToCheck">The permission to authorize the current user against.</param>
|
||||
public ContentPermissionsQueryStringRequirement(char permissionToCheck, string paramName = "id")
|
||||
{
|
||||
QueryStringName = paramName;
|
||||
PermissionToCheck = permissionToCheck;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the specific node Id.
|
||||
/// </summary>
|
||||
public int? NodeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the querystring parameter name.
|
||||
/// </summary>
|
||||
public string QueryStringName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the permission to authorize the current user against.
|
||||
/// </summary>
|
||||
public char PermissionToCheck { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
@@ -8,27 +11,54 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class ContentPermissionsResource
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsResource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="permissionToCheck">The permission to authorize.</param>
|
||||
public ContentPermissionsResource(IContent content, char permissionToCheck)
|
||||
{
|
||||
PermissionsToCheck = new List<char> { permissionToCheck };
|
||||
Content = content;
|
||||
}
|
||||
|
||||
public ContentPermissionsResource(IContent content, IReadOnlyList<char> permissionToCheck)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsResource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="permissionsToCheck">The collection of permissions to authorize.</param>
|
||||
public ContentPermissionsResource(IContent content, IReadOnlyList<char> permissionsToCheck)
|
||||
{
|
||||
Content = content;
|
||||
PermissionsToCheck = permissionToCheck;
|
||||
PermissionsToCheck = permissionsToCheck;
|
||||
}
|
||||
|
||||
public ContentPermissionsResource(IContent content, int nodeId, IReadOnlyList<char> permissionToCheck)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsResource"/> class.
|
||||
/// </summary>
|
||||
/// <param name="content">The content.</param>
|
||||
/// <param name="nodeId">The node Id.</param>
|
||||
/// <param name="permissionsToCheck">The collection of permissions to authorize.</param>
|
||||
public ContentPermissionsResource(IContent content, int nodeId, IReadOnlyList<char> permissionsToCheck)
|
||||
{
|
||||
Content = content;
|
||||
NodeId = nodeId;
|
||||
PermissionsToCheck = permissionToCheck;
|
||||
PermissionsToCheck = permissionsToCheck;
|
||||
}
|
||||
|
||||
public int? NodeId { get; }
|
||||
/// <summary>
|
||||
/// Gets the node Id.
|
||||
/// </summary>
|
||||
public int? NodeId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the collection of permissions to authorize.
|
||||
/// </summary>
|
||||
public IReadOnlyList<char> PermissionsToCheck { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the content.
|
||||
/// </summary>
|
||||
public IContent Content { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System.Threading.Tasks;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
@@ -10,28 +13,34 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class ContentPermissionsResourceHandler : MustSatisfyRequirementAuthorizationHandler<ContentPermissionsResourceRequirement, ContentPermissionsResource>
|
||||
{
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
private readonly ContentPermissions _contentPermissions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContentPermissionsResourceHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="contentPermissions">Helper for content authorization checks.</param>
|
||||
public ContentPermissionsResourceHandler(
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
ContentPermissions contentPermissions)
|
||||
{
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
_contentPermissions = contentPermissions;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, ContentPermissionsResourceRequirement requirement, ContentPermissionsResource resource)
|
||||
{
|
||||
var permissionResult = resource.NodeId.HasValue
|
||||
ContentPermissions.ContentAccess permissionResult = resource.NodeId.HasValue
|
||||
? _contentPermissions.CheckPermissions(
|
||||
resource.NodeId.Value,
|
||||
_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
out IContent _,
|
||||
resource.PermissionsToCheck)
|
||||
: _contentPermissions.CheckPermissions(
|
||||
resource.Content,
|
||||
_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
resource.PermissionsToCheck);
|
||||
|
||||
return Task.FromResult(permissionResult != ContentPermissions.ContentAccess.Denied);
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Web.Actions;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An authorization requirement for <see cref="ContentPermissionsResourceHandler"/>
|
||||
/// </summary>
|
||||
|
||||
@@ -1,26 +1,27 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Web.BackOffice.Security;
|
||||
using Umbraco.Web.Common.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the resource cannot be accessed if <see cref="IBackOfficeExternalLoginProviders.HasDenyLocalLogin"/> returns true
|
||||
/// Ensures the resource cannot be accessed if <see cref="IBackOfficeExternalLoginProviders.HasDenyLocalLogin"/> returns true.
|
||||
/// </summary>
|
||||
public class DenyLocalLoginHandler : MustSatisfyRequirementAuthorizationHandler<DenyLocalLoginRequirement>
|
||||
{
|
||||
private readonly IBackOfficeExternalLoginProviders _externalLogins;
|
||||
|
||||
public DenyLocalLoginHandler(IBackOfficeExternalLoginProviders externalLogins)
|
||||
{
|
||||
_externalLogins = externalLogins;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DenyLocalLoginHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="externalLogins">Provides access to <see cref="BackOfficeExternalLoginProvider" /> instances.</param>
|
||||
public DenyLocalLoginHandler(IBackOfficeExternalLoginProviders externalLogins) => _externalLogins = externalLogins;
|
||||
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, DenyLocalLoginRequirement requirement)
|
||||
{
|
||||
return Task.FromResult(!_externalLogins.HasDenyLocalLogin());
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, DenyLocalLoginRequirement requirement) =>
|
||||
Task.FromResult(!_externalLogins.HasDenyLocalLogin());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker requirement for the <see cref="DenyLocalLoginHandler"/>
|
||||
/// Marker requirement for the <see cref="DenyLocalLoginHandler"/>.
|
||||
/// </summary>
|
||||
public class DenyLocalLoginRequirement : IAuthorizationRequirement
|
||||
{
|
||||
|
||||
@@ -1,29 +1,41 @@
|
||||
using System.Threading.Tasks;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to authorize if the user has the correct permission access to the media for the media id specified in a query string.
|
||||
/// </summary>
|
||||
public class MediaPermissionsQueryStringHandler : PermissionsQueryStringHandler<MediaPermissionsQueryStringRequirement>
|
||||
{
|
||||
private readonly MediaPermissions _mediaPermissions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaPermissionsQueryStringHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="httpContextAccessor">Accessor for the HTTP context of the current request.</param>
|
||||
/// <param name="entityService">Service for entity operations.</param>
|
||||
/// <param name="mediaPermissions">Helper for media authorization checks.</param>
|
||||
public MediaPermissionsQueryStringHandler(
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IEntityService entityService,
|
||||
MediaPermissions mediaPermissions)
|
||||
: base(backofficeSecurityAccessor, httpContextAccessor, entityService)
|
||||
{
|
||||
_mediaPermissions = mediaPermissions;
|
||||
}
|
||||
: base(backOfficeSecurityAccessor, httpContextAccessor, entityService) => _mediaPermissions = mediaPermissions;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, MediaPermissionsQueryStringRequirement requirement)
|
||||
{
|
||||
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out var routeVal))
|
||||
if (!HttpContextAccessor.HttpContext.Request.Query.TryGetValue(requirement.QueryStringName, out StringValues routeVal))
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it.
|
||||
return Task.FromResult(true);
|
||||
@@ -37,10 +49,10 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
var permissionResult = _mediaPermissions.CheckPermissions(
|
||||
BackofficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
MediaPermissions.MediaAccess permissionResult = _mediaPermissions.CheckPermissions(
|
||||
BackOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
nodeId,
|
||||
out var mediaItem);
|
||||
out IMedia mediaItem);
|
||||
|
||||
if (mediaItem != null)
|
||||
{
|
||||
@@ -53,6 +65,6 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
MediaPermissions.MediaAccess.Denied => Task.FromResult(false),
|
||||
_ => Task.FromResult(true),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// An authorization requirement for <see cref="MediaPermissionsQueryStringHandler"/>
|
||||
/// </summary>
|
||||
public class MediaPermissionsQueryStringRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public MediaPermissionsQueryStringRequirement(string paramName)
|
||||
{
|
||||
QueryStringName = paramName;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaPermissionsQueryStringRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="paramName">Querystring paramter name.</param>
|
||||
public MediaPermissionsQueryStringRequirement(string paramName) => QueryStringName = paramName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the querystring paramter name.
|
||||
/// </summary>
|
||||
public string QueryStringName { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Umbraco.Core.Models;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
@@ -1,36 +1,45 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to authorize if the user has the correct permission access to the content for the <see cref="IContent"/> specified
|
||||
/// Used to authorize if the user has the correct permission access to the content for the <see cref="IContent"/> specified.
|
||||
/// </summary>
|
||||
public class MediaPermissionsResourceHandler : MustSatisfyRequirementAuthorizationHandler<MediaPermissionsResourceRequirement, MediaPermissionsResource>
|
||||
{
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
private readonly MediaPermissions _mediaPermissions;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MediaPermissionsResourceHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="mediaPermissions">Helper for media authorization checks.</param>
|
||||
public MediaPermissionsResourceHandler(
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
MediaPermissions mediaPermissions)
|
||||
{
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
_mediaPermissions = mediaPermissions;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, MediaPermissionsResourceRequirement requirement, MediaPermissionsResource resource)
|
||||
{
|
||||
var permissionResult = resource.NodeId.HasValue
|
||||
MediaPermissions.MediaAccess permissionResult = resource.NodeId.HasValue
|
||||
? _mediaPermissions.CheckPermissions(
|
||||
_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser,
|
||||
resource.NodeId.Value,
|
||||
out _)
|
||||
: _mediaPermissions.CheckPermissions(
|
||||
resource.Media,
|
||||
_backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser);
|
||||
_backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser);
|
||||
|
||||
return Task.FromResult(permissionResult != MediaPermissions.MediaAccess.Denied);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// An authorization requirement for <see cref="MediaPermissionsResourceHandler"/>
|
||||
/// </summary>
|
||||
public class MediaPermissionsResourceRequirement : IAuthorizationRequirement
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract handler that must satisfy the requirement so Succeed or Fail will be called no matter what
|
||||
/// Abstract handler that must satisfy the requirement so Succeed or Fail will be called no matter what.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="T">Authorization requirement.</typeparam>
|
||||
/// <remarks>
|
||||
/// aspnetcore Authz handlers are not required to satisfy the requirement and generally don't explicitly call Fail when the requirement
|
||||
/// isn't satisfied, however in many simple cases explicitly calling Succeed or Fail is what we want which is what this class is used for.
|
||||
/// </remarks>
|
||||
public abstract class MustSatisfyRequirementAuthorizationHandler<T> : AuthorizationHandler<T> where T : IAuthorizationRequirement
|
||||
public abstract class MustSatisfyRequirementAuthorizationHandler<T> : AuthorizationHandler<T>
|
||||
where T : IAuthorizationRequirement
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, T requirement)
|
||||
{
|
||||
var isAuth = await IsAuthorized(context, requirement);
|
||||
@@ -29,23 +34,25 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// <summary>
|
||||
/// Return true if the requirement is succeeded or ignored, return false if the requirement is explicitly not met
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="requirement"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="context">The authorization context.</param>
|
||||
/// <param name="requirement">The authorization requirement.</param>
|
||||
/// <returns>True if request is authorized, false if not.</returns>
|
||||
protected abstract Task<bool> IsAuthorized(AuthorizationHandlerContext context, T requirement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Abstract handler that must satisfy the requirement so Succeed or Fail will be called no matter what
|
||||
/// Abstract handler that must satisfy the requirement so Succeed or Fail will be called no matter what.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <typeparam name="TResource"></typeparam>
|
||||
/// <typeparam name="T">Authorization requirement.</typeparam>
|
||||
/// <typeparam name="TResource">Resource to authorize access to.</typeparam>
|
||||
/// <remarks>
|
||||
/// aspnetcore Authz handlers are not required to satisfy the requirement and generally don't explicitly call Fail when the requirement
|
||||
/// isn't satisfied, however in many simple cases explicitly calling Succeed or Fail is what we want which is what this class is used for.
|
||||
/// </remarks>
|
||||
public abstract class MustSatisfyRequirementAuthorizationHandler<T, TResource> : AuthorizationHandler<T, TResource> where T : IAuthorizationRequirement
|
||||
public abstract class MustSatisfyRequirementAuthorizationHandler<T, TResource> : AuthorizationHandler<T, TResource>
|
||||
where T : IAuthorizationRequirement
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, T requirement, TResource resource)
|
||||
{
|
||||
var isAuth = await IsAuthorized(context, requirement, resource);
|
||||
@@ -62,9 +69,10 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// <summary>
|
||||
/// Return true if the requirement is succeeded or ignored, return false if the requirement is explicitly not met
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <param name="requirement"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="context">The authorization context.</param>
|
||||
/// <param name="requirement">The authorization requirement.</param>
|
||||
/// <param name="resource">The resource to authorize access to.</param>
|
||||
/// <returns>True if request is authorized, false if not.</returns>
|
||||
protected abstract Task<bool> IsAuthorized(AuthorizationHandlerContext context, T requirement, TResource resource);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using System;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Umbraco.Core;
|
||||
@@ -8,25 +11,50 @@ using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract base class providing common functionality for authorization checks based on querystrings.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Authorization requirement</typeparam>
|
||||
public abstract class PermissionsQueryStringHandler<T> : MustSatisfyRequirementAuthorizationHandler<T>
|
||||
where T : IAuthorizationRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PermissionsQueryStringHandler{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
/// <param name="httpContextAccessor">Accessor for the HTTP context of the current request.</param>
|
||||
/// <param name="entityService">Service for entity operations.</param>
|
||||
public PermissionsQueryStringHandler(
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IEntityService entityService)
|
||||
{
|
||||
BackofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
BackOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
HttpContextAccessor = httpContextAccessor;
|
||||
EntityService = entityService;
|
||||
}
|
||||
|
||||
protected IBackOfficeSecurityAccessor BackofficeSecurityAccessor { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IBackOfficeSecurityAccessor" /> instance.
|
||||
/// </summary>
|
||||
protected IBackOfficeSecurityAccessor BackOfficeSecurityAccessor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IHttpContextAccessor" /> instance.
|
||||
/// </summary>
|
||||
protected IHttpContextAccessor HttpContextAccessor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the <see cref="IEntityService" /> instance.
|
||||
/// </summary>
|
||||
protected IEntityService EntityService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to parse a node ID from a string representation found in a querystring value.
|
||||
/// </summary>
|
||||
/// <param name="argument">Querystring value.</param>
|
||||
/// <param name="nodeId">Output parsed Id.</param>
|
||||
/// <returns>True of node ID could be parased, false it not.</returns>
|
||||
protected bool TryParseNodeId(string argument, out int nodeId)
|
||||
{
|
||||
// If the argument is an int, it will parse and can be assigned to nodeId.
|
||||
@@ -38,12 +66,12 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
nodeId = parsedId;
|
||||
return true;
|
||||
}
|
||||
else if (UdiParser.TryParse(argument, true, out var udi))
|
||||
else if (UdiParser.TryParse(argument, true, out Udi udi))
|
||||
{
|
||||
nodeId = EntityService.GetId(udi).Result;
|
||||
return true;
|
||||
}
|
||||
else if (Guid.TryParse(argument, out var key))
|
||||
else if (Guid.TryParse(argument, out Guid key))
|
||||
{
|
||||
nodeId = EntityService.GetId(key, UmbracoObjectTypes.Document).Result;
|
||||
return true;
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the current user has access to the section
|
||||
/// </summary>
|
||||
@@ -14,18 +16,21 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </remarks>
|
||||
public class SectionHandler : MustSatisfyRequirementAuthorizationHandler<SectionRequirement>
|
||||
{
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
|
||||
public SectionHandler(IBackOfficeSecurityAccessor backofficeSecurityAccessor)
|
||||
{
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="SectionHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
public SectionHandler(IBackOfficeSecurityAccessor backOfficeSecurityAccessor) => _backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, SectionRequirement requirement)
|
||||
{
|
||||
var authorized = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
|
||||
&& requirement.SectionAliases.Any(app => _backofficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
|
||||
app, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
|
||||
var authorized = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null &&
|
||||
requirement.SectionAliases
|
||||
.Any(app => _backOfficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
|
||||
app, _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
|
||||
|
||||
return Task.FromResult(authorized);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -9,10 +12,14 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
public class SectionRequirement : IAuthorizationRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// The aliases for sections that the user will need access to
|
||||
/// Initializes a new instance of the <see cref="SectionRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="aliases">Aliases for sections that the user will need access to.</param>
|
||||
public SectionRequirement(params string[] aliases) => SectionAliases = aliases;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aliases for sections that the user will need access to.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> SectionAliases { get; }
|
||||
|
||||
public SectionRequirement(params string[] aliases) => SectionAliases = aliases;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Web.Services;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Ensures that the current user has access to the section for which the specified tree(s) belongs
|
||||
/// </summary>
|
||||
@@ -18,40 +20,35 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </remarks>
|
||||
public class TreeHandler : MustSatisfyRequirementAuthorizationHandler<TreeRequirement>
|
||||
{
|
||||
|
||||
private readonly ITreeService _treeService;
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor to set authorization to be based on a tree alias for which application security will be applied
|
||||
/// Initializes a new instance of the <see cref="TreeHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="treeService"></param>
|
||||
/// <param name="backofficeSecurityAccessor"></param>
|
||||
/// <param name="treeAliases">
|
||||
/// If the user has access to the application that the treeAlias is specified in, they will be authorized.
|
||||
/// Multiple trees may be specified.
|
||||
/// </param>
|
||||
public TreeHandler(ITreeService treeService, IBackOfficeSecurityAccessor backofficeSecurityAccessor)
|
||||
/// <param name="treeService">Service for section tree operations.</param>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
public TreeHandler(ITreeService treeService, IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
|
||||
{
|
||||
_treeService = treeService ?? throw new ArgumentNullException(nameof(treeService));
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backofficeSecurityAccessor));
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor ?? throw new ArgumentNullException(nameof(backOfficeSecurityAccessor));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, TreeRequirement requirement)
|
||||
{
|
||||
var apps = requirement.TreeAliases.Select(x => _treeService
|
||||
.GetByAlias(x))
|
||||
var apps = requirement.TreeAliases
|
||||
.Select(x => _treeService.GetByAlias(x))
|
||||
.WhereNotNull()
|
||||
.Select(x => x.SectionAlias)
|
||||
.Distinct()
|
||||
.ToArray();
|
||||
|
||||
var isAuth = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null
|
||||
&& apps.Any(app => _backofficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
|
||||
app, _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
|
||||
var isAuth = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser != null &&
|
||||
apps.Any(app => _backOfficeSecurityAccessor.BackOfficeSecurity.UserHasSectionAccess(
|
||||
app, _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser));
|
||||
|
||||
return Task.FromResult(isAuth);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,25 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Authorization requirements for <see cref="TreeHandler"/>
|
||||
/// </summary>
|
||||
public class TreeRequirement : IAuthorizationRequirement
|
||||
{
|
||||
/// <summary>
|
||||
/// The aliases for trees that the user will need access to
|
||||
/// Initializes a new instance of the <see cref="TreeRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="aliases">The aliases for trees that the user will need access to.</param>
|
||||
public TreeRequirement(params string[] aliases) => TreeAliases = aliases;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the aliases for trees that the user will need access to.
|
||||
/// </summary>
|
||||
public IReadOnlyCollection<string> TreeAliases { get; }
|
||||
|
||||
public TreeRequirement(params string[] aliases) => TreeAliases = aliases;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Security;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Web.BackOffice.Controllers;
|
||||
@@ -14,40 +20,51 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class UserGroupHandler : MustSatisfyRequirementAuthorizationHandler<UserGroupRequirement>
|
||||
{
|
||||
private readonly IHttpContextAccessor _httpContextAcessor;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly IUserService _userService;
|
||||
private readonly IContentService _contentService;
|
||||
private readonly IMediaService _mediaService;
|
||||
private readonly IEntityService _entityService;
|
||||
private readonly IBackOfficeSecurityAccessor _backofficeSecurityAccessor;
|
||||
private readonly IBackOfficeSecurityAccessor _backOfficeSecurityAccessor;
|
||||
|
||||
public UserGroupHandler(IHttpContextAccessor httpContextAcessor,
|
||||
IUserService userService,
|
||||
IContentService contentService,
|
||||
IMediaService mediaService,
|
||||
IEntityService entityService,
|
||||
IBackOfficeSecurityAccessor backofficeSecurityAccessor)
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserGroupHandler"/> class.
|
||||
/// </summary>
|
||||
/// <param name="httpContextAccessor">Accessor for the HTTP context of the current request.</param>
|
||||
/// <param name="userService">Service for user related operations.</param>
|
||||
/// <param name="contentService">Service for content related operations.</param>
|
||||
/// <param name="mediaService">Service for media related operations.</param>
|
||||
/// <param name="entityService">Service for entity related operations.</param>
|
||||
/// <param name="backOfficeSecurityAccessor">Accessor for back-office security.</param>
|
||||
public UserGroupHandler(
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IUserService userService,
|
||||
IContentService contentService,
|
||||
IMediaService mediaService,
|
||||
IEntityService entityService,
|
||||
IBackOfficeSecurityAccessor backOfficeSecurityAccessor)
|
||||
{
|
||||
_httpContextAcessor = httpContextAcessor;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userService = userService;
|
||||
_contentService = contentService;
|
||||
_mediaService = mediaService;
|
||||
_entityService = entityService;
|
||||
_backofficeSecurityAccessor = backofficeSecurityAccessor;
|
||||
_backOfficeSecurityAccessor = backOfficeSecurityAccessor;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<bool> IsAuthorized(AuthorizationHandlerContext context, UserGroupRequirement requirement)
|
||||
{
|
||||
var currentUser = _backofficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
|
||||
IUser currentUser = _backOfficeSecurityAccessor.BackOfficeSecurity.CurrentUser;
|
||||
|
||||
var queryString = _httpContextAcessor.HttpContext?.Request.Query;
|
||||
IQueryCollection queryString = _httpContextAccessor.HttpContext?.Request.Query;
|
||||
if (queryString == null)
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it.
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
|
||||
var ids = queryString.Where(x => x.Key == requirement.QueryStringName).ToArray();
|
||||
KeyValuePair<string, StringValues>[] ids = queryString.Where(x => x.Key == requirement.QueryStringName).ToArray();
|
||||
if (ids.Length == 0)
|
||||
{
|
||||
// Must succeed this requirement since we cannot process it.
|
||||
@@ -64,10 +81,9 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
_mediaService,
|
||||
_entityService);
|
||||
|
||||
var isAuth = authHelper.AuthorizeGroupAccess(currentUser, intIds);
|
||||
Attempt<string> isAuth = authHelper.AuthorizeGroupAccess(currentUser, intIds);
|
||||
|
||||
return Task.FromResult(isAuth.Success);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
// Copyright (c) Umbraco.
|
||||
// See LICENSE for more details.
|
||||
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
|
||||
namespace Umbraco.Web.BackOffice.Authorization
|
||||
{
|
||||
@@ -7,11 +10,15 @@ namespace Umbraco.Web.BackOffice.Authorization
|
||||
/// </summary>
|
||||
public class UserGroupRequirement : IAuthorizationRequirement
|
||||
{
|
||||
public UserGroupRequirement(string queryStringName = "id")
|
||||
{
|
||||
QueryStringName = queryStringName;
|
||||
}
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UserGroupRequirement"/> class.
|
||||
/// </summary>
|
||||
/// <param name="queryStringName">Query string name from which to authorize values.</param>
|
||||
public UserGroupRequirement(string queryStringName = "id") => QueryStringName = queryStringName;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the query string name from which to authorize values.
|
||||
/// </summary>
|
||||
public string QueryStringName { get; }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user