Renamed and added initial member role store methods, and initial unit tests
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom user store that uses Umbraco member data
|
||||
/// </summary>
|
||||
public class MemberRolesUserStore : RoleStoreBase<IdentityRole<string>, string, IdentityUserRole<string>, IdentityRoleClaim<string>>
|
||||
{
|
||||
private readonly IMemberService _memberService;
|
||||
private readonly IMemberGroupService _memberGroupService;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
|
||||
public MemberRolesUserStore(IMemberService memberService, IMemberGroupService memberGroupService, IScopeProvider scopeProvider, IdentityErrorDescriber describer)
|
||||
: base(describer)
|
||||
{
|
||||
_memberService = memberService ?? throw new ArgumentNullException(nameof(memberService));
|
||||
_memberGroupService = memberGroupService ?? throw new ArgumentNullException(nameof(memberGroupService));
|
||||
_scopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IQueryable<IdentityRole<string>> Roles { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> CreateAsync(IdentityRole<string> role, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> UpdateAsync(IdentityRole<string> role, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> DeleteAsync(IdentityRole<string> role, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityRole<string>> FindByIdAsync(string id, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityRole<string>> FindByNameAsync(string normalizedName, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IList<Claim>> GetClaimsAsync(IdentityRole<string> role, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task AddClaimAsync(IdentityRole<string> role, Claim claim, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task RemoveClaimAsync(IdentityRole<string> role, Claim claim, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
193
src/Umbraco.Infrastructure/Security/MembersRoleStore.cs
Normal file
193
src/Umbraco.Infrastructure/Security/MembersRoleStore.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Core.Security
|
||||
{
|
||||
/// <summary>
|
||||
/// A custom user store that uses Umbraco member data
|
||||
/// </summary>
|
||||
public class MembersRoleStore : RoleStoreBase<IdentityRole<string>, string, IdentityUserRole<string>, IdentityRoleClaim<string>>
|
||||
{
|
||||
private readonly IMemberService _memberService;
|
||||
private readonly IMemberGroupService _memberGroupService;
|
||||
private readonly IScopeProvider _scopeProvider;
|
||||
|
||||
public MembersRoleStore(IMemberService memberService, IMemberGroupService memberGroupService, IScopeProvider scopeProvider, IdentityErrorDescriber describer)
|
||||
: base(describer)
|
||||
{
|
||||
_memberService = memberService ?? throw new ArgumentNullException(nameof(memberService));
|
||||
_memberGroupService = memberGroupService ?? throw new ArgumentNullException(nameof(memberGroupService));
|
||||
_scopeProvider = scopeProvider ?? throw new ArgumentNullException(nameof(scopeProvider));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override IQueryable<IdentityRole<string>> Roles
|
||||
{
|
||||
get
|
||||
{
|
||||
IEnumerable<IMemberGroup> memberGroups = _memberGroupService.GetAll();
|
||||
var identityRoles = new List<IdentityRole<string>>();
|
||||
foreach (IMemberGroup group in memberGroups)
|
||||
{
|
||||
IdentityRole<string> identityRole = MapFromMemberGroup(group);
|
||||
identityRoles.Add(identityRole);
|
||||
}
|
||||
|
||||
return identityRoles.AsQueryable();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> CreateAsync(
|
||||
IdentityRole<string> role,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
|
||||
var memberGroup = new MemberGroup
|
||||
{
|
||||
Name = role.Name
|
||||
};
|
||||
|
||||
_memberGroupService.Save(memberGroup);
|
||||
|
||||
role.Id = memberGroup.Id.ToString();
|
||||
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> UpdateAsync(IdentityRole<string> role,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
|
||||
if (!int.TryParse(role.Id, out int roleId))
|
||||
{
|
||||
return new Task<IdentityResult>(() => IdentityResult.Failed());
|
||||
}
|
||||
|
||||
IMemberGroup memberGroup = _memberGroupService.GetById(roleId);
|
||||
if (memberGroup != null)
|
||||
{
|
||||
if (MapToMemberGroup(role, memberGroup))
|
||||
{
|
||||
_memberGroupService.Save(memberGroup);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityResult> DeleteAsync(IdentityRole<string> role,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (role == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(role));
|
||||
}
|
||||
|
||||
if (!int.TryParse(role.Id, out int roleId))
|
||||
{
|
||||
return new Task<IdentityResult>(() => IdentityResult.Failed());
|
||||
}
|
||||
|
||||
IMemberGroup memberGroup = _memberGroupService.GetById(roleId);
|
||||
if (memberGroup != null)
|
||||
{
|
||||
_memberGroupService.Delete(memberGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: throw exception when not found, or return failure?
|
||||
return Task.FromResult(IdentityResult.Failed());
|
||||
}
|
||||
|
||||
return Task.FromResult(IdentityResult.Success);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityRole<string>> FindByIdAsync(string id,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
if (!int.TryParse(id, out int roleId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
IMemberGroup memberGroup = _memberGroupService.GetById(roleId);
|
||||
|
||||
return Task.FromResult(memberGroup == null ? null : MapFromMemberGroup(memberGroup));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IdentityRole<string>> FindByNameAsync(string normalizedName,
|
||||
CancellationToken cancellationToken = new CancellationToken())
|
||||
{
|
||||
IMemberGroup memberGroup = _memberGroupService.GetByName(normalizedName);
|
||||
|
||||
return Task.FromResult(memberGroup == null ? null : MapFromMemberGroup(memberGroup));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task<IList<Claim>> GetClaimsAsync(IdentityRole<string> role, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task AddClaimAsync(IdentityRole<string> role, Claim claim, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task RemoveClaimAsync(IdentityRole<string> role, Claim claim, CancellationToken cancellationToken = new CancellationToken()) => throw new System.NotImplementedException();
|
||||
|
||||
/// <summary>
|
||||
/// Maps a member group to an identity role
|
||||
/// </summary>
|
||||
/// <param name="memberGroup"></param>
|
||||
/// <returns></returns>
|
||||
private IdentityRole<string> MapFromMemberGroup(IMemberGroup memberGroup)
|
||||
{
|
||||
var result = new IdentityRole
|
||||
{
|
||||
Id = memberGroup.Id.ToString(),
|
||||
Name = memberGroup.Name
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Map an identity role to a member group
|
||||
/// </summary>
|
||||
/// <param name="role"></param>
|
||||
/// <param name="memberGroup"></param>
|
||||
/// <returns></returns>
|
||||
private bool MapToMemberGroup(IdentityRole<string> role, IMemberGroup memberGroup)
|
||||
{
|
||||
var anythingChanged = false;
|
||||
|
||||
if (!string.IsNullOrEmpty(role.Name) && memberGroup.Name != role.Name)
|
||||
{
|
||||
memberGroup.Name = role.Name;
|
||||
anythingChanged = true;
|
||||
}
|
||||
|
||||
return anythingChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -74,8 +74,5 @@ namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
|
||||
Assert.IsTrue(identityResult.Succeeded);
|
||||
Assert.IsTrue(!identityResult.Errors.Any());
|
||||
}
|
||||
|
||||
//GetPasswordHashAsync
|
||||
//GetUserIdAsync
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Umbraco.Cms.Core.Models;
|
||||
using Umbraco.Cms.Core.Scoping;
|
||||
using Umbraco.Cms.Core.Security;
|
||||
using Umbraco.Cms.Core.Services;
|
||||
|
||||
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Infrastructure.Security
|
||||
{
|
||||
[TestFixture]
|
||||
public class MemberRoleStoreTests
|
||||
{
|
||||
private Mock<IMemberService> _mockMemberService;
|
||||
private Mock<IMemberGroupService> _mockMemberGroupService;
|
||||
|
||||
public MembersRoleStore CreateSut()
|
||||
{
|
||||
_mockMemberService = new Mock<IMemberService>();
|
||||
_mockMemberGroupService = new Mock<IMemberGroupService>();
|
||||
return new MembersRoleStore(
|
||||
_mockMemberService.Object,
|
||||
_mockMemberGroupService.Object,
|
||||
new Mock<IScopeProvider>().Object,
|
||||
new IdentityErrorDescriber());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GivenICreateAMemberRole_AndTheGroupIsNull_ThenIShouldGetAFailedResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
CancellationToken fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
// act
|
||||
Action actual = () => sut.CreateAsync(null, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.That(actual, Throws.ArgumentNullException);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task GivenICreateAMemberRole_AndTheGroupIsPopulatedCorrectly_ThenIShouldGetASuccessResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
var fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
bool raiseEvents = false;
|
||||
|
||||
_mockMemberGroupService.Setup(x => x.Save(mockMemberGroup, raiseEvents));
|
||||
|
||||
// act
|
||||
IdentityResult identityResult = await sut.CreateAsync(fakeRole, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(identityResult.Succeeded);
|
||||
Assert.IsTrue(!identityResult.Errors.Any());
|
||||
_mockMemberGroupService.Verify(x => x.Save(It.IsAny<MemberGroup>(), It.IsAny<bool>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GivenIUpdateAMemberRole_AndTheGroupExists_ThenIShouldGetASuccessResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
var fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
bool raiseEvents = false;
|
||||
|
||||
_mockMemberGroupService.Setup(x => x.GetById(777)).Returns(mockMemberGroup);
|
||||
_mockMemberGroupService.Setup(x => x.Save(mockMemberGroup, raiseEvents));
|
||||
|
||||
// act
|
||||
IdentityResult identityResult = await sut.UpdateAsync(fakeRole, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(identityResult.Succeeded);
|
||||
Assert.IsTrue(!identityResult.Errors.Any());
|
||||
_mockMemberGroupService.Verify(x => x.Save(mockMemberGroup, false));
|
||||
_mockMemberGroupService.Verify(x => x.GetById(777));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GivenIUpdateAMemberRole_AndTheGroupDoesntExist_ThenIShouldGetAFailureResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
var fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
bool raiseEvents = false;
|
||||
|
||||
|
||||
// act
|
||||
IdentityResult identityResult = await sut.UpdateAsync(fakeRole, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(identityResult.Succeeded == false);
|
||||
Assert.IsTrue(identityResult.Errors.Any());
|
||||
_mockMemberGroupService.Verify(x => x.GetById(777));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GivenIDeleteAMemberRole_AndItExists_ThenTheMemberGroupShouldBeDeleted_AndIShouldGetASuccessResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
var fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
_mockMemberGroupService.Setup(x => x.GetById(777)).Returns(mockMemberGroup);
|
||||
|
||||
// act
|
||||
IdentityResult identityResult = await sut.DeleteAsync(fakeRole, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(identityResult.Succeeded);
|
||||
Assert.IsTrue(!identityResult.Errors.Any());
|
||||
_mockMemberGroupService.Verify(x => x.GetById(777));
|
||||
_mockMemberGroupService.Verify(x => x.Delete(mockMemberGroup));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GivenIDeleteAMemberRole_AndItDoesntExist_ThenTheMemberGroupShouldBeDeleted_AndIShouldGetASuccessResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
var fakeCancellationToken = new CancellationToken() { };
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
|
||||
// act
|
||||
IdentityResult identityResult = await sut.DeleteAsync(fakeRole, fakeCancellationToken);
|
||||
|
||||
// assert
|
||||
Assert.IsTrue(identityResult.Succeeded == false);
|
||||
Assert.IsTrue(identityResult.Errors.Any());
|
||||
_mockMemberGroupService.Verify(x => x.GetById(777));
|
||||
_mockMemberGroupService.Verify(x => x.Delete(mockMemberGroup));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GivenIGetAllMemberRoles_ThenIShouldGetAllMemberGroups_AndASuccessResultAsync()
|
||||
{
|
||||
// arrange
|
||||
MembersRoleStore sut = CreateSut();
|
||||
var fakeRole = new IdentityRole<string>()
|
||||
{
|
||||
Id = "777",
|
||||
Name = "testname"
|
||||
};
|
||||
IEnumerable<IdentityRole<string>> expected = new List<IdentityRole<string>>()
|
||||
{
|
||||
new IdentityRole("fakeGroupName")
|
||||
{
|
||||
Id = "77"
|
||||
}
|
||||
};
|
||||
|
||||
IMemberGroup mockMemberGroup = Mock.Of<IMemberGroup>(m =>
|
||||
m.Name == "fakeGroupName" && m.CreatorId == 77);
|
||||
|
||||
IEnumerable<IMemberGroup> fakeMemberGroups = new List<IMemberGroup>()
|
||||
{
|
||||
mockMemberGroup
|
||||
};
|
||||
|
||||
_mockMemberGroupService.Setup(x => x.GetAll()).Returns(fakeMemberGroups);
|
||||
|
||||
// act
|
||||
IQueryable<IdentityRole<string>> actual = sut.Roles;
|
||||
|
||||
// assert
|
||||
Assert.AreEqual(expected.AsQueryable(), actual);
|
||||
_mockMemberGroupService.Verify(x => x.GetAll());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user