From 5711a48b36d3f07aad2ab2c14ce0d6800a6bdd60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=86=9B?= <510423039@qq.com> Date: Sun, 21 Nov 2021 10:27:45 +0800 Subject: [PATCH] =?UTF-8?q?=E2=98=94=EF=B8=8F=20=E6=B7=BB=E5=8A=A0Identity?= =?UTF-8?q?Server=20Domain=E5=B1=82=E5=8D=95=E5=85=83=E6=B5=8B=E8=AF=95=20?= =?UTF-8?q?=F0=9F=9A=91=20=E4=BF=AE=E5=A4=8D=E5=8D=95=E5=85=83=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=E6=A3=80=E6=B5=8B=E5=87=BA=E5=BE=97Bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Pages/Account/Login.cshtml | 147 +++++------ .../Pages/Account/ReWriteLogin.cshtml | 101 ++++++++ .../IdenityServerApiResourceManager.cs | 23 +- .../IdenityServerApiScopeManager.cs | 16 +- .../IdenityServerClientManager.cs | 32 ++- .../IdentityServer/IdentityResourceManager.cs | 27 +- .../IdenityServerApiResourceManager_Tests.cs | 89 +++++++ .../IdenityServerApiScopeManager_Tests.cs | 86 +++++++ .../IdenityServerClientManager_Tests.cs | 202 +++++++++++++++ .../IdentityResourceManager_Tests.cs | 93 +++++++ .../IdentityServerDataSeedContributor.cs | 238 ++++++++++++++++++ 11 files changed, 924 insertions(+), 130 deletions(-) create mode 100644 aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/ReWriteLogin.cshtml create mode 100644 aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiResourceManager_Tests.cs create mode 100644 aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiScopeManager_Tests.cs create mode 100644 aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerClientManager_Tests.cs create mode 100644 aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdentityResourceManager_Tests.cs create mode 100644 aspnet-core/services/test/CompanyName.ProjectName.TestBase/IdentityServerDataSeedContributor.cs diff --git a/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/Login.cshtml b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/Login.cshtml index 46dae08e..21493d2a 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/Login.cshtml +++ b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/Login.cshtml @@ -1,101 +1,70 @@ @page @using Microsoft.AspNetCore.Mvc.Localization @using Volo.Abp.Account.Localization +@using Volo.Abp.Account.Settings +@using Volo.Abp.Settings @model Volo.Abp.Account.Web.Pages.Account.LoginModel @inject IHtmlLocalizer L - -@{ - ViewData["Title"] = L["Login"]; - Layout = null; -} - - @L["Login"] - - - - - - - - - - -
- - -
-
-
-
-
-

@L["Login"]

-
+@inject Volo.Abp.Settings.ISettingProvider SettingProvider +
+
+

@L["Login"]

+ @* @if (await SettingProvider.IsTrueAsync(AccountSettingNames.IsSelfRegistrationEnabled)) *@ + @* { *@ + @* *@ + @* @L["AreYouANewUser"] *@ + @* @L["Register"] *@ + @* *@ + @* } *@ + @if (Model.EnableLocalLogin) + { +
+
+ + +
-
-
- -
- - - -
-
- -
-
-
-
-
-
-
- -
-
-
- - - -
- - - - -
- -
-
-
-
- - - -
+
+ + + +
+ + + + + @* *@ + @* @L["ForgotPassword"] *@ + @* *@ + + @L["Login"] + @if (Model.ShowCancelButton) + { + @L["Cancel"] + } + + } - - -
+ @if (Model.VisibleExternalProviders.Any()) + { +
+
@L["OrLoginWith"]
+
+ @foreach (var provider in Model.VisibleExternalProviders) + { + + } +
+
+ } -
- -
- -
- -
-
+ @if (!Model.EnableLocalLogin && !Model.VisibleExternalProviders.Any()) + { +
+ @L["InvalidLoginRequest"] + @L["ThereAreNoLoginSchemesConfiguredForThisClient"]
-
+ }
- -
diff --git a/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/ReWriteLogin.cshtml b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/ReWriteLogin.cshtml new file mode 100644 index 00000000..46dae08e --- /dev/null +++ b/aspnet-core/services/host/CompanyName.ProjectName.IdentityServer/Pages/Account/ReWriteLogin.cshtml @@ -0,0 +1,101 @@ +@page +@using Microsoft.AspNetCore.Mvc.Localization +@using Volo.Abp.Account.Localization +@model Volo.Abp.Account.Web.Pages.Account.LoginModel +@inject IHtmlLocalizer L + +@{ + ViewData["Title"] = L["Login"]; + Layout = null; +} + + @L["Login"] + + + + + + + + + + +
+ + +
+
+
+
+
+

@L["Login"]

+
+
+
+
+ +
+ + + +
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + +
+ + + + +
+ +
+
+
+
+ + + +
+ + + +
+ +
+ +
+ +
+
+
+
+
+
+ +
+ + +
diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs index 78c2386a..7e833424 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiResourceManager.cs @@ -20,18 +20,20 @@ namespace CompanyName.ProjectName.IdentityServer } public Task> GetListAsync( - int skipCount, - int maxResultCount, + int skipCount = 0, + int maxResultCount = 10, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return _apiResourceRepository.GetListAsync("CreationTime desc", skipCount, maxResultCount, filter, + return _apiResourceRepository.GetListAsync("CreationTime desc", skipCount, + maxResultCount, filter, includeDetails, cancellationToken); } - public Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + public Task GetCountAsync(string filter = null, + CancellationToken cancellationToken = default) { return _apiResourceRepository.GetCountAsync(filter, cancellationToken); @@ -81,7 +83,8 @@ namespace CompanyName.ProjectName.IdentityServer // // properties?.Distinct().ToList().ForEach(item => { apiResource.AddProperty(item.Key, item.Value); }); - return await _apiResourceRepository.InsertAsync(apiResource, cancellationToken: cancellationToken); + return await _apiResourceRepository.InsertAsync(apiResource, + cancellationToken: cancellationToken); } public async Task DeleteAsync( @@ -136,13 +139,17 @@ namespace CompanyName.ProjectName.IdentityServer apiResource.Scopes.Clear(); - foreach (var item in scopes) + if (scopes != null) { - apiResource.AddScope(item); + foreach (var item in scopes) + { + apiResource.AddScope(item); + } } - return await _apiResourceRepository.UpdateAsync(apiResource, cancellationToken: cancellationToken); + return await _apiResourceRepository.UpdateAsync(apiResource, + cancellationToken: cancellationToken); } } } \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiScopeManager.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiScopeManager.cs index 1a45b37d..56c7912b 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiScopeManager.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerApiScopeManager.cs @@ -18,8 +18,8 @@ namespace CompanyName.ProjectName.IdentityServer } public Task> GetListAsync( - int skipCount, - int maxResultCount, + int skipCount = 0, + int maxResultCount = 10, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) @@ -33,7 +33,8 @@ namespace CompanyName.ProjectName.IdentityServer cancellationToken); } - public Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + public Task GetCountAsync(string filter = null, + CancellationToken cancellationToken = default) { return _apiScopeRepository.GetCountAsync(filter, cancellationToken); } @@ -50,7 +51,8 @@ namespace CompanyName.ProjectName.IdentityServer var apiScope = await _apiScopeRepository.GetByNameAsync(name, false); if (null != apiScope) throw new UserFriendlyException(message: $"{name}已存在"); - apiScope = new ApiScope(GuidGenerator.Create(), name, displayName, description, required, emphasize, + apiScope = new ApiScope(GuidGenerator.Create(), name, displayName, description, + required, emphasize, showInDiscoveryDocument, enabled); return await _apiScopeRepository.InsertAsync(apiScope); } @@ -81,9 +83,11 @@ namespace CompanyName.ProjectName.IdentityServer return _apiScopeRepository.DeleteAsync(id, autoSave, cancellationToken); } - public async Task> FindAllAsync(CancellationToken cancellationToken = default) + public async Task> FindAllAsync( + CancellationToken cancellationToken = default) { - return await _apiScopeRepository.GetListAsync(e => e.Enabled == true, false, cancellationToken); + return await _apiScopeRepository.GetListAsync(e => e.Enabled == true, false, + cancellationToken); } } } \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs index 0636c57f..412f8976 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdenityServerClientManager.cs @@ -22,36 +22,40 @@ namespace CompanyName.ProjectName.IdentityServer public Task> GetListAsync( - int skipCount, - int maxResultCount, + int skipCount = 0, + int maxResultCount = 10, string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { - return _clientRepository.GetListAsync("CreationTime desc", skipCount, maxResultCount, filter, includeDetails, + return _clientRepository.GetListAsync("CreationTime desc", skipCount, maxResultCount, + filter, includeDetails, cancellationToken); } - public Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) + public Task GetCountAsync(string filter = null, + CancellationToken cancellationToken = default) { return _clientRepository.GetCountAsync(filter, cancellationToken); } - public Task DeleteAsync(Guid id, bool autoSave = false, CancellationToken cancellationToken = default) + public Task DeleteAsync(Guid id, bool autoSave = false, + CancellationToken cancellationToken = default) { return _clientRepository.DeleteAsync(id, autoSave, default); } - public async Task CreateAsync(string clientId, string clientName, string description, string allowedGrantTypes) + public async Task CreateAsync(string clientId, string clientName, + string description, string allowedGrantTypes) { var entity = await _clientRepository.FindByClientIdAsync(clientId); if (null != entity) throw new UserFriendlyException(message: "当前ClientId已存在"); entity = new Client(GuidGenerator.Create(), clientId) { - ClientName = clientName, Description = description + ClientName = clientName, Description = description, + ClientClaimsPrefix = "client_" }; - entity.ClientClaimsPrefix="client_"; entity.AddGrantType(allowedGrantTypes); return await _clientRepository.InsertAsync(entity); } @@ -160,7 +164,6 @@ namespace CompanyName.ProjectName.IdentityServer client.ClientSecrets.Clear(); client.AddSecret(secret.ToSha256(), null, secretType, String.Empty); } - } } @@ -179,8 +182,15 @@ namespace CompanyName.ProjectName.IdentityServer var client = await _clientRepository.FindByClientIdAsync(clientId); if (client == null) throw new UserFriendlyException(message: $"{clientId}不存在"); client.RemoveAllScopes(); - scopes.ForEach(item => { client.AddScope(item.Trim()); }); - + + foreach (var item in scopes.Distinct()) + { + if (item.IsNotNullOrWhiteSpace()) + { + client.AddScope(item.Trim()); + } + + } return await _clientRepository.UpdateAsync(client); } diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs index ba93d0fb..39b89742 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Domain/IdentityServer/IdentityResourceManager.cs @@ -18,9 +18,9 @@ namespace CompanyName.ProjectName.IdentityServer } public Task> GetListAsync( - int skipCount, - int maxResultCount, - string filter, + int skipCount = 0, + int maxResultCount = 10, + string filter = null, bool includeDetails = false, CancellationToken cancellationToken = default) { @@ -33,22 +33,16 @@ namespace CompanyName.ProjectName.IdentityServer cancellationToken); } - public Task> GetAllAsync(CancellationToken cancellationToken = default) + public Task> GetAllAsync( + CancellationToken cancellationToken = default) { return _identityResourceRepository.GetListAsync(true, cancellationToken); } - public Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) - { - return _identityResourceRepository.GetCountAsync(filter, cancellationToken); - } - - public Task FindByNameAsync( - string name, - bool includeDetails = true, + public Task GetCountAsync(string filter = null, CancellationToken cancellationToken = default) { - return _identityResourceRepository.FindByNameAsync(name, includeDetails, cancellationToken); + return _identityResourceRepository.GetCountAsync(filter, cancellationToken); } @@ -63,9 +57,10 @@ namespace CompanyName.ProjectName.IdentityServer { var identityResource = await _identityResourceRepository.FindByNameAsync(name, false); if (null != identityResource) throw new UserFriendlyException(message: $"{name}已存在"); - identityResource = new IdentityResource(GuidGenerator.Create(), name, displayName, description, required, - emphasize, - showInDiscoveryDocument, enabled); + identityResource = new IdentityResource(GuidGenerator.Create(), name, displayName, + description, enabled, + required, + false, showInDiscoveryDocument); return await _identityResourceRepository.InsertAsync(identityResource); } diff --git a/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiResourceManager_Tests.cs b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiResourceManager_Tests.cs new file mode 100644 index 00000000..7224765e --- /dev/null +++ b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiResourceManager_Tests.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Shouldly; +using Volo.Abp; +using Xunit; + +namespace CompanyName.ProjectName.IdentityServer +{ + public class IdenityServerApiResourceManager_Tests : ProjectNameDomainTestBase + { + private readonly IdenityServerApiResourceManager _idenityServerApiResourceManager; + + public IdenityServerApiResourceManager_Tests() + { + _idenityServerApiResourceManager = + GetRequiredService(); + } + + [Fact] + public async Task Shuold_GetListAsync_Ok() + { + var result = await _idenityServerApiResourceManager.GetListAsync(); + result.Count.ShouldBe(1); + result.FirstOrDefault()?.Name.ShouldBe("ApiResource_Test"); + } + + [Fact] + public async Task Shuold_GetListAsync_Filter_Ok() + { + var result = + await _idenityServerApiResourceManager.GetListAsync(filter: "ApiResource_Test"); + result.Count.ShouldBe(1); + result.FirstOrDefault()?.Name.ShouldBe("ApiResource_Test"); + } + + + [Fact] + public async Task Shuold_GetCountAsync_Ok() + { + var result = await _idenityServerApiResourceManager.GetCountAsync(); + result.ShouldBe(1); + } + + [Fact] + public async Task Shuold_GetCountAsync_Filter_Ok() + { + var result = await _idenityServerApiResourceManager.GetCountAsync(filter:"ApiResource_Test"); + result.ShouldBe(1); + } + + [Fact] + public async Task Shuold_CreateAsync_Ok() + { + var result = await _idenityServerApiResourceManager.CreateAsync(Guid.NewGuid(), + "Create_ApiResource", "单元测试创建", "Xunit", true, "", false, "1q2w3E*"); + result.Name.ShouldBe("Create_ApiResource"); + } + + [Fact] + public async Task Shuold_CreateAsync_Name_Repetition_Exception() + { + (await Should.ThrowAsync(async () => + { + var result = await _idenityServerApiResourceManager.CreateAsync(Guid.NewGuid(), + "ApiResource_Test", "单元测试创建", "Xunit", true, "", false, "1q2w3E*"); + })).Message.ShouldBe("ApiResource已存在"); + } + + + [Fact] + public async Task Shuold_UpdateAsync_Ok() + { + var result = await _idenityServerApiResourceManager.UpdateAsync("ApiResource_Test", + "Update", "Update_Desc", false, "", true, + "123456", new List()); + result.Name.ShouldBe("ApiResource_Test"); + result.DisplayName.ShouldBe("Update"); + result.Enabled.ShouldBeFalse(); + } + + [Fact] + public async Task Shuold_DeleteAsync_Ok() + { + await _idenityServerApiResourceManager.DeleteAsync(Guid.NewGuid()); + } + } +} \ No newline at end of file diff --git a/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiScopeManager_Tests.cs b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiScopeManager_Tests.cs new file mode 100644 index 00000000..b1627b3d --- /dev/null +++ b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerApiScopeManager_Tests.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp; +using Xunit; + +namespace CompanyName.ProjectName.IdentityServer +{ + public class IdenityServerApiScopeManager_Tests : ProjectNameDomainTestBase + { + private readonly IdenityServerApiScopeManager _idenityServerApiScopeManager; + + public IdenityServerApiScopeManager_Tests() + { + _idenityServerApiScopeManager = GetRequiredService(); + } + + [Fact] + public async Task Shuold_GetListAsync_Ok() + { + var result = await _idenityServerApiScopeManager.GetListAsync(); + result.Count.ShouldBe(1); + result.FirstOrDefault()?.Name.ShouldBe("ApiScope_Test"); + } + + [Fact] + public async Task Shuold_GetListAsync_Filter_Ok() + { + var result = + await _idenityServerApiScopeManager.GetListAsync(filter: "ApiScope_Test"); + result.Count.ShouldBe(1); + result.FirstOrDefault()?.Name.ShouldBe("ApiScope_Test"); + } + + [Fact] + public async Task Shuold_GetCountAsync_Ok() + { + var result = await _idenityServerApiScopeManager.GetCountAsync(); + result.ShouldBe(1); + } + + [Fact] + public async Task Shuold_GetCountAsync_Filter_Ok() + { + var result = await _idenityServerApiScopeManager.GetCountAsync(filter: "ApiScope_Test"); + result.ShouldBe(1); + } + + [Fact] + public async Task Shuold_CreateAsync_Ok() + { + var result = await _idenityServerApiScopeManager.CreateAsync( + "Create_ApiScope", "单元测试创建", "Xunit", true, false, false, true); + result.Name.ShouldBe("Create_ApiScope"); + } + + [Fact] + public async Task Shuold_CreateAsync_Name_Repetition_Exception() + { + (await Should.ThrowAsync(async () => + { + var result = await _idenityServerApiScopeManager.CreateAsync( + "ApiScope_Test", "单元测试创建", "Xunit", true, false, false, true); + })).Message.ShouldBe("ApiScope_Test已存在"); + } + + [Fact] + public async Task Shuold_UpdateAsync_Ok() + { + var result = await _idenityServerApiScopeManager.UpdateAsync("ApiScope_Test", + "Update", "Update_Desc", true, true, true, + true); + result.DisplayName.ShouldBe("Update"); + result.Enabled.ShouldBeTrue(); + } + + [Fact] + public async Task Shuold_DeleteAsync_Ok() + { + await _idenityServerApiScopeManager.DeleteAsync(Guid.NewGuid()); + } + + } +} \ No newline at end of file diff --git a/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerClientManager_Tests.cs b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerClientManager_Tests.cs new file mode 100644 index 00000000..18d5ec16 --- /dev/null +++ b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdenityServerClientManager_Tests.cs @@ -0,0 +1,202 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp; +using Xunit; + +namespace CompanyName.ProjectName.IdentityServer +{ + public class IdenityServerClientManager_Tests : ProjectNameDomainTestBase + { + private readonly IdenityServerClientManager _idenityServerClientManager; + + public IdenityServerClientManager_Tests() + { + _idenityServerClientManager = GetRequiredService(); + } + + [Fact] + public async Task Shuold_GetListAsync_Ok() + { + var result = await _idenityServerClientManager.GetListAsync(); + result.ShouldNotBeNull(); + result.FirstOrDefault()?.ClientName.ShouldBe("Test_Client"); + } + + [Fact] + public async Task Shuold_GetListAsync_Filter_Ok() + { + var result = + await _idenityServerClientManager.GetListAsync(filter: "Test_Client"); + result.ShouldNotBeNull(); + result.FirstOrDefault()?.ClientName.ShouldBe("Test_Client"); + } + + + [Fact] + public async Task Shuold_GetCountAsync_Ok() + { + var result = await _idenityServerClientManager.GetCountAsync(); + result.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task Shuold_GetCountAsync_Filter_Ok() + { + var result = await _idenityServerClientManager.GetCountAsync(filter: "Test_Client"); + result.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task Shuold_CreateAsync_Ok() + { + var result = + await _idenityServerClientManager.CreateAsync("Xunit", "XunitName", "desc", "test"); + result.ClientName.ShouldBe("XunitName"); + result.Enabled.ShouldBeTrue(); + } + + [Fact] + public async Task Shuold_CreateAsync_Name_Repetition_Exception() + { + (await Should.ThrowAsync(async () => + { + var result = + await _idenityServerClientManager.CreateAsync("Test_Client", "XunitName", + "desc", "test"); + })).Message.ShouldBe("当前ClientId已存在"); + } + + [Fact] + public async Task Shuold_UpdateBasicDataAsync_Ok() + { + var result = await _idenityServerClientManager.UpdateBasicDataAsync( + "Test_Client", + "单元测试", + "desc", + "clientUrl", + "logoUrl", + false, + "http", + false, + false, + false, + false, + false, + false, + false, + false, + "logoutUrl", + false, + "backLogoutUrl", + false, + false, + 300, + "unit", + 3500, + 3400, + 3300, + 3200, + 3100, + false, + 3000, + 1, + false, + false, + false, + "client", + "salt", + 2900, + "user", + 2600, + 2800, + "123456", + "123456", + "sc" + ); + result.Description.ShouldBe("desc"); + result.Enabled.ShouldBeFalse(); + result.AccessTokenLifetime.ShouldBe(3500); + result.AuthorizationCodeLifetime.ShouldBe(3400); + result.IdentityTokenLifetime.ShouldBe(300); + result.RefreshTokenExpiration.ShouldBe(3000); + } + + [Fact] + public async Task Shuold_UpdateScopesAsync_Ok() + { + var result = + await _idenityServerClientManager.UpdateScopesAsync("Test_Client", + new List() { "001","002" }); + result.AllowedScopes.Count.ShouldBe(2); + } + + [Fact] + public async Task Shuold_AddRedirectUriAsync_Ok() + { + var result = + await _idenityServerClientManager.AddRedirectUriAsync("Test_Client","doc.cncore.club"); + result.RedirectUris.FirstOrDefault(e => e.RedirectUri == "doc.cncore.club") + .ShouldNotBeNull(); + } + + [Fact] + public async Task Shuold_RemoveRedirectUriAsync_Ok() + { + await WithUnitOfWorkAsync(async () => { await _idenityServerClientManager.AddRedirectUriAsync("Test_Client","doc.cncore.club");; }); + + var result = + await _idenityServerClientManager.RemoveRedirectUriAsync("Test_Client","doc.cncore.club"); + result.RedirectUris.FirstOrDefault(e => e.RedirectUri == "doc.cncore.club") + .ShouldBeNull(); + } + + + [Fact] + public async Task Shuold_AddLogoutRedirectUriAsync_Ok() + { + var result = + await _idenityServerClientManager.AddLogoutRedirectUriAsync("Test_Client","doc.cncore.club"); + result.PostLogoutRedirectUris.Any(e=>e.PostLogoutRedirectUri=="doc.cncore.club").ShouldBeTrue(); + } + + [Fact] + public async Task Shuold_RemoveLogoutRedirectUriAsync_Ok() + { + await WithUnitOfWorkAsync(async () => { await _idenityServerClientManager.AddLogoutRedirectUriAsync("Test_Client","doc.cncore.club");; }); + + var result = + await _idenityServerClientManager.RemoveLogoutRedirectUriAsync("Test_Client","doc.cncore.club"); + result.PostLogoutRedirectUris.Any(e=>e.PostLogoutRedirectUri=="doc.cncore.club").ShouldBeFalse(); + } + + [Fact] + public async Task Shuold_AddCorsAsync_Ok() + { + var result = + await _idenityServerClientManager.AddCorsAsync("Test_Client","doc.cncore.club"); + result.AllowedCorsOrigins.FirstOrDefault(e => e.Origin == "doc.cncore.club") + .ShouldNotBeNull(); + } + + [Fact] + public async Task Shuold_RemoveCorsAsync_Ok() + { + await WithUnitOfWorkAsync(async () => { await _idenityServerClientManager.AddCorsAsync("Test_Client","doc.cncore.club");; }); + + var result = + await _idenityServerClientManager.RemoveCorsAsync("Test_Client","doc.cncore.club"); + result.AllowedCorsOrigins.FirstOrDefault(e => e.Origin == "doc.cncore.club") + .ShouldBeNull(); + } + + [Fact] + public async Task Shuold_EnabledAsync_Ok() + { + var result = + await _idenityServerClientManager.EnabledAsync("Test_Client",false); + result.Enabled.ShouldBeFalse(); + } + } +} \ No newline at end of file diff --git a/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdentityResourceManager_Tests.cs b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdentityResourceManager_Tests.cs new file mode 100644 index 00000000..cfe341a9 --- /dev/null +++ b/aspnet-core/services/test/CompanyName.ProjectName.Domain.Tests/IdentityServer/IdentityResourceManager_Tests.cs @@ -0,0 +1,93 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Shouldly; +using Volo.Abp; +using Xunit; + +namespace CompanyName.ProjectName.IdentityServer +{ + public class IdentityResourceManager_Tests : ProjectNameDomainTestBase + { + private readonly IdentityResourceManager _identityResourceManager; + + public IdentityResourceManager_Tests() + { + _identityResourceManager = GetRequiredService(); + } + + + [Fact] + public async Task Shuold_GetListAsync_Ok() + { + var result = await _identityResourceManager.GetListAsync(); + result.ShouldNotBeNull(); + } + + [Fact] + public async Task Shuold_GetListAsync_Filter_Ok() + { + var result = + await _identityResourceManager.GetListAsync(filter: "openid"); + result.FirstOrDefault()?.Name.ShouldBe("openid"); + } + + + [Fact] + public async Task Shuold_GetCountAsync_Ok() + { + var result = await _identityResourceManager.GetCountAsync(); + result.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task Shuold_GetCountAsync_Filter_Ok() + { + var result = await _identityResourceManager.GetCountAsync(filter: "openid"); + result.ShouldBeGreaterThan(0); + } + + [Fact] + public async Task Shuold_CreateAsync_Ok() + { + var result = await _identityResourceManager.CreateAsync("Create_Identity", "单元测试", + "desc", true, false, + false, + false); + result.Name.ShouldBe("Create_Identity"); + result.Enabled.ShouldBeTrue(); + result.ShowInDiscoveryDocument.ShouldBeFalse(); + } + + [Fact] + public async Task Shuold_CreateAsync_Name_Repetition_Exception() + { + (await Should.ThrowAsync(async () => + { + var result = await _identityResourceManager.CreateAsync("openid", "单元测试", + "desc", true, false, + false, + false); + })).Message.ShouldBe("openid已存在"); + } + + + [Fact] + public async Task Shuold_UpdateAsync_Ok() + { + var result = await _identityResourceManager.UpdateAsync("openid", "单元测试", + "desc", false, false, + false, + false); + result.DisplayName.ShouldBe("单元测试"); + result.Enabled.ShouldBeFalse(); + } + + [Fact] + public async Task Shuold_DeleteAsync_Ok() + { + await _identityResourceManager.DeleteAsync(Guid.NewGuid()); + } + } +} \ No newline at end of file diff --git a/aspnet-core/services/test/CompanyName.ProjectName.TestBase/IdentityServerDataSeedContributor.cs b/aspnet-core/services/test/CompanyName.ProjectName.TestBase/IdentityServerDataSeedContributor.cs new file mode 100644 index 00000000..2615881e --- /dev/null +++ b/aspnet-core/services/test/CompanyName.ProjectName.TestBase/IdentityServerDataSeedContributor.cs @@ -0,0 +1,238 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using IdentityServer4.Models; +using Volo.Abp.Authorization.Permissions; +using Volo.Abp.Data; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.IdentityServer.ApiResources; +using Volo.Abp.IdentityServer.ApiScopes; +using Volo.Abp.IdentityServer.Clients; +using Volo.Abp.IdentityServer.IdentityResources; +using Volo.Abp.MultiTenancy; +using Volo.Abp.PermissionManagement; +using Volo.Abp.Uow; +using ApiResource = Volo.Abp.IdentityServer.ApiResources.ApiResource; +using ApiScope = Volo.Abp.IdentityServer.ApiScopes.ApiScope; +using Client = Volo.Abp.IdentityServer.Clients.Client; + +namespace CompanyName.ProjectName +{ + public class IdentityServerDataSeedContributor : IDataSeedContributor, ITransientDependency + { + private readonly IApiResourceRepository _apiResourceRepository; + private readonly IApiScopeRepository _apiScopeRepository; + private readonly IClientRepository _clientRepository; + private readonly IIdentityResourceDataSeeder _identityResourceDataSeeder; + private readonly IGuidGenerator _guidGenerator; + private readonly IPermissionDataSeeder _permissionDataSeeder; + private readonly ICurrentTenant _currentTenant; + + public IdentityServerDataSeedContributor( + IClientRepository clientRepository, + IApiResourceRepository apiResourceRepository, + IApiScopeRepository apiScopeRepository, + IIdentityResourceDataSeeder identityResourceDataSeeder, + IGuidGenerator guidGenerator, + IPermissionDataSeeder permissionDataSeeder, + ICurrentTenant currentTenant) + { + _clientRepository = clientRepository; + _apiResourceRepository = apiResourceRepository; + _apiScopeRepository = apiScopeRepository; + _identityResourceDataSeeder = identityResourceDataSeeder; + _guidGenerator = guidGenerator; + _permissionDataSeeder = permissionDataSeeder; + _currentTenant = currentTenant; + } + + [UnitOfWork] + public virtual async Task SeedAsync(DataSeedContext context) + { + using (_currentTenant.Change(context?.TenantId)) + { + await _identityResourceDataSeeder.CreateStandardResourcesAsync(); + await CreateApiResourcesAsync(); + await CreateApiScopesAsync(); + await CreateClientsAsync(); + } + } + + private async Task CreateApiScopesAsync() + { + await CreateApiScopeAsync(); + } + + private async Task CreateApiResourcesAsync() + { + var commonApiUserClaims = new[] + { + "email", + "email_verified", + "name", + "phone_number", + "phone_number_verified", + "role" + }; + + await CreateApiResourceAsync(commonApiUserClaims); + } + + private async Task CreateApiResourceAsync(IEnumerable claims) + { + var apiResource = new ApiResource( + _guidGenerator.Create(), + "ApiResource_Test", + "单元测试" + ); + return await _apiResourceRepository.InsertAsync(apiResource); + } + + private async Task CreateApiScopeAsync() + { + await _apiScopeRepository.InsertAsync( + new ApiScope( + _guidGenerator.Create(), + "ApiScope_Test" + ), + autoSave: true + ); + } + + private async Task CreateClientsAsync() + { + var client = await _clientRepository.FindByClientIdAsync("Test_Client"); + if (client != null) + { + return; + } + + var commonScopes = new[] + { + "email", + "openid", + "profile", + "role", + "phone", + "address", + }; + + await CreateClientAsync( + name: "Test_Client", + description: "单元测试", + scopes: commonScopes, + grantTypes: new[] { "implicit" }, + secret: "1q2w3E*".Sha256(), + redirectUri: "http://localhost:4200/oidcSignIn", + postLogoutRedirectUri: "http://localhost:4200/oidcSignOut", + frontChannelLogoutUri: "http://localhost:4200/oidcSignOut", + corsOrigins: new[] + { + "http://localhost:4200" + }, + requireClientSecret: false + ); + } + + private async Task CreateClientAsync( + string name, + string description, + IEnumerable scopes, + IEnumerable grantTypes, + string secret = null, + string redirectUri = null, + string postLogoutRedirectUri = null, + string frontChannelLogoutUri = null, + bool requireClientSecret = true, + bool requirePkce = false, + IEnumerable permissions = null, + IEnumerable corsOrigins = null) + { + var client = new Client( + _guidGenerator.Create(), + name + ) + { + ClientName = name, + ProtocolType = "oidc", + Description = description, + AlwaysIncludeUserClaimsInIdToken = true, + AllowOfflineAccess = true, + AbsoluteRefreshTokenLifetime = 31536000, //365 days + AccessTokenLifetime = 31536000, //365 days + AuthorizationCodeLifetime = 300, + IdentityTokenLifetime = 300, + RequireConsent = false, + FrontChannelLogoutUri = frontChannelLogoutUri, + RequireClientSecret = requireClientSecret, + RequirePkce = requirePkce, + AllowAccessTokensViaBrowser = true, + }; + + + foreach (var scope in scopes) + { + if (client.FindScope(scope) == null) + { + client.AddScope(scope); + } + } + + foreach (var grantType in grantTypes) + { + if (client.FindGrantType(grantType) == null) + { + client.AddGrantType(grantType); + } + } + + if (!secret.IsNullOrEmpty()) + { + if (client.FindSecret(secret) == null) + { + client.AddSecret(secret); + } + } + + if (redirectUri != null) + { + if (client.FindRedirectUri(redirectUri) == null) + { + client.AddRedirectUri(redirectUri); + } + } + + if (postLogoutRedirectUri != null) + { + if (client.FindPostLogoutRedirectUri(postLogoutRedirectUri) == null) + { + client.AddPostLogoutRedirectUri(postLogoutRedirectUri); + } + } + + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + + if (corsOrigins != null) + { + foreach (var origin in corsOrigins) + { + if (!origin.IsNullOrWhiteSpace() && client.FindCorsOrigin(origin) == null) + { + client.AddCorsOrigin(origin); + } + } + } + + return await _clientRepository.InsertAsync(client); + } + } +} \ No newline at end of file