diff --git a/README.md b/README.md index 8dc562035..cd64f439a 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,7 @@ The purpose of MASA.Contrib is based on [MASA.BuildingBlocks](https://github.com * Storage: cloud storage * [Aliyun Storage](./src/Storage/Masa.Contrib.Storage.ObjectStorage.Aliyun/README.md) * Operational capacity + * [Auth](./src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.md): Authentication and Authorization * [Dcc](./src/BasicAbility/Masa.Contrib.BasicAbility.Dcc/README.md): Distributed Configuration Center * [PM](./src/BasicAbility/Masa.Contrib.BasicAbility.Pm/README.md): Project Management * [Scheduler](./src/BasicAbility/Masa.Contrib.BasicAbility.Scheduler/README.md): Distributed Scheduler diff --git a/README.zh-CN.md b/README.zh-CN.md index 080f658e1..5676458a7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,4 +1,4 @@ -中 | [EN](README.md) +中 | [EN](README.md) [![codecov](https://codecov.io/gh/masastack/MASA.Contrib/branch/main/graph/badge.svg?token=87TPNHUHW2)](https://codecov.io/gh/masastack/MASA.Contrib) @@ -56,6 +56,7 @@ MASA.Contrib是基于[MASA.BuildingBlocks](https://github.com/masastack/MASA.Bui * Storage: 云存储 * [阿里云存储](./src/Storage/Masa.Contrib.Storage.ObjectStorage.Aliyun/README.zh-CN.md) * 业务能力 + * [Auth](./src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.zh-CN.md): 权限认证 * [Dcc](./src/BasicAbility/Masa.Contrib.BasicAbility.Dcc/README.zh-CN.md): 分布式配置中心 * [PM](./src/BasicAbility/Masa.Contrib.BasicAbility.Pm/README.zh-CN.md): 项目管理 * [Scheduler](./src/BasicAbility/Masa.Contrib.BasicAbility.Scheduler/README.zh-CN.md): 分布式调度中心 diff --git a/src/Authentication/Masa.Contrib.Authentication.Oidc.EntityFrameworkCore/ServiceCollectionExtensions.cs b/src/Authentication/Masa.Contrib.Authentication.Oidc.EntityFrameworkCore/ServiceCollectionExtensions.cs index e45376674..50794fab0 100644 --- a/src/Authentication/Masa.Contrib.Authentication.Oidc.EntityFrameworkCore/ServiceCollectionExtensions.cs +++ b/src/Authentication/Masa.Contrib.Authentication.Oidc.EntityFrameworkCore/ServiceCollectionExtensions.cs @@ -21,14 +21,15 @@ public static IServiceCollection AddOidcDbContext(this IServiceCollection ser public static IServiceCollection SeedClientData(this IServiceCollection services, List clients) { var clientRepository = services.BuildServiceProvider().GetRequiredService(); - var apiScopeRepository = services.BuildServiceProvider().GetRequiredService(); + var identityResourceRepository = services.BuildServiceProvider().GetRequiredService(); var scopes = clients.SelectMany(c => c.AllowedScopes); foreach (var scope in scopes) { - if (apiScopeRepository.FindAsync(s => s.Name == scope.Scope).Result == null) + if (identityResourceRepository.FindAsync(s => s.Name == scope.Scope).Result == null) { - _ = apiScopeRepository.AddAsync(new ApiScope(scope.Scope)).Result; + _ = identityResourceRepository.AddAsync(new IdentityResource(scope.Scope, scope.Scope, "", + true, true, true, true, true)).Result; } } foreach (var client in clients) diff --git a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/AuthClient.cs b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/AuthClient.cs index d65c19773..79af2f22c 100644 --- a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/AuthClient.cs +++ b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/AuthClient.cs @@ -9,7 +9,7 @@ public AuthClient(ICallerProvider callerProvider, IMultiEnvironmentUserContext u { UserService = new UserService(callerProvider, userContext); SubjectService = new SubjectService(callerProvider); - TeamService = new TeamService(callerProvider); + TeamService = new TeamService(callerProvider, userContext); ProjectService = new ProjectService(callerProvider, userContext); PermissionService = new PermissionService(callerProvider, userContext); } diff --git a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.md b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.md new file mode 100644 index 000000000..5e18d7f30 --- /dev/null +++ b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.md @@ -0,0 +1,46 @@ +[中](README.zh-CN.md) | EN + +## Masa.Contrib.BasicAbility.Auth + +Injecting IAuthClient interface,cal the service to obtain the capabilities provided by the auth SDK. +SDK need to get current user ID dependency Masa.Contrib.Identity.IdentityModel(../../Identity/Masa.Contrib.Identity.IdentityModel/README.zh,Therefore,the identitymodel service needs to be added before use. + +### Service Introduction + +```c# +IAuthClient +├── UserService +├── SubjectService +├── TeamService +├── PermissionService +└── ProjectService +``` + +### Use Introduction + +#### Install dependent package + +```C# +Install-Package Masa.Contrib.BasicAbility.Auth +``` + +#### Register auth service + +```C# +builder.Services.AddAuthClient("http://authservice.com"); +``` + +> `http://authservice.com` is auth service address + +#### Dependency injection IAuthClient + +```c# +var app = builder.Build(); + +app.MapGet("/GetTeams", ([FromServices] IAuthClient authClient) => +{ + return authClient.TeamService.GetAllAsync(); +}); + +app.Run(); +``` diff --git a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.zh-CN.md b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.zh-CN.md new file mode 100644 index 000000000..db93895e3 --- /dev/null +++ b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/README.zh-CN.md @@ -0,0 +1,45 @@ +中 | [EN](README.md) + +## Masa.Contrib.BasicAbility.Auth + +通过注入IAuthClient接口,调用对应Service获取Auth SDK 提供的能力。 +SDK获取当前用户ID依赖Masa.Contrib.Identity.IdentityModel(../../Identity/Masa.Contrib.Identity.IdentityModel/README.zh-CN.zh,所以使用前需添加IdentityModel服务。 + +### 服务介绍 +```c# +IAuthClient +├── UserService 用户服务 +├── SubjectService 全局搜索用户、角色、团队、组织架构 +├── TeamService 团队服务 +├── PermissionService 权限、菜单服务 +└── ProjectService 全局导航服务 +``` + +### 使用介绍 + +#### 安装依赖包 + +```C# +Install-Package Masa.Contrib.BasicAbility.Auth +``` + +#### 注册相关服务 + +```C# +builder.Services.AddAuthClient("http://authservice.com"); +``` + +> `http://authservice.com` 为Auth后台服务地址 + +#### 依赖注入IAuthClient + +```c# +var app = builder.Build(); + +app.MapGet("/GetTeams", ([FromServices] IAuthClient authClient) => +{ + return authClient.TeamService.GetAllAsync(); +}); + +app.Run(); +``` diff --git a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/TeamService.cs b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/TeamService.cs index cbeb92107..49d5c6ecc 100644 --- a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/TeamService.cs +++ b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/TeamService.cs @@ -7,10 +7,12 @@ public class TeamService : ITeamService { readonly ICallerProvider _callerProvider; readonly string _party = "api/team/"; + readonly IUserContext _userContext; - public TeamService(ICallerProvider callerProvider) + public TeamService(ICallerProvider callerProvider, IUserContext userContext) { _callerProvider = callerProvider; + _userContext = userContext; } public async Task GetDetailAsync(Guid id) @@ -28,5 +30,18 @@ public async Task> GetListAsync(Guid userId = default) } return await _callerProvider.GetAsync>(requestUri) ?? new(); } + + public async Task> GetAllAsync() + { + var requestUri = $"{_party}list"; + return await _callerProvider.GetAsync>(requestUri) ?? new(); + } + + public async Task> GetUserTeamsAsync() + { + var userId = _userContext.GetUserId(); + var requestUri = $"{_party}list?userId={userId}"; + return await _callerProvider.GetAsync>(requestUri) ?? new(); + } } diff --git a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/UserService.cs b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/UserService.cs index 777d0c012..96889ddca 100644 --- a/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/UserService.cs +++ b/src/BasicAbility/Masa.Contrib.BasicAbility.Auth/Service/UserService.cs @@ -50,8 +50,9 @@ public async Task FindByAccountAsync(string account) return await _callerProvider.GetAsync(requestUri, new { account = account }) ?? new(); } - public async Task FindByIdAsync(Guid id) + public async Task GetCurrentUserAsync() { + var id = _userContext.GetUserId(); var requestUri = $"api/user/findById"; return await _callerProvider.GetAsync(requestUri, new { id }) ?? new(); } diff --git a/src/BuildingBlocks/MASA.BuildingBlocks b/src/BuildingBlocks/MASA.BuildingBlocks index 63dca8be6..2c304d286 160000 --- a/src/BuildingBlocks/MASA.BuildingBlocks +++ b/src/BuildingBlocks/MASA.BuildingBlocks @@ -1 +1 @@ -Subproject commit 63dca8be684c9fadcf21bc6529b2f9dfb7699c22 +Subproject commit 2c304d2869b38284630c314e48a3888046dd53be diff --git a/test/Masa.Contrib.BasicAbility.Auth.Tests/TeamServiceTest.cs b/test/Masa.Contrib.BasicAbility.Auth.Tests/TeamServiceTest.cs index 4a85fef7a..d2ede4b6c 100644 --- a/test/Masa.Contrib.BasicAbility.Auth.Tests/TeamServiceTest.cs +++ b/test/Masa.Contrib.BasicAbility.Auth.Tests/TeamServiceTest.cs @@ -14,21 +14,39 @@ public async Task TestGetDetailAsync() var requestUri = $"api/team/detail"; var callerProvider = new Mock(); callerProvider.Setup(provider => provider.GetAsync(requestUri, It.IsAny(), default)).ReturnsAsync(data).Verifiable(); - var teamService = new Mock(callerProvider.Object); + var userContext = new Mock(); + var teamService = new Mock(callerProvider.Object, userContext.Object); var result = await teamService.Object.GetDetailAsync(teamId); callerProvider.Verify(provider => provider.GetAsync(requestUri, It.IsAny(), default), Times.Once); Assert.IsTrue(result is not null); } [TestMethod] - public async Task TestGetListAsync() + public async Task TestGetAllAsync() { var data = new List(); var requestUri = $"api/team/list"; var callerProvider = new Mock(); callerProvider.Setup(provider => provider.GetAsync>(requestUri, default)).ReturnsAsync(data).Verifiable(); - var teamService = new Mock(callerProvider.Object); - var result = await teamService.Object.GetListAsync(); + var userContext = new Mock(); + var teamService = new Mock(callerProvider.Object, userContext.Object); + var result = await teamService.Object.GetAllAsync(); + callerProvider.Verify(provider => provider.GetAsync>(requestUri, default), Times.Once); + Assert.IsTrue(result is not null); + } + + [TestMethod] + public async Task TestGetUserTeamsAsync() + { + var userId = Guid.Parse("A9C8E0DD-1E9C-474D-8FE7-8BA9672D53D1"); + var data = new List(); + var requestUri = $"api/team/list?userId={userId}"; + var callerProvider = new Mock(); + callerProvider.Setup(provider => provider.GetAsync>(requestUri, default)).ReturnsAsync(data).Verifiable(); + var userContext = new Mock(); + userContext.Setup(user => user.GetUserId()).Returns(userId).Verifiable(); + var teamService = new Mock(callerProvider.Object, userContext.Object); + var result = await teamService.Object.GetUserTeamsAsync(); callerProvider.Verify(provider => provider.GetAsync>(requestUri, default), Times.Once); Assert.IsTrue(result is not null); } diff --git a/test/Masa.Contrib.BasicAbility.Auth.Tests/UserServiceTest.cs b/test/Masa.Contrib.BasicAbility.Auth.Tests/UserServiceTest.cs index cf30d3ea0..2b0bba999 100644 --- a/test/Masa.Contrib.BasicAbility.Auth.Tests/UserServiceTest.cs +++ b/test/Masa.Contrib.BasicAbility.Auth.Tests/UserServiceTest.cs @@ -105,6 +105,22 @@ public async Task TestFindByAccountAsync(string account) Assert.IsTrue(result is not null); } + [TestMethod] + public async Task TestGetCurrentUserAsync() + { + var userId = Guid.Parse("A9C8E0DD-1E9C-474D-8FE7-8BA9672D53D1"); + var data = new UserModel(); + var requestUri = $"api/user/findById"; + var callerProvider = new Mock(); + callerProvider.Setup(provider => provider.GetAsync(requestUri, It.IsAny(), default)).ReturnsAsync(data).Verifiable(); + var userContext = new Mock(); + userContext.Setup(user => user.GetUserId()).Returns(userId).Verifiable(); + var userService = new UserService(callerProvider.Object, userContext.Object); + var result = await userService.GetCurrentUserAsync(); + callerProvider.Verify(provider => provider.GetAsync(requestUri, It.IsAny(), default), Times.Once); + Assert.IsTrue(result is not null); + } + [TestMethod] [DataRow("https://www.baidu.com/")] public async Task TestVisitedAsync(string url)