- @if (Model.Projects.IsNullOrEmpty())
+ @if (Model.Projects == null || !Model.Projects.Any())
{
@L["NoProjectWarning"]
}
- @if (Model.Projects.Count > 0)
+ else
{
@L["Projects"]
diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj
index 56ff4979d2..390476a38f 100644
--- a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj
+++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo.Docs.Admin.Application.Tests.csproj
@@ -11,7 +11,6 @@
-
diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs
similarity index 57%
rename from modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs
rename to modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs
index 9f2dfa06b8..c11233849a 100644
--- a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs
+++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestBase.cs
@@ -4,9 +4,4 @@
{
}
-
- public class DocsApplicationTestBase : DocsTestBase
- {
-
- }
}
diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs
similarity index 60%
rename from modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs
rename to modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs
index 32c49787b3..e85bac8ce3 100644
--- a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsApplicationTestModule.cs
+++ b/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/DocsAdminApplicationTestModule.cs
@@ -3,15 +3,6 @@ using Volo.Docs.Admin;
namespace Volo.Docs
{
- [DependsOn(
- typeof(DocsApplicationModule),
- typeof(DocsDomainTestModule)
- )]
- public class DocsApplicationTestModule : AbpModule
- {
-
- }
-
[DependsOn(
typeof(DocsAdminApplicationModule),
typeof(DocsDomainTestModule)
diff --git a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ApplicationService_Tests.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs
similarity index 81%
rename from modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ApplicationService_Tests.cs
rename to modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs
index 02bcc4e0db..bff7f09e1f 100644
--- a/modules/docs/test/Volo.Docs.Admin.Application.Tests/Volo/Docs/ApplicationService_Tests.cs
+++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/ApplicationService_Tests.cs
@@ -36,7 +36,10 @@ namespace Volo.Docs
[Fact]
public async Task GetVersionsAsync()
{
- // TODO: Need to mock WebClient and Octokit components
+ var versions = await _projectAppService.GetVersionsAsync("ABP");
+ versions.ShouldNotBeNull();
+ versions.Items.Count.ShouldBe(1);
+ versions.Items.ShouldContain(x => x.Name == "0.15.0" && x.DisplayName == "0.15.0");
}
}
}
diff --git a/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs
new file mode 100644
index 0000000000..f0fb94d40b
--- /dev/null
+++ b/modules/docs/test/Volo.Docs.Application.Tests/Volo/Docs/DocsApplicationTestBase.cs
@@ -0,0 +1,7 @@
+namespace Volo.Docs
+{
+ public class DocsApplicationTestBase : DocsTestBase
+ {
+
+ }
+}
diff --git a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs
index 7de6bb3182..b46e054370 100644
--- a/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs
+++ b/modules/docs/test/Volo.Docs.Domain.Tests/Volo/Docs/DocsDomainTestBase.cs
@@ -1,43 +1,7 @@
-using System;
-using System.Collections.Generic;
-using Microsoft.Extensions.DependencyInjection;
-using NSubstitute;
-using Octokit;
-using Volo.Docs.GitHub.Documents;
-
-namespace Volo.Docs
+namespace Volo.Docs
{
public abstract class DocsDomainTestBase : DocsTestBase
{
- protected override void AfterAddApplication(IServiceCollection services)
- {
- var repositoryManager = Substitute.For();
- repositoryManager.GetFileRawStringContentAsync(Arg.Any(), Arg.Any(), Arg.Any())
- .Returns("stringContent");
- repositoryManager.GetFileRawByteArrayContentAsync(Arg.Any(), Arg.Any(), Arg.Any())
- .Returns(new byte[] { 0x01, 0x02, 0x03 });
- repositoryManager.GetReleasesAsync(Arg.Any(), Arg.Any(), Arg.Any())
- .Returns(new List
- {
- new Release("https://api.github.com/repos/abpframework/abp/releases/16293679",
- "https://github.com/abpframework/abp/releases/tag/0.15.0",
- "https://api.github.com/repos/abpframework/abp/releases/16293679/assets",
- "https://uploads.github.com/repos/abpframework/abp/releases/16293679/assets{?name,label}",
- 16293679,
- "0.15.0",
- "master",
- "0.15.0",
- "0.15.0 already release",
- false,
- false,
- DateTimeOffset.Parse("2019-03-22T18:43:58Z"),
- DateTimeOffset.Parse("2019-03-22T19:44:25Z"),
- null,
- "https://api.github.com/repos/abpframework/abp/tarball/0.15.0",
- "https://api.github.com/repos/abpframework/abp/zipball/0.15.0",
- null)
- });
- services.AddSingleton(repositoryManager);
- }
+
}
}
diff --git a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs
index 2ceb4b8f95..e8b7fa0126 100644
--- a/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs
+++ b/modules/docs/test/Volo.Docs.TestBase/Volo/Docs/DocsTestBase.cs
@@ -1,5 +1,11 @@
-using Volo.Abp;
+using System;
+using System.Collections.Generic;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+using Octokit;
+using Volo.Abp;
using Volo.Abp.Modularity;
+using Volo.Docs.GitHub.Documents;
namespace Volo.Docs
{
@@ -10,5 +16,36 @@ namespace Volo.Docs
{
options.UseAutofac();
}
+
+ protected override void AfterAddApplication(IServiceCollection services)
+ {
+ var repositoryManager = Substitute.For();
+ repositoryManager.GetFileRawStringContentAsync(Arg.Any(), Arg.Any(), Arg.Any())
+ .Returns("stringContent");
+ repositoryManager.GetFileRawByteArrayContentAsync(Arg.Any(), Arg.Any(), Arg.Any())
+ .Returns(new byte[] { 0x01, 0x02, 0x03 });
+ repositoryManager.GetReleasesAsync(Arg.Any(), Arg.Any(), Arg.Any())
+ .Returns(new List
+ {
+ new Release("https://api.github.com/repos/abpframework/abp/releases/16293679",
+ "https://github.com/abpframework/abp/releases/tag/0.15.0",
+ "https://api.github.com/repos/abpframework/abp/releases/16293679/assets",
+ "https://uploads.github.com/repos/abpframework/abp/releases/16293679/assets{?name,label}",
+ 16293679,
+ "0.15.0",
+ "master",
+ "0.15.0",
+ "0.15.0 already release",
+ false,
+ false,
+ DateTimeOffset.Parse("2019-03-22T18:43:58Z"),
+ DateTimeOffset.Parse("2019-03-22T19:44:25Z"),
+ null,
+ "https://api.github.com/repos/abpframework/abp/tarball/0.15.0",
+ "https://api.github.com/repos/abpframework/abp/zipball/0.15.0",
+ null)
+ });
+ services.AddSingleton(repositoryManager);
+ }
}
}
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json
new file mode 100644
index 0000000000..25137f1ee3
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/Localization/ApplicationContracts/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+
+ }
+}
\ No newline at end of file
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json
new file mode 100644
index 0000000000..3f906a3cdc
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/tr.json
@@ -0,0 +1,6 @@
+{
+ "culture": "tr",
+ "texts": {
+
+ }
+}
\ No newline at end of file
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json
new file mode 100644
index 0000000000..25137f1ee3
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Domain/Volo/Abp/FeatureManagement/Localization/Domain/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+
+ }
+}
\ No newline at end of file
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json
new file mode 100644
index 0000000000..3f906a3cdc
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/tr.json
@@ -0,0 +1,6 @@
+{
+ "culture": "tr",
+ "texts": {
+
+ }
+}
\ No newline at end of file
diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json
new file mode 100644
index 0000000000..25137f1ee3
--- /dev/null
+++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Web/Localization/Resources/FeatureManagement/zh-Hans.json
@@ -0,0 +1,6 @@
+{
+ "culture": "zh-Hans",
+ "texts": {
+
+ }
+}
\ No newline at end of file
diff --git a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs
index e9646d38cf..bac63a0c11 100644
--- a/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs
+++ b/modules/identity/src/Volo.Abp.Identity.Domain/Volo/Abp/Identity/IdentityUserStore.cs
@@ -981,7 +981,7 @@ namespace Volo.Abp.Identity
/// The value of the token.
/// The used to propagate notifications that the operation should be canceled.
/// The that represents the asynchronous operation.
- public virtual async Task SetTokenAsync([NotNull] IdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken)
+ public virtual async Task SetTokenAsync([NotNull] IdentityUser user, string loginProvider, string name, string value, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1000,7 +1000,7 @@ namespace Volo.Abp.Identity
/// The name of the token.
/// The used to propagate notifications that the operation should be canceled.
/// The that represents the asynchronous operation.
- public async Task RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken)
+ public async Task RemoveTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1019,7 +1019,7 @@ namespace Volo.Abp.Identity
/// The name of the token.
/// The used to propagate notifications that the operation should be canceled.
/// The that represents the asynchronous operation.
- public async Task GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken)
+ public async Task GetTokenAsync(IdentityUser user, string loginProvider, string name, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1030,12 +1030,12 @@ namespace Volo.Abp.Identity
return user.FindToken(loginProvider, name)?.Value;
}
- public Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken)
+ public Task SetAuthenticatorKeyAsync(IdentityUser user, string key, CancellationToken cancellationToken = default)
{
return SetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, key, cancellationToken);
}
- public Task GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken)
+ public Task GetAuthenticatorKeyAsync(IdentityUser user, CancellationToken cancellationToken = default)
{
return GetTokenAsync(user, InternalLoginProvider, AuthenticatorKeyTokenName, cancellationToken);
}
@@ -1046,7 +1046,7 @@ namespace Volo.Abp.Identity
/// The user who owns the recovery code.
/// The used to propagate notifications that the operation should be canceled.
/// The number of valid recovery codes for the user..
- public virtual async Task CountCodesAsync(IdentityUser user, CancellationToken cancellationToken)
+ public virtual async Task CountCodesAsync(IdentityUser user, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -1068,7 +1068,7 @@ namespace Volo.Abp.Identity
/// The new recovery codes for the user.
/// The used to propagate notifications that the operation should be canceled.
/// The new recovery codes for the user.
- public virtual Task ReplaceCodesAsync(IdentityUser user, IEnumerable recoveryCodes, CancellationToken cancellationToken)
+ public virtual Task ReplaceCodesAsync(IdentityUser user, IEnumerable recoveryCodes, CancellationToken cancellationToken = default)
{
var mergedCodes = string.Join(";", recoveryCodes);
return SetTokenAsync(user, InternalLoginProvider, RecoveryCodeTokenName, mergedCodes, cancellationToken);
@@ -1082,7 +1082,7 @@ namespace Volo.Abp.Identity
/// The recovery code to use.
/// The used to propagate notifications that the operation should be canceled.
/// True if the recovery code was found for the user.
- public virtual async Task RedeemCodeAsync(IdentityUser user, string code, CancellationToken cancellationToken)
+ public virtual async Task RedeemCodeAsync(IdentityUser user, string code, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
diff --git a/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs
new file mode 100644
index 0000000000..7358238294
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Application.Tests/Volo/Abp/Identity/IdentityUserLookupAppService_Tests.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdentityUserLookupAppService_Tests : AbpIdentityApplicationTestBase
+ {
+ private readonly IIdentityUserLookupAppService _identityUserLookupAppService;
+ private readonly IIdentityUserRepository _identityUserRepository;
+ private readonly ILookupNormalizer _lookupNormalizer;
+
+ public IdentityUserLookupAppService_Tests()
+ {
+ _identityUserLookupAppService = GetRequiredService();
+ _identityUserRepository = GetRequiredService();
+ _lookupNormalizer = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task FindByIdAsync()
+ {
+ var user = await _identityUserRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserLookupAppService.FindByIdAsync(user.Id)).UserName.ShouldBe(user.UserName);
+ }
+
+ [Fact]
+ public async Task FindById_NotExist_Should_Return_Null()
+ {
+ var user = await _identityUserLookupAppService.FindByIdAsync(Guid.NewGuid());
+ user.ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task FindByUserNameAsync()
+ {
+ var user = await _identityUserRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserLookupAppService.FindByUserNameAsync(user.UserName)).UserName.ShouldBe(user.UserName);
+ }
+
+ [Fact]
+ public async Task FindByUserName_NotExist_Should_Return_Null()
+ {
+ var user = await _identityUserLookupAppService.FindByUserNameAsync(Guid.NewGuid().ToString());
+ user.ShouldBeNull();
+ }
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs
new file mode 100644
index 0000000000..c27967e704
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdenityClaimTypeManager_Tests.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdenityClaimTypeManager_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IIdentityClaimTypeRepository _identityClaimTypeRepository;
+ private readonly IdenityClaimTypeManager _claimTypeManager;
+ private readonly IdentityTestData _testData;
+
+ public IdenityClaimTypeManager_Tests()
+ {
+ _identityClaimTypeRepository = GetRequiredService();
+ _claimTypeManager = GetRequiredService();
+ _testData = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task CreateAsync()
+ {
+ var claimType = await _claimTypeManager.CreateAsync(new IdentityClaimType(Guid.NewGuid(), "Phone", false,
+ false, null,
+ null, null, IdentityClaimValueType.String));
+
+ claimType.ShouldNotBeNull();
+ claimType.Name.ShouldBe("Phone");
+ }
+
+ [Fact]
+ public async Task Create_Name_Exist_Should_Exception()
+ {
+ await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.CreateAsync(
+ new IdentityClaimType(
+ Guid.NewGuid(), "Age")));
+ }
+
+ [Fact]
+ public async Task UpdateAsync()
+ {
+ var ageClaim = _identityClaimTypeRepository.Find(_testData.AgeClaimId);
+ ageClaim.ShouldNotBeNull();
+ ageClaim.Description = "this is age";
+
+ var updatedAgeClaimType = await _claimTypeManager.UpdateAsync(ageClaim);
+ updatedAgeClaimType.ShouldNotBeNull();
+ updatedAgeClaimType.Description.ShouldBe("this is age");
+ }
+
+
+ [Fact]
+ public async Task Update_Name_Exist_Should_Exception()
+ {
+ await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync(
+ new IdentityClaimType(
+ Guid.NewGuid(), "Age")));
+ }
+
+
+ [Fact]
+ public async Task Static_IdentityClaimType_Cant_Not_Update()
+ {
+ var phoneClaim = new IdentityClaimType(Guid.NewGuid(), "Phone", true, true);
+ _identityClaimTypeRepository.Insert(phoneClaim);
+
+ await Assert.ThrowsAnyAsync(async () => await _claimTypeManager.UpdateAsync(phoneClaim));
+ }
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs
new file mode 100644
index 0000000000..9cdafa10bb
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleManager_Tests.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Shouldly;
+using Volo.Abp.Uow;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdentityRoleManager_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IdentityRoleManager _identityRoleManager;
+ private readonly IIdentityRoleRepository _identityRoleRepository;
+ private readonly ILookupNormalizer _lookupNormalizer;
+ private readonly IdentityTestData _testData;
+
+ public IdentityRoleManager_Tests()
+ {
+ _identityRoleManager = GetRequiredService();
+ _identityRoleRepository = GetRequiredService();
+ _lookupNormalizer = GetRequiredService();
+ _testData = GetRequiredService();
+ }
+
+
+ [Fact]
+ public async Task GetByIdAsync()
+ {
+ var role = await _identityRoleManager.FindByIdAsync(_testData.RoleModeratorId.ToString());
+
+ role.ShouldNotBeNull();
+ role.Name.ShouldBe("moderator");
+ }
+
+ [Fact]
+ public async Task SetRoleNameAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ (await _identityRoleManager.SetRoleNameAsync(role, "teacher")).Succeeded.ShouldBeTrue();
+
+ role.Name.ShouldBe("teacher");
+ }
+
+ [Fact]
+ public async Task DeleteAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleManager.DeleteAsync(role);
+
+ (await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"))).ShouldBeNull();
+ }
+
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs
new file mode 100644
index 0000000000..d2f674411b
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityRoleStore_Tests.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Shouldly;
+using Volo.Abp.Uow;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdentityRoleStore_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IdentityRoleStore _identityRoleStore;
+ private readonly ILookupNormalizer _lookupNormalizer;
+ private readonly IIdentityRoleRepository _identityRoleRepository;
+ private readonly IdentityTestData _testData;
+ private readonly IUnitOfWorkManager _unitOfWorkManager;
+
+ public IdentityRoleStore_Tests()
+ {
+ _identityRoleStore = GetRequiredService();
+ _lookupNormalizer = GetRequiredService();
+ _identityRoleRepository = GetRequiredService();
+ _testData = GetRequiredService();
+ _unitOfWorkManager = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task CreateAsync()
+ {
+ var roleId = Guid.NewGuid();
+ var role = new IdentityRole(roleId, "teacher");
+ (await _identityRoleStore.CreateAsync(role)).Succeeded.ShouldBeTrue();
+
+ var teacher = await _identityRoleStore.FindByIdAsync(roleId.ToString());
+
+ teacher.ShouldNotBeNull();
+ teacher.Name.ShouldBe("teacher");
+ }
+
+ [Fact]
+ public async Task UpdateAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ role.IsDefault = true;
+ await _identityRoleStore.UpdateAsync(role);
+
+ role.IsDefault.ShouldBeTrue();
+ }
+
+
+ [Fact]
+ public async Task DeleteAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleStore.DeleteAsync(role);
+
+ (await _identityRoleStore.FindByIdAsync(_testData.RoleModeratorId.ToString())).ShouldBeNull();
+ }
+
+ [Fact]
+ public async Task GetRoleIdAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ (await _identityRoleStore.GetRoleIdAsync(role)).ShouldBe(_testData.RoleModeratorId.ToString());
+ }
+
+ [Fact]
+ public async Task GetRoleNameAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ (await _identityRoleStore.GetRoleNameAsync(role)).ShouldBe(role.Name);
+ }
+
+
+ [Fact]
+ public async Task SetRoleNameAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleStore.SetRoleNameAsync(role, "teacher");
+
+ role.Name.ShouldBe("teacher");
+ }
+
+ [Fact]
+ public async Task FindByIdAsync()
+ {
+ var role = await _identityRoleStore.FindByIdAsync(_testData.RoleModeratorId.ToString());
+
+ role.ShouldNotBeNull();
+ role.Name.ShouldBe("moderator");
+ }
+
+ [Fact]
+ public async Task FindByNameAsync()
+ {
+ var role = await _identityRoleStore.FindByNameAsync(_lookupNormalizer.Normalize("moderator"));
+
+ role.ShouldNotBeNull();
+ role.Name.ShouldBe("moderator");
+ }
+
+ [Fact]
+ public async Task GetNormalizedRoleNameAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ (await _identityRoleStore.GetNormalizedRoleNameAsync(role)).ShouldBe(role.NormalizedName);
+ }
+
+ [Fact]
+ public async Task SetNormalizedRoleNameAsync()
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleStore.SetNormalizedRoleNameAsync(role, _lookupNormalizer.Normalize("teacher"));
+
+ role.NormalizedName.ShouldBe(_lookupNormalizer.Normalize("teacher"));
+ }
+
+ [Fact]
+ public async Task GetClaimsAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ var claims = await _identityRoleStore.GetClaimsAsync(role);
+
+ claims.ShouldNotBeEmpty();
+ claims.ShouldContain(x => x.Type == "test-claim" && x.Value == "test-value");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task AddClaimAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleStore.AddClaimAsync(role, new Claim("my-claim", "my-value"));
+
+ role.Claims.ShouldContain(x => x.ClaimType == "my-claim" && x.ClaimValue == "my-value");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task RemoveClaimAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var role = await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("moderator"));
+ role.ShouldNotBeNull();
+
+ await _identityRoleStore.RemoveClaimAsync(role, new Claim("test-claim", "test-value"));
+
+ role.Claims.ShouldNotContain(x => x.ClaimType == "test-claim" && x.ClaimValue == "test-value");
+
+ await uow.CompleteAsync();
+ }
+ }
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs
new file mode 100644
index 0000000000..3755342375
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserManager_Tests.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Shouldly;
+using Volo.Abp.Uow;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdentityUserManager_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IdentityUserManager _identityUserManager;
+ private readonly IIdentityUserRepository _identityUserRepository;
+ private readonly IIdentityRoleRepository _identityRoleRepository;
+ private readonly ILookupNormalizer _lookupNormalizer;
+ private readonly IUnitOfWorkManager _unitOfWorkManager;
+ private readonly IdentityTestData _testData;
+
+ public IdentityUserManager_Tests()
+ {
+ _identityUserManager = GetRequiredService();
+ _identityUserRepository = GetRequiredService();
+ _identityRoleRepository = GetRequiredService();
+ _lookupNormalizer = GetRequiredService();
+ _testData = GetRequiredService();
+ _unitOfWorkManager = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetByIdAsync()
+ {
+ var user = await _identityUserManager.GetByIdAsync(_testData.UserJohnId);
+
+ user.ShouldNotBeNull();
+ user.UserName.ShouldBe("john.nash");
+ }
+
+ [Fact]
+ public async Task SetRolesAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _identityUserRepository.FindByNormalizedUserNameAsync(
+ _lookupNormalizer.Normalize("david"));
+ user.ShouldNotBeNull();
+
+ var identityResult = await _identityUserManager.SetRolesAsync(user, new List()
+ {
+ "moderator",
+ });
+
+ identityResult.Succeeded.ShouldBeTrue();
+ user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId);
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task SetRoles_Should_Remove_Other_Roles()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var roleSupporter =
+ await _identityRoleRepository.FindByNormalizedNameAsync(_lookupNormalizer.Normalize("supporter"));
+ roleSupporter.ShouldNotBeNull();
+
+ var user = await _identityUserRepository.FindByNormalizedUserNameAsync(
+ _lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ var identityResult = await _identityUserManager.SetRolesAsync(user, new List()
+ {
+ "admin",
+ });
+
+ identityResult.Succeeded.ShouldBeTrue();
+ user.Roles.ShouldNotContain(x => x.RoleId == _testData.RoleModeratorId);
+ user.Roles.ShouldNotContain(x => x.RoleId == roleSupporter.Id);
+
+ await uow.CompleteAsync();
+ }
+ }
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs
new file mode 100644
index 0000000000..0e4c1e8bc6
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/IdentityUserStore_Tests.cs
@@ -0,0 +1,777 @@
+using System;
+using System.Collections.Generic;
+using System.Security.Claims;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Identity;
+using Shouldly;
+using Volo.Abp.Guids;
+using Volo.Abp.Uow;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class IdentityUserStore_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IdentityUserStore _identityUserStore;
+ private readonly ILookupNormalizer _lookupNormalizer;
+ private readonly IIdentityUserRepository _userRepository;
+ private readonly IdentityTestData _testData;
+ private readonly IUnitOfWorkManager _unitOfWorkManager;
+
+ public IdentityUserStore_Tests()
+ {
+ _identityUserStore = GetRequiredService();
+ _lookupNormalizer = GetRequiredService();
+ _userRepository = GetRequiredService();
+ _testData = GetRequiredService();
+ _unitOfWorkManager = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetUserIdAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetUserIdAsync(user)).ShouldBe(user.Id.ToString());
+ }
+
+
+ [Fact]
+ public async Task GetUserNameAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetUserNameAsync(user)).ShouldBe(user.UserName);
+ }
+
+ [Fact]
+ public async Task SetUserNameAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetUserNameAsync(user, "bob.lee");
+ user.UserName.ShouldBe("bob.lee");
+ //user.NormalizedUserName.ShouldBe(_lookupNormalizer.Normalize("bob.lee"));
+ }
+
+
+ [Fact]
+ public async Task GetNormalizedUserNameAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetNormalizedUserNameAsync(user)).ShouldBe(user.NormalizedUserName);
+ }
+
+ [Fact]
+ public async Task SetNormalizedUserNameAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetNormalizedUserNameAsync(user, _lookupNormalizer.Normalize("bob.lee"));
+
+ user.NormalizedUserName.ShouldBe(_lookupNormalizer.Normalize("bob.lee"));
+ }
+
+ [Fact]
+ public async Task CreateAsync()
+ {
+ var userId = Guid.NewGuid();
+ var user = new IdentityUser(userId, "bob.lee", "bob.lee@abp.io");
+
+ await _identityUserStore.CreateAsync(user);
+
+ var bobLee = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("bob.lee"));
+ bobLee.ShouldNotBeNull();
+ bobLee.UserName.ShouldBe("bob.lee");
+ bobLee.Email.ShouldBe("bob.lee@abp.io");
+ }
+
+ [Fact]
+ public async Task UpdateAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ user.Name = "lee";
+ (await _identityUserStore.UpdateAsync(user)).Succeeded.ShouldBeTrue();
+
+ (await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"))).Name
+ .ShouldBe("lee");
+ }
+
+ [Fact]
+ public async Task Update_Concurrency()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.UpdateAsync(user)).Succeeded.ShouldBeTrue();
+
+ user.ConcurrencyStamp = Guid.NewGuid().ToString();
+ var identityResult = await _identityUserStore.UpdateAsync(user);
+
+ identityResult.Succeeded.ShouldBeFalse();
+ identityResult.Errors.ShouldContain(x =>
+ x.Code == nameof(IdentityErrorDescriber.ConcurrencyFailure));
+
+ // && x.Description == Resources.PasswordMismatch);
+ }
+
+
+ [Fact]
+ public async Task DeleteAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.DeleteAsync(user)).Succeeded.ShouldBeTrue();
+
+ (await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"))).ShouldBeNull();
+ }
+
+
+ [Fact]
+ public async Task FindByIdAsync()
+ {
+ var user = await _identityUserStore.FindByIdAsync(_testData.UserJohnId.ToString());
+
+ user.ShouldNotBeNull();
+ user.UserName.ShouldBe("john.nash");
+ }
+
+
+ [Fact]
+ public async Task FindByNameAsync()
+ {
+ var user = await _identityUserStore.FindByNameAsync(_lookupNormalizer.Normalize("john.nash"));
+
+ user.ShouldNotBeNull();
+ user.UserName.ShouldBe("john.nash");
+ }
+
+
+ [Fact]
+ public async Task SetPasswordHashAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ user.PasswordHash.ShouldBeNull();
+
+ await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd");
+ user.PasswordHash.ShouldBe("P@ssw0rd");
+ }
+
+
+ [Fact]
+ public async Task GetPasswordHashAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd");
+
+ (await _identityUserStore.GetPasswordHashAsync(user)).ShouldBe("P@ssw0rd");
+ }
+
+
+ [Fact]
+ public async Task HasPasswordAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ (await _identityUserStore.HasPasswordAsync(user)).ShouldBeFalse();
+
+ await _identityUserStore.SetPasswordHashAsync(user, "P@ssw0rd");
+ (await _identityUserStore.HasPasswordAsync(user)).ShouldBeTrue();
+ }
+
+
+ [Fact]
+ public async Task AddToRoleAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("david"));
+ user.ShouldNotBeNull();
+ user.Roles.ShouldBeEmpty();
+
+ await _identityUserStore.AddToRoleAsync(user, _lookupNormalizer.Normalize("moderator"));
+
+ user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId);
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task RemoveFromRoleAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ user.Roles.ShouldContain(x => x.RoleId == _testData.RoleModeratorId);
+
+ await _identityUserStore.RemoveFromRoleAsync(user, _lookupNormalizer.Normalize("moderator"));
+
+ user.Roles.ShouldNotContain(x => x.RoleId == _testData.RoleModeratorId);
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task GetRolesAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ var roleNames = await _identityUserStore.GetRolesAsync(user);
+ roleNames.ShouldNotBeEmpty();
+ roleNames.ShouldContain(x => x == "moderator");
+ roleNames.ShouldContain(x => x == "supporter");
+ }
+
+ [Fact]
+ public async Task IsInRoleAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.IsInRoleAsync(user, _lookupNormalizer.Normalize("moderator"))).ShouldBeTrue();
+ (await _identityUserStore.IsInRoleAsync(user, _lookupNormalizer.Normalize("moderatorNotExist"))).ShouldBeFalse();
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task GetClaimsAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ var claims = await _identityUserStore.GetClaimsAsync(user);
+ claims.ShouldNotBeEmpty();
+ claims.ShouldContain(x => x.Type == "TestClaimType" && x.Value == "42");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task AddClaimsAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.AddClaimsAsync(user, new List()
+ {
+ new Claim("MyClaimType", "MyClaimValue")
+ });
+
+ user.Claims.ShouldContain(x => x.ClaimType == "MyClaimType" && x.ClaimValue == "MyClaimValue");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task ReplaceClaimAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.ReplaceClaimAsync(user, new Claim("TestClaimType", "42"), new Claim("MyClaimType", "MyClaimValue"));
+
+ user.Claims.ShouldNotContain(x => x.ClaimType == "TestClaimType" && x.ClaimValue == "42");
+ user.Claims.ShouldContain(x => x.ClaimType == "MyClaimType" && x.ClaimValue == "MyClaimValue");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task RemoveClaimsAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.RemoveClaimsAsync(user, new List()
+ {
+ new Claim("TestClaimType", "42")
+ });
+
+ user.Claims.ShouldNotContain(x => x.ClaimType == "TestClaimType" && x.ClaimValue == "42");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task AddLoginAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ user.Logins.ShouldNotContain(x => x.LoginProvider == "facebook" && x.ProviderKey == "john");
+
+ await _identityUserStore.AddLoginAsync(user, new UserLoginInfo("facebook", "john", "John Nash"));
+
+ user.Logins.ShouldContain(x => x.LoginProvider == "facebook" && x.ProviderKey == "john");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task RemoveLoginAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ user.Logins.ShouldContain(x => x.LoginProvider == "github" && x.ProviderKey == "john");
+
+ await _identityUserStore.RemoveLoginAsync(user, "github", "john");
+
+ user.Logins.ShouldNotContain(x => x.LoginProvider == "github" && x.ProviderKey == "john");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task GetLoginsAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ var logins = await _identityUserStore.GetLoginsAsync(user);
+
+ logins.ShouldNotBeNull();
+ logins.ShouldContain(x => x.LoginProvider == "github" && x.ProviderKey == "john");
+ logins.ShouldContain(x => x.LoginProvider == "twitter" && x.ProviderKey == "johnx");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+
+ [Fact]
+ public async Task FindByLoginAsync()
+ {
+ var user = await _identityUserStore.FindByLoginAsync("github", "john");
+ user.ShouldNotBeNull();
+ user.UserName.ShouldBe("john.nash");
+ }
+
+
+ [Fact]
+ public async Task GetEmailConfirmedAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetEmailConfirmedAsync(user)).ShouldBe(user.EmailConfirmed);
+ }
+
+
+ [Fact]
+ public async Task SetEmailConfirmedAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var emailConfirmed = user.EmailConfirmed;
+
+ await _identityUserStore.SetEmailConfirmedAsync(user, !emailConfirmed);
+
+ user.EmailConfirmed.ShouldBe(!emailConfirmed);
+ }
+
+ [Fact]
+ public async Task SetEmailAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetEmailAsync(user, "john.nash.kobe@abp.io");
+
+ user.Email.ShouldBe("john.nash.kobe@abp.io");
+ //user.NormalizedEmail.ShouldBe(_lookupNormalizer.Normalize("john.nash.kobe@abp.io"));
+ }
+
+ [Fact]
+ public async Task GetEmailAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetEmailAsync(user)).ShouldBe(user.Email);
+ }
+
+ [Fact]
+ public async Task GetNormalizedEmailAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetNormalizedEmailAsync(user)).ShouldBe(user.NormalizedEmail);
+ }
+
+ [Fact]
+ public async Task SetNormalizedEmailAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetNormalizedEmailAsync(user, _lookupNormalizer.Normalize("john.nash.kobe@abp.io"));
+
+ user.NormalizedEmail.ShouldBe(_lookupNormalizer.Normalize("john.nash.kobe@abp.io"));
+ }
+
+ [Fact]
+ public async Task FindByEmailAsync()
+ {
+ var user = await _identityUserStore.FindByEmailAsync(_lookupNormalizer.Normalize("john.nash@abp.io"));
+
+ user.ShouldNotBeNull();
+ user.Email.ShouldBe("john.nash@abp.io");
+ }
+
+ [Fact]
+ public async Task GetLockoutEndDateAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetLockoutEndDateAsync(user)).ShouldBe(user.LockoutEnd);
+ }
+
+ [Fact]
+ public async Task SetLockoutEndDateAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetLockoutEndDateAsync(user, DateTimeOffset.Parse("01/01/2019"));
+
+ user.LockoutEnd.ShouldBe(DateTimeOffset.Parse("01/01/2019"));
+ }
+
+
+ [Fact]
+ public async Task IncrementAccessFailedCountAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var count = user.AccessFailedCount;
+
+ await _identityUserStore.IncrementAccessFailedCountAsync(user);
+
+ user.AccessFailedCount.ShouldBe(count + 1);
+ }
+
+ [Fact]
+ public async Task ResetAccessFailedCountAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.ResetAccessFailedCountAsync(user);
+
+ user.AccessFailedCount.ShouldBe(0);
+ }
+
+ [Fact]
+ public async Task GetAccessFailedCountAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetAccessFailedCountAsync(user)).ShouldBe(user.AccessFailedCount);
+ }
+
+ [Fact]
+ public async Task GetLockoutEnabledAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetLockoutEnabledAsync(user)).ShouldBe(user.LockoutEnabled);
+ }
+
+ [Fact]
+ public async Task SetLockoutEnabledAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var lockoutEnabled = user.LockoutEnabled;
+
+ await _identityUserStore.SetLockoutEnabledAsync(user, !lockoutEnabled);
+
+ user.LockoutEnabled.ShouldBe(!lockoutEnabled);
+ }
+
+
+ [Fact]
+ public async Task SetPhoneNumberAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetPhoneNumberAsync(user, "13800138000");
+
+ user.PhoneNumber.ShouldBe("13800138000");
+ }
+
+
+ [Fact]
+ public async Task GetPhoneNumberAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetPhoneNumberAsync(user)).ShouldBe(user.PhoneNumber);
+ }
+
+ [Fact]
+ public async Task GetPhoneNumberConfirmedAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetPhoneNumberConfirmedAsync(user)).ShouldBe(user.PhoneNumberConfirmed);
+ }
+
+
+ [Fact]
+ public async Task SetPhoneNumberConfirmedAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var phoneNumberConfirmed = user.PhoneNumberConfirmed;
+
+ await _identityUserStore.SetPhoneNumberConfirmedAsync(user, !phoneNumberConfirmed);
+
+ user.PhoneNumberConfirmed.ShouldBe(!phoneNumberConfirmed);
+ }
+
+
+ [Fact]
+ public async Task SetSecurityStampAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var securityStamp = Guid.NewGuid().ToString();
+
+ await _identityUserStore.SetSecurityStampAsync(user, securityStamp);
+
+ user.SecurityStamp.ShouldBe(securityStamp);
+ }
+
+ [Fact]
+ public async Task GetSecurityStampAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetSecurityStampAsync(user)).ShouldBe(user.SecurityStamp);
+ }
+
+
+ [Fact]
+ public async Task SetTwoFactorEnabledAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ var twoFactorEnabled = user.TwoFactorEnabled;
+
+ await _identityUserStore.SetTwoFactorEnabledAsync(user, !twoFactorEnabled);
+
+ user.TwoFactorEnabled.ShouldBe(!twoFactorEnabled);
+ }
+
+
+ [Fact]
+ public async Task GetTwoFactorEnabledAsync()
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetTwoFactorEnabledAsync(user)).ShouldBe(user.TwoFactorEnabled);
+ }
+
+ [Fact]
+ public async Task GetUsersForClaimAsync()
+ {
+ var user = await _identityUserStore.GetUsersForClaimAsync(new Claim("TestClaimType", "42"));
+ user.ShouldNotBeNull();
+ user.ShouldNotBeEmpty();
+ user.ShouldContain(x => x.UserName == "john.nash");
+ }
+
+ [Fact]
+ public async Task GetUsersInRoleAsync()
+ {
+ var user = await _identityUserStore.GetUsersInRoleAsync(_lookupNormalizer.Normalize("moderator"));
+ user.ShouldNotBeNull();
+ user.ShouldContain(x => x.UserName == "john.nash");
+ }
+
+ [Fact]
+ public async Task SetTokenAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetTokenAsync(user, "test-provider", "test-name", "123123");
+
+ user.Tokens.ShouldNotBeEmpty();
+ user.Tokens.ShouldContain(x => x.LoginProvider == "test-provider" && x.Name == "test-name" && x.Value == "123123");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task RemoveTokenAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.RemoveTokenAsync(user, "test-provider", "test-name");
+
+ user.Tokens.ShouldNotContain(x => x.LoginProvider == "test-provider" && x.Name == "test-name" && x.Value == "123123");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task GetTokenAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ (await _identityUserStore.GetTokenAsync(user, "test-provider", "test-name")).ShouldBe("test-value");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task SetAuthenticatorKeyAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.SetAuthenticatorKeyAsync(user, "testKey");
+
+ user.Tokens.ShouldContain(x => x.LoginProvider == "[AspNetUserStore]" && x.Name == "AuthenticatorKey" && x.Value == "testKey");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task GetAuthenticatorKeyAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ await _identityUserStore.SetAuthenticatorKeyAsync(user, "testKey");
+
+ (await _identityUserStore.GetAuthenticatorKeyAsync(user)).ShouldBe("testKey");
+
+ await uow.CompleteAsync();
+ }
+
+ }
+
+ [Fact]
+ public async Task CountCodesAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ await _identityUserStore.SetTokenAsync(user, "[AspNetUserStore]", "RecoveryCodes", "testKey;testKey2");
+
+ (await _identityUserStore.CountCodesAsync(user)).ShouldBe(2);
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task ReplaceCodesAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+
+ await _identityUserStore.ReplaceCodesAsync(user, new List()
+ {
+ "testKey",
+ "testKey2"
+ });
+
+ user.Tokens.ShouldContain(x => x.LoginProvider == "[AspNetUserStore]" && x.Name == "RecoveryCodes" && x.Value == "testKey;testKey2");
+
+ await uow.CompleteAsync();
+ }
+ }
+
+ [Fact]
+ public async Task RedeemCodeAsync()
+ {
+ using (var uow = _unitOfWorkManager.Begin())
+ {
+ var user = await _userRepository.FindByNormalizedUserNameAsync(_lookupNormalizer.Normalize("john.nash"));
+ user.ShouldNotBeNull();
+ await _identityUserStore.SetTokenAsync(user, "[AspNetUserStore]", "RecoveryCodes", "testKey;testKey2");
+
+ (await _identityUserStore.RedeemCodeAsync(user, "testKey")).ShouldBeTrue();
+
+ await uow.CompleteAsync();
+ }
+ }
+ }
+}
diff --git a/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs
new file mode 100644
index 0000000000..ef06949500
--- /dev/null
+++ b/modules/identity/test/Volo.Abp.Identity.Domain.Tests/Volo/Abp/Identity/UserRoleFinder_Tests.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.Identity
+{
+ public class UserRoleFinder_Tests : AbpIdentityDomainTestBase
+ {
+ private readonly IUserRoleFinder _userRoleFinder;
+ private readonly IdentityTestData _testData;
+
+ public UserRoleFinder_Tests()
+ {
+ _userRoleFinder = GetRequiredService();
+ _testData = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetRolesAsync()
+ {
+ var roleNames = await _userRoleFinder.GetRolesAsync(_testData.UserJohnId);
+ roleNames.ShouldNotBeEmpty();
+ roleNames.ShouldContain(x => x == "moderator");
+ roleNames.ShouldContain(x => x == "supporter");
+ }
+ }
+}
diff --git a/modules/permission-management/Volo.Abp.PermissionManagement.sln b/modules/permission-management/Volo.Abp.PermissionManagement.sln
index e0fdd1e0ec..5812918a3c 100644
--- a/modules/permission-management/Volo.Abp.PermissionManagement.sln
+++ b/modules/permission-management/Volo.Abp.PermissionManagement.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27428.1
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.28729.10
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B559B878-38F7-49CC-BC06-43A32D68C1A7}"
EndProject
@@ -29,9 +29,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManageme
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.MongoDB.Tests", "test\Volo.Abp.PermissionManagement.MongoDB.Tests\Volo.Abp.PermissionManagement.MongoDB.Tests.csproj", "{AFA65E08-1F17-4BBE-96A6-80F3CFE22A75}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.HttpApi", "src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj", "{9E0B517E-F02E-436F-9695-7CF12795D34C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.HttpApi", "src\Volo.Abp.PermissionManagement.HttpApi\Volo.Abp.PermissionManagement.HttpApi.csproj", "{9E0B517E-F02E-436F-9695-7CF12795D34C}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.HttpApi.Client", "src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj", "{1CD80519-9431-48DB-B0EA-291A73FF9F49}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.PermissionManagement.HttpApi.Client", "src\Volo.Abp.PermissionManagement.HttpApi.Client\Volo.Abp.PermissionManagement.HttpApi.Client.csproj", "{1CD80519-9431-48DB-B0EA-291A73FF9F49}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.PermissionManagement.Application.Tests", "test\Volo.Abp.PermissionManagement.Application.Tests\Volo.Abp.PermissionManagement.Application.Tests.csproj", "{A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -91,6 +93,10 @@ Global
{1CD80519-9431-48DB-B0EA-291A73FF9F49}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1CD80519-9431-48DB-B0EA-291A73FF9F49}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1CD80519-9431-48DB-B0EA-291A73FF9F49}.Release|Any CPU.Build.0 = Release|Any CPU
+ {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -109,6 +115,7 @@ Global
{AFA65E08-1F17-4BBE-96A6-80F3CFE22A75} = {63DA4A89-5908-4F37-B7E6-525AEEF20C77}
{9E0B517E-F02E-436F-9695-7CF12795D34C} = {B559B878-38F7-49CC-BC06-43A32D68C1A7}
{1CD80519-9431-48DB-B0EA-291A73FF9F49} = {B559B878-38F7-49CC-BC06-43A32D68C1A7}
+ {A0F72F5F-3713-4E06-ADB7-15ADFDCB79B1} = {63DA4A89-5908-4F37-B7E6-525AEEF20C77}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8FC7DF78-5E2D-489F-9D43-147D2ABAA112}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj
new file mode 100644
index 0000000000..7e817abf24
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo.Abp.PermissionManagement.Application.Tests.csproj
@@ -0,0 +1,18 @@
+
+
+
+ netcoreapp2.2
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs
new file mode 100644
index 0000000000..7102b8f851
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestBase.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using NSubstitute;
+using Volo.Abp.Users;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class AbpPermissionManagementApplicationTestBase : PermissionManagementTestBase
+ {
+ protected Guid? CurrentUserId { get; set; }
+
+ protected AbpPermissionManagementApplicationTestBase()
+ {
+ CurrentUserId = Guid.NewGuid();
+ }
+ protected override void AfterAddApplication(IServiceCollection services)
+ {
+ var currentUser = Substitute.For();
+ //currentUser.Id.Returns(ci => CurrentUserId);
+ currentUser.IsAuthenticated.Returns(true);
+
+ services.AddSingleton(currentUser);
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs
new file mode 100644
index 0000000000..2bbfb07acd
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/AbpPermissionManagementApplicationTestModule.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Microsoft.Extensions.DependencyInjection;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Modularity;
+
+namespace Volo.Abp.PermissionManagement
+{
+ [DependsOn(
+ typeof(AbpPermissionManagementApplicationModule),
+ typeof(AbpPermissionManagementTestModule)
+ )]
+ public class AbpPermissionManagementApplicationTestModule : AbpModule
+ {
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.AddAlwaysAllowAuthorization();
+
+ context.Services.Configure(options =>
+ {
+ options.ProviderPolicies[UserPermissionValueProvider.ProviderName] = UserPermissionValueProvider.ProviderName;
+ options.ProviderPolicies["Test"] = "Test";
+ options.ManagementProviders.Add();
+ });
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs
new file mode 100644
index 0000000000..8b36b02877
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Application.Tests/Volo/Abp/PermissionManagement/PermissionAppService_Tests.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Authorization.Permissions;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement.Application.Tests.Volo.Abp.PermissionManagement
+{
+ public class PermissionAppService_Tests : AbpPermissionManagementApplicationTestBase
+ {
+ private readonly IPermissionAppService _permissionAppService;
+ private readonly IPermissionGrantRepository _permissionGrantRepository;
+
+ public PermissionAppService_Tests()
+ {
+ _permissionAppService = GetRequiredService();
+ _permissionGrantRepository = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetAsync()
+ {
+ var permissionListResultDto = await _permissionAppService.GetAsync(UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString());
+
+ permissionListResultDto.ShouldNotBeNull();
+ permissionListResultDto.EntityDisplayName.ShouldBe(PermissionTestDataBuilder.User1Id.ToString());
+ permissionListResultDto.Groups.Count.ShouldBe(1);
+ permissionListResultDto.Groups.ShouldContain(x => x.Name == "TestGroup");
+
+ permissionListResultDto.Groups.First().Permissions.Count.ShouldBe(4);
+ permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission1");
+ permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission2");
+ permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission2.ChildPermission1");
+ permissionListResultDto.Groups.First().Permissions.ShouldContain(x => x.Name == "MyPermission3");
+
+ }
+
+ [Fact]
+ public async Task UpdateAsync()
+ {
+ (await _permissionGrantRepository.FindAsync("MyPermission1", "Test",
+ "Test")).ShouldBeNull();
+
+ await _permissionAppService.UpdateAsync("Test",
+ "Test", new UpdatePermissionsDto()
+ {
+ Permissions = new UpdatePermissionDto[]
+ {
+ new UpdatePermissionDto()
+ {
+ IsGranted = true,
+ Name = "MyPermission1"
+ }
+ }
+ });
+
+ (await _permissionGrantRepository.FindAsync("MyPermission1", "Test",
+ "Test")).ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task Update_Revoke_Test()
+ {
+ _permissionGrantRepository.Insert(
+ new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission1",
+ "Test",
+ "Test"
+ )
+ );
+ (await _permissionGrantRepository.FindAsync("MyPermission1", "Test",
+ "Test")).ShouldNotBeNull();
+
+ await _permissionAppService.UpdateAsync("Test",
+ "Test", new UpdatePermissionsDto()
+ {
+ Permissions = new UpdatePermissionDto[]
+ {
+ new UpdatePermissionDto()
+ {
+ IsGranted = false,
+ Name = "MyPermission1"
+ }
+ }
+ });
+
+ (await _permissionGrantRepository.FindAsync("MyPermission1", "Test",
+ "Test")).ShouldBeNull();
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs
index 4423cf114b..ec343d9615 100644
--- a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/AbpPermissionManagementTestBaseModule.cs
@@ -12,6 +12,14 @@ namespace Volo.Abp.PermissionManagement
)]
public class AbpPermissionManagementTestBaseModule : AbpModule
{
+ public override void ConfigureServices(ServiceConfigurationContext context)
+ {
+ context.Services.Configure(options =>
+ {
+ options.ManagementProviders.Add();
+ });
+ }
+
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
SeedTestData(context);
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs
new file mode 100644
index 0000000000..f66ed2995d
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.TestBase/Volo/Abp/PermissionManagement/TestPermissionManagementProvider.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Volo.Abp.Guids;
+using Volo.Abp.MultiTenancy;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class TestPermissionManagementProvider : PermissionManagementProvider
+ {
+ public override string Name => "Test";
+
+ public TestPermissionManagementProvider(
+ IPermissionGrantRepository permissionGrantRepository,
+ IGuidGenerator guidGenerator,
+ ICurrentTenant currentTenant)
+ : base(
+ permissionGrantRepository,
+ guidGenerator,
+ currentTenant)
+ {
+
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Basic_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionChecker_Basic_Tests.cs
similarity index 100%
rename from modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Basic_Tests.cs
rename to modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionChecker_Basic_Tests.cs
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs
new file mode 100644
index 0000000000..6868421a8a
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionDataSeeder_Tests.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class PermissionDataSeeder_Tests : PermissionTestBase
+ {
+ private readonly IPermissionDataSeeder _permissionDataSeeder;
+ private readonly IPermissionGrantRepository _grantpermissionGrantRepository;
+
+ public PermissionDataSeeder_Tests()
+ {
+ _permissionDataSeeder = GetRequiredService();
+ _grantpermissionGrantRepository = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task SeedAsync()
+ {
+ (await _grantpermissionGrantRepository.FindAsync("MyPermission1", "Test", "Test")).ShouldBeNull();
+ (await _grantpermissionGrantRepository.FindAsync("MyPermission2", "Test", "Test")).ShouldBeNull();
+
+ await _permissionDataSeeder.SeedAsync("Test", "Test", new List()
+ {
+ "MyPermission1",
+ "MyPermission2"
+ });
+
+ (await _grantpermissionGrantRepository.FindAsync("MyPermission1", "Test", "Test")).ShouldNotBeNull();
+ (await _grantpermissionGrantRepository.FindAsync("MyPermission2", "Test", "Test")).ShouldNotBeNull();
+
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs
new file mode 100644
index 0000000000..9d4248bb5a
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionGrantCacheItemInvalidator_Tests.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Authorization.Permissions;
+using Volo.Abp.Caching;
+using Volo.Abp.MultiTenancy;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class PermissionGrantCacheItemInvalidator_Tests : PermissionTestBase
+ {
+ private readonly IDistributedCache _cache;
+ private readonly IPermissionStore _permissionStore;
+ private readonly IPermissionGrantRepository _permissionGrantRepository;
+
+ public PermissionGrantCacheItemInvalidator_Tests()
+ {
+ _cache = GetRequiredService>();
+ _permissionStore = GetRequiredService();
+ _permissionGrantRepository = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task PermissionStore_IsGrantedAsync_Should_Cache_PermissionGrant()
+ {
+ (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString()))).ShouldBeNull();
+
+
+ await _permissionStore.IsGrantedAsync("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString());
+
+
+ (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString()))).ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task Cache_Should_Invalidator_WhenPermissionGrantChanged()
+ {
+ // IsGrantedAsync will cache PermissionGrant
+ await _permissionStore.IsGrantedAsync("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString());
+
+ var permissionGrant = await _permissionGrantRepository.FindAsync("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString());
+ permissionGrant.ShouldNotBeNull();
+ await _permissionGrantRepository.DeleteAsync(permissionGrant);
+
+ (await _cache.GetAsync(PermissionGrantCacheItem.CalculateCacheKey("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString()))).ShouldBeNull();
+ }
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs
new file mode 100644
index 0000000000..d1e249c29a
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManagementProvider_Tests.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Authorization.Permissions;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class PermissionManagementProvider_Tests : PermissionTestBase
+ {
+ private readonly IPermissionManagementProvider _permissionManagementProvider;
+ private readonly IPermissionGrantRepository _permissionGrantRepository;
+
+
+ public PermissionManagementProvider_Tests()
+ {
+ _permissionManagementProvider = GetRequiredService();
+ _permissionGrantRepository = GetRequiredService();
+ }
+
+
+ [Fact]
+ public async Task CheckAsync()
+ {
+ _permissionGrantRepository.Insert(
+ new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission1",
+ "Test",
+ "Test"
+ )
+ );
+
+ var permissionValueProviderGrantInfo = await _permissionManagementProvider.CheckAsync("MyPermission1",
+ "Test",
+ "Test");
+
+ permissionValueProviderGrantInfo.IsGranted.ShouldBeTrue();
+ permissionValueProviderGrantInfo.ProviderKey.ShouldBe("Test");
+ }
+
+ [Fact]
+ public async Task Check_Should_Return_NonGranted_When_ProviderName_NotEquals_Name()
+ {
+ var permissionValueProviderGrantInfo = await _permissionManagementProvider.CheckAsync("MyPermission1",
+ "TestNotExist",
+ "Test");
+
+ permissionValueProviderGrantInfo.IsGranted.ShouldBeFalse();
+ permissionValueProviderGrantInfo.ProviderKey.ShouldBeNull();
+ }
+
+
+ [Fact]
+ public async Task SetAsync()
+ {
+ _permissionGrantRepository.Insert(
+ new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission1",
+ "Test",
+ "Test"
+ )
+ );
+ (await _permissionGrantRepository.FindAsync("MyPermission1",
+ "Test",
+ "Test")).ShouldNotBeNull();
+
+ await _permissionManagementProvider.SetAsync("MyPermission1",
+ "Test",
+ false);
+
+ (await _permissionGrantRepository.FindAsync("MyPermission1",
+ "Test",
+ "Test")).ShouldBeNull();
+ }
+
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs
new file mode 100644
index 0000000000..b5fe647c89
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionManager_Tests.cs
@@ -0,0 +1,108 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Authorization.Permissions;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class PermissionManager_Tests : PermissionTestBase
+ {
+ private readonly IPermissionManager _permissionManager;
+ private readonly IPermissionGrantRepository _permissionGrantRepository;
+
+ public PermissionManager_Tests()
+ {
+ _permissionManager = GetRequiredService();
+ _permissionGrantRepository = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task GetAsync()
+ {
+ await _permissionGrantRepository.InsertAsync(new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission1",
+ "Test",
+ "Test")
+ );
+
+ var grantedProviders = await _permissionManager.GetAsync("MyPermission1",
+ "Test",
+ "Test");
+
+ grantedProviders.ShouldNotBeNull();
+ grantedProviders.IsGranted.ShouldBeTrue();
+ grantedProviders.Name.ShouldBe("MyPermission1");
+ grantedProviders.Providers.ShouldContain(x => x.Key == "Test");
+ }
+
+ [Fact]
+ public async Task Get_Should_Exception_When_Permission_Undefined()
+ {
+ await Assert.ThrowsAsync(async () => await _permissionManager.GetAsync(
+ "MyPermission1NotExist",
+ "Test",
+ "Test"));
+ }
+
+ [Fact]
+ public async Task GetAllAsync()
+ {
+ await _permissionGrantRepository.InsertAsync(new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission1",
+ "Test",
+ "Test")
+ );
+
+ await _permissionGrantRepository.InsertAsync(new PermissionGrant(
+ Guid.NewGuid(),
+ "MyPermission2",
+ "Test",
+ "Test")
+ );
+
+ var permissionWithGrantedProviders = await _permissionManager.GetAllAsync(
+ "Test",
+ "Test");
+
+ permissionWithGrantedProviders.ShouldNotBeNull();
+ permissionWithGrantedProviders.ShouldContain(x =>
+ x.IsGranted && x.Name == "MyPermission1" && x.Providers.Any(p => p.Key == "Test"));
+ permissionWithGrantedProviders.ShouldContain(x =>
+ x.IsGranted && x.Name == "MyPermission2" && x.Providers.Any(p => p.Key == "Test"));
+ }
+
+ [Fact]
+ public async Task SetAsync()
+ {
+ (await _permissionGrantRepository.FindAsync("MyPermission2",
+ "Test",
+ "Test")).ShouldBeNull();
+
+ await _permissionManager.SetAsync(
+ "MyPermission2",
+ "Test",
+ "Test", true);
+
+ (await _permissionGrantRepository.FindAsync("MyPermission2",
+ "Test",
+ "Test")).ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task Set_Should_Exception_When_Permission_Undefined()
+ {
+ await Assert.ThrowsAsync(async () => await _permissionManager.SetAsync(
+ "MyPermission1NotExist",
+ "Test",
+ "Test",
+ true));
+ }
+
+ }
+}
diff --git a/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs
new file mode 100644
index 0000000000..965899ede9
--- /dev/null
+++ b/modules/permission-management/test/Volo.Abp.PermissionManagement.Tests/Volo/Abp/PermissionManagement/PermissionStore_Tests.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using Shouldly;
+using Volo.Abp.Authorization.Permissions;
+using Xunit;
+
+namespace Volo.Abp.PermissionManagement
+{
+ public class PermissionStore_Tests : PermissionTestBase
+ {
+ private readonly IPermissionStore _permissionStore;
+
+ public PermissionStore_Tests()
+ {
+ _permissionStore = GetRequiredService();
+ }
+
+ [Fact]
+ public async Task IsGrantedAsync()
+ {
+ (await _permissionStore.IsGrantedAsync("MyPermission1",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString())).ShouldBeTrue();
+
+
+ (await _permissionStore.IsGrantedAsync("MyPermission1NotExist",
+ UserPermissionValueProvider.ProviderName,
+ PermissionTestDataBuilder.User1Id.ToString())).ShouldBeFalse();
+
+ }
+ }
+}
diff --git a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json
index e75ef463f1..e670d9f206 100644
--- a/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json
+++ b/modules/tenant-management/src/Volo.Abp.TenantManagement.Application.Contracts/Volo/Abp/TenantManagement/Localization/ApplicationContracts/zh-Hans.json
@@ -4,6 +4,7 @@
"Permission:TenantManagement": "租户管理",
"Permission:Create": "创建",
"Permission:Edit": "编辑",
- "Permission:Delete": "删除"
+ "Permission:Delete": "删除",
+ "Permission:ManageFeatures": "管理功能"
}
}
\ No newline at end of file
diff --git a/samples/MicroserviceDemo/databases/MsDemo_Identity.zip b/samples/MicroserviceDemo/databases/MsDemo_Identity.zip
index f31c9e4f3d..0cba5df02d 100644
Binary files a/samples/MicroserviceDemo/databases/MsDemo_Identity.zip and b/samples/MicroserviceDemo/databases/MsDemo_Identity.zip differ
diff --git a/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip b/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip
index 28ed35d8ca..2e722f4eda 100644
Binary files a/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip and b/samples/MicroserviceDemo/databases/MsDemo_ProductManagement.zip differ
diff --git a/samples/MicroserviceDemo/databases/restore/entrypoint.sh b/samples/MicroserviceDemo/databases/restore/entrypoint.sh
index 91de230f78..662c69b3a3 100644
--- a/samples/MicroserviceDemo/databases/restore/entrypoint.sh
+++ b/samples/MicroserviceDemo/databases/restore/entrypoint.sh
@@ -25,7 +25,7 @@ done
/opt/mssql-tools/bin/sqlcmd \
-S sqlserver -U SA -P $SA_PASSWORD \
-d MsDemo_Identity \
- -Q 'UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51512/signin-oidc" WHERE ClientId = "00265494-2D70-9615-4BD0-39EB2AF3CD33"
- UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51513/signin-oidc" WHERE ClientId = "10265494-2D70-9615-4BD0-39EB2AF3CD33"
- UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51512/signout-callback-oidc" WHERE ClientId = "00265494-2D70-9615-4BD0-39EB2AF3CD33"
- UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51513/signout-callback-oidc" WHERE ClientId = "10265494-2D70-9615-4BD0-39EB2AF3CD33"'
\ No newline at end of file
+ -Q 'UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51512/signin-oidc" WHERE ClientId = "3C8A6051-2030-1977-707F-39ED0F2F4527"
+ UPDATE IdentityServerClientRedirectUris SET RedirectUri = "http://localhost:51513/signin-oidc" WHERE ClientId = "D1190176-2529-D6AB-ED4C-39ED0F2F4557"
+ UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51512/signout-callback-oidc" WHERE ClientId = "3C8A6051-2030-1977-707F-39ED0F2F4527"
+ UPDATE IdentityServerClientPostLogoutRedirectUris SET PostLogoutRedirectUri = "http://localhost:51513/signout-callback-oidc" WHERE ClientId = "D1190176-2529-D6AB-ED4C-39ED0F2F4557"'
\ No newline at end of file
diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs
index 4bf1ab94f8..442ffa7d07 100644
--- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs
+++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/DemoAppModule.cs
@@ -115,7 +115,6 @@ namespace MyCompanyName.MyProjectName.DemoApp
app.UseAbpRequestLocalization();
app.UseAuditing();
-
app.UseMvcWithDefaultRouteAndArea();
using (var scope = context.ServiceProvider.CreateScope())
diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs
similarity index 99%
rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs
rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs
index 91a4c096ff..9189ba1c41 100644
--- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.Designer.cs
+++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.Designer.cs
@@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.DemoApp;
namespace MyCompanyName.MyProjectName.DemoApp.Migrations
{
[DbContext(typeof(DemoAppDbContext))]
- [Migration("20190320125012_Initial")]
+ [Migration("20190410095748_Initial")]
partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.cs b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.cs
similarity index 100%
rename from templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190320125012_Initial.cs
rename to templates/module/app/MyCompanyName.MyProjectName.DemoApp/Migrations/20190410095748_Initial.cs
diff --git a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj
index 041d6cf9ce..4e019c6d9b 100644
--- a/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj
+++ b/templates/module/app/MyCompanyName.MyProjectName.DemoApp/MyCompanyName.MyProjectName.DemoApp.csproj
@@ -35,8 +35,4 @@
-
-
-
-
diff --git a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs
similarity index 93%
rename from templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs
rename to templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs
index 8ef18c7e12..edb0c5cedf 100644
--- a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.Designer.cs
+++ b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.Designer.cs
@@ -10,7 +10,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace IdentityServerHost.Migrations
{
[DbContext(typeof(DemoAppDbContext))]
- [Migration("20190320142333_Initial")]
+ [Migration("20190410095119_Initial")]
partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -84,6 +84,8 @@ namespace IdentityServerHost.Migrations
b.Property("TenantId")
.HasColumnName("TenantId");
+ b.Property("TenantName");
+
b.Property("Url")
.HasColumnName("Url")
.HasMaxLength(256);
@@ -163,6 +165,8 @@ namespace IdentityServerHost.Migrations
.HasColumnName("EntityId")
.HasMaxLength(128);
+ b.Property("EntityTenantId");
+
b.Property("EntityTypeFullName")
.IsRequired()
.HasColumnName("EntityTypeFullName")
@@ -522,6 +526,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConcurrencyStamp");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -533,6 +549,17 @@ namespace IdentityServerHost.Migrations
b.Property("ExtraProperties")
.HasColumnName("ExtraProperties");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("Name")
.IsRequired()
.HasMaxLength(200);
@@ -660,6 +687,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConsentLifetime");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -679,6 +718,17 @@ namespace IdentityServerHost.Migrations
b.Property("IncludeJwtId");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("LogoUri")
.HasMaxLength(300);
@@ -890,6 +940,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConcurrencyStamp");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -903,6 +965,17 @@ namespace IdentityServerHost.Migrations
b.Property("ExtraProperties")
.HasColumnName("ExtraProperties");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("Name")
.IsRequired()
.HasMaxLength(200);
diff --git a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs
similarity index 96%
rename from templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs
rename to templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs
index 88588fb970..b90275e883 100644
--- a/templates/service/host/IdentityServerHost/Migrations/20190320142333_Initial.cs
+++ b/templates/service/host/IdentityServerHost/Migrations/20190410095119_Initial.cs
@@ -18,6 +18,7 @@ namespace IdentityServerHost.Migrations
UserId = table.Column(nullable: true),
UserName = table.Column(maxLength: 256, nullable: true),
TenantId = table.Column(nullable: true),
+ TenantName = table.Column(nullable: true),
ImpersonatorUserId = table.Column(nullable: true),
ImpersonatorTenantId = table.Column(nullable: true),
ExecutionTime = table.Column(nullable: false),
@@ -150,6 +151,13 @@ namespace IdentityServerHost.Migrations
Id = table.Column(nullable: false),
ExtraProperties = table.Column(nullable: true),
ConcurrencyStamp = table.Column(nullable: true),
+ CreationTime = table.Column(nullable: false),
+ CreatorId = table.Column(nullable: true),
+ LastModificationTime = table.Column(nullable: true),
+ LastModifierId = table.Column(nullable: true),
+ IsDeleted = table.Column(nullable: false, defaultValue: false),
+ DeleterId = table.Column(nullable: true),
+ DeletionTime = table.Column(nullable: true),
Name = table.Column(maxLength: 200, nullable: false),
DisplayName = table.Column(maxLength: 200, nullable: true),
Description = table.Column(maxLength: 1000, nullable: true),
@@ -167,6 +175,13 @@ namespace IdentityServerHost.Migrations
Id = table.Column(nullable: false),
ExtraProperties = table.Column(nullable: true),
ConcurrencyStamp = table.Column(nullable: true),
+ CreationTime = table.Column(nullable: false),
+ CreatorId = table.Column(nullable: true),
+ LastModificationTime = table.Column(nullable: true),
+ LastModifierId = table.Column(nullable: true),
+ IsDeleted = table.Column(nullable: false, defaultValue: false),
+ DeleterId = table.Column(nullable: true),
+ DeletionTime = table.Column(nullable: true),
ClientId = table.Column(maxLength: 200, nullable: false),
ClientName = table.Column(maxLength: 200, nullable: true),
Description = table.Column(maxLength: 1000, nullable: true),
@@ -214,6 +229,13 @@ namespace IdentityServerHost.Migrations
Id = table.Column(nullable: false),
ExtraProperties = table.Column(nullable: true),
ConcurrencyStamp = table.Column(nullable: true),
+ CreationTime = table.Column(nullable: false),
+ CreatorId = table.Column(nullable: true),
+ LastModificationTime = table.Column(nullable: true),
+ LastModifierId = table.Column(nullable: true),
+ IsDeleted = table.Column(nullable: false, defaultValue: false),
+ DeleterId = table.Column(nullable: true),
+ DeletionTime = table.Column(nullable: true),
Name = table.Column(maxLength: 200, nullable: false),
DisplayName = table.Column(maxLength: 200, nullable: true),
Description = table.Column(maxLength: 1000, nullable: true),
@@ -281,6 +303,7 @@ namespace IdentityServerHost.Migrations
TenantId = table.Column(nullable: true),
ChangeTime = table.Column(nullable: false),
ChangeType = table.Column(nullable: false),
+ EntityTenantId = table.Column(nullable: true),
EntityId = table.Column(maxLength: 128, nullable: false),
EntityTypeFullName = table.Column(maxLength: 128, nullable: false),
ExtraProperties = table.Column(nullable: true)
diff --git a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs
index 1aec48ea05..3b63d152aa 100644
--- a/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs
+++ b/templates/service/host/IdentityServerHost/Migrations/DemoAppDbContextModelSnapshot.cs
@@ -82,6 +82,8 @@ namespace IdentityServerHost.Migrations
b.Property("TenantId")
.HasColumnName("TenantId");
+ b.Property("TenantName");
+
b.Property("Url")
.HasColumnName("Url")
.HasMaxLength(256);
@@ -161,6 +163,8 @@ namespace IdentityServerHost.Migrations
.HasColumnName("EntityId")
.HasMaxLength(128);
+ b.Property("EntityTenantId");
+
b.Property("EntityTypeFullName")
.IsRequired()
.HasColumnName("EntityTypeFullName")
@@ -520,6 +524,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConcurrencyStamp");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -531,6 +547,17 @@ namespace IdentityServerHost.Migrations
b.Property("ExtraProperties")
.HasColumnName("ExtraProperties");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("Name")
.IsRequired()
.HasMaxLength(200);
@@ -658,6 +685,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConsentLifetime");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -677,6 +716,17 @@ namespace IdentityServerHost.Migrations
b.Property("IncludeJwtId");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("LogoUri")
.HasMaxLength(300);
@@ -888,6 +938,18 @@ namespace IdentityServerHost.Migrations
b.Property("ConcurrencyStamp");
+ b.Property("CreationTime")
+ .HasColumnName("CreationTime");
+
+ b.Property("CreatorId")
+ .HasColumnName("CreatorId");
+
+ b.Property("DeleterId")
+ .HasColumnName("DeleterId");
+
+ b.Property("DeletionTime")
+ .HasColumnName("DeletionTime");
+
b.Property("Description")
.HasMaxLength(1000);
@@ -901,6 +963,17 @@ namespace IdentityServerHost.Migrations
b.Property("ExtraProperties")
.HasColumnName("ExtraProperties");
+ b.Property("IsDeleted")
+ .ValueGeneratedOnAdd()
+ .HasColumnName("IsDeleted")
+ .HasDefaultValue(false);
+
+ b.Property("LastModificationTime")
+ .HasColumnName("LastModificationTime");
+
+ b.Property("LastModifierId")
+ .HasColumnName("LastModifierId");
+
b.Property("Name")
.IsRequired()
.HasMaxLength(200);
diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs
similarity index 98%
rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs
rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs
index 423eb1cb0a..4803948516 100644
--- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.Designer.cs
+++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.Designer.cs
@@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.Host;
namespace MyCompanyName.MyProjectName.Host.Migrations
{
[DbContext(typeof(DemoAppDbContext))]
- [Migration("20190320142412_Initial")]
+ [Migration("20190410095222_Initial")]
partial class Initial
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@@ -84,6 +84,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
b.Property("TenantId")
.HasColumnName("TenantId");
+ b.Property("TenantName");
+
b.Property("Url")
.HasColumnName("Url")
.HasMaxLength(256);
@@ -163,6 +165,8 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
.HasColumnName("EntityId")
.HasMaxLength(128);
+ b.Property("EntityTenantId");
+
b.Property("EntityTypeFullName")
.IsRequired()
.HasColumnName("EntityTypeFullName")
diff --git a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs
similarity index 98%
rename from templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs
rename to templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs
index b2074c3513..ecef8c8f9a 100644
--- a/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190320142412_Initial.cs
+++ b/templates/service/host/MyCompanyName.MyProjectName.Host/Migrations/20190410095222_Initial.cs
@@ -18,6 +18,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
UserId = table.Column(nullable: true),
UserName = table.Column(maxLength: 256, nullable: true),
TenantId = table.Column(nullable: true),
+ TenantName = table.Column(nullable: true),
ImpersonatorUserId = table.Column(nullable: true),
ImpersonatorTenantId = table.Column(nullable: true),
ExecutionTime = table.Column(nullable: false),
@@ -102,6 +103,7 @@ namespace MyCompanyName.MyProjectName.Host.Migrations
TenantId = table.Column(nullable: true),
ChangeTime = table.Column(nullable: false),
ChangeType = table.Column(nullable: false),
+ EntityTenantId = table.Column(nullable: true),
EntityId = table.Column(maxLength: 128, nullable: false),
EntityTypeFullName = table.Column(maxLength: 128, nullable: false),
ExtraProperties = table.Column