From 73d8d67504a27fcf79b413249875a7d7f7d1186e Mon Sep 17 00:00:00 2001 From: liguoyang Date: Wed, 5 Jun 2024 17:54:41 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E6=95=B0=E6=8D=AE=E6=95=8F=E6=84=9F?= =?UTF-8?q?=E5=88=86=E9=85=8D=E8=A7=92=E8=89=B2=E5=8F=AF=E8=A7=81,?= =?UTF-8?q?=E5=88=87=E6=8D=A2=E5=9F=BA=E5=9C=B0,=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1lock?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Src/Dlhis.Basic/Dlhis.Basic.csproj | 1 - .../ObfuscateProviderJsonConverter.cs | 50 +++++++++++++++++++ .../Controllers/GainfoMealController.cs | 3 ++ .../Response/GainfoPageResponse.cs | 14 +++--- .../Services/Implements/MealUserService.cs | 1 - Src/Dlhis.ScheduledTask/BaseJob.cs | 22 +++----- .../Jobs/DeleteApiLogTaskJob.cs | 3 +- .../Identity/Controllers/RolesController.cs | 23 ++++++++- .../Identity/Controllers/UsersController.cs | 14 +++++- .../Identity/Request/RoleObfuscateRequest.cs | 9 ++++ .../Request/UserResetLoginTenantRequest.cs | 12 +++++ .../Identity/Services/IRoleService.cs | 6 ++- .../Identity/Services/IUserService.cs | 2 + .../Services/Implements/RoleService.cs | 32 +++++++++++- .../Services/Implements/UserService.cs | 25 +++++++++- Src/Dlhis.Sys/Program.cs | 7 +++ Src/Dlhis.Sys/appsettings.json | 3 ++ 17 files changed, 196 insertions(+), 31 deletions(-) create mode 100644 Src/Dlhis.Basic/ObfuscateProviderJsonConverter.cs create mode 100644 Src/Dlhis.Sys/Identity/Request/RoleObfuscateRequest.cs create mode 100644 Src/Dlhis.Sys/Identity/Request/UserResetLoginTenantRequest.cs diff --git a/Src/Dlhis.Basic/Dlhis.Basic.csproj b/Src/Dlhis.Basic/Dlhis.Basic.csproj index c78651c2..431cf27f 100644 --- a/Src/Dlhis.Basic/Dlhis.Basic.csproj +++ b/Src/Dlhis.Basic/Dlhis.Basic.csproj @@ -31,7 +31,6 @@ - diff --git a/Src/Dlhis.Basic/ObfuscateProviderJsonConverter.cs b/Src/Dlhis.Basic/ObfuscateProviderJsonConverter.cs new file mode 100644 index 00000000..a76eb20c --- /dev/null +++ b/Src/Dlhis.Basic/ObfuscateProviderJsonConverter.cs @@ -0,0 +1,50 @@ +using System.Security.Claims; +using Kurisu.AspNetCore; +using Kurisu.AspNetCore.Authentication.Abstractions; +using Kurisu.AspNetCore.Utils; +using Kurisu.AspNetCore.Utils.Converters; +using Newtonsoft.Json; + +namespace Dlhis.Basic; + +public class ObfuscateProviderJsonConverter : ObfuscateJsonConverter +{ + private readonly int _last; + + /// + public ObfuscateProviderJsonConverter(int last) : base(last) + { + _last = last; + } + + /// + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var sp = App.GetServiceProvider(true); + var cache = sp.GetService(); + var currentUser = sp.GetService(); + var range = cache.ListRange("datapermission:role"); + if (range.Contains(currentUser.GetUserClaim(ClaimTypes.Role))) + { + writer.WriteValue(value); + } + else + { + var v = value?.ToString() ?? string.Empty; + var vc = v.ToCharArray().Reverse().ToList(); + + for (int i = 0; i < vc.Count; i++) + { + if (i + 1 > _last) + { + vc[i] = '*'; + } + } + + vc.Reverse(); + v = string.Join("", vc); + + writer.WriteValue(v); + } + } +} \ No newline at end of file diff --git a/Src/Dlhis.Basic/Organization/Controllers/GainfoMealController.cs b/Src/Dlhis.Basic/Organization/Controllers/GainfoMealController.cs index f352daf4..b93a4490 100644 --- a/Src/Dlhis.Basic/Organization/Controllers/GainfoMealController.cs +++ b/Src/Dlhis.Basic/Organization/Controllers/GainfoMealController.cs @@ -2,6 +2,7 @@ using Dlhis.Basic.Organization.Response; using Dlhis.Basic.Organization.Services; using Kurisu.AspNetCore.DataAccess.Dto; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -37,6 +38,8 @@ public class GainfoMealController : ControllerBase /// 迁移 /// [Authorize(Roles = "admin")] + [Transactional] + [Authorize(Roles = "admin,tenant-admin")] [HttpPost("migration")] public async Task MigrationAsync(GainfoBalanceMigrationRequest request) { diff --git a/Src/Dlhis.Basic/Organization/Response/GainfoPageResponse.cs b/Src/Dlhis.Basic/Organization/Response/GainfoPageResponse.cs index 3de856ad..cac38ce0 100644 --- a/Src/Dlhis.Basic/Organization/Response/GainfoPageResponse.cs +++ b/Src/Dlhis.Basic/Organization/Response/GainfoPageResponse.cs @@ -47,8 +47,14 @@ public class GainfoPageResponse /// /// 身份证号 /// - [JsonConverter(typeof(ObfuscateJsonConverter), 6)] + [JsonConverter(typeof(ObfuscateProviderJsonConverter), 6)] public string IdNo { get; set; } + + /// + /// 手机号码 + /// + [JsonConverter(typeof(ObfuscateProviderJsonConverter), 4)] + public string Phone { get; set; } /// /// 身份证籍贯区域代码 @@ -88,12 +94,6 @@ public class GainfoPageResponse /// public string Nation { get; set; } - /// - /// 手机号码 - /// - [JsonConverter(typeof(ObfuscateJsonConverter), 4)] - public string Phone { get; set; } - /// /// 学历 /// diff --git a/Src/Dlhis.Basic/Organization/Services/Implements/MealUserService.cs b/Src/Dlhis.Basic/Organization/Services/Implements/MealUserService.cs index a8c13089..e9789d4c 100644 --- a/Src/Dlhis.Basic/Organization/Services/Implements/MealUserService.cs +++ b/Src/Dlhis.Basic/Organization/Services/Implements/MealUserService.cs @@ -9,7 +9,6 @@ using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; -using SqlSugar; namespace Dlhis.Basic.Organization.Services.Implements; diff --git a/Src/Dlhis.ScheduledTask/BaseJob.cs b/Src/Dlhis.ScheduledTask/BaseJob.cs index 12a01794..845ce16d 100644 --- a/Src/Dlhis.ScheduledTask/BaseJob.cs +++ b/Src/Dlhis.ScheduledTask/BaseJob.cs @@ -23,27 +23,21 @@ public abstract class BaseJob : IJob { using (var scope = _serviceProvider.CreateScope()) { - Logger = scope.ServiceProvider.GetService>(); - var recurringJob = this.GetType().GetCustomAttribute()!; var key = recurringJob.UniqueJobKey; - var name = recurringJob!.Name; - - var redisCache = scope.ServiceProvider.GetService(); - await using var handler = await redisCache.LockAsync($"scheduled:{key}"); - + var name = recurringJob.Name; + + Logger = scope.ServiceProvider.GetService>(); DbContext = scope.ServiceProvider.GetService(); - DbContext.Client.QueryFilter.ClearAndBackup(); - var sqlSugarOptionsService = scope.ServiceProvider.GetService(); - sqlSugarOptionsService.IgnoreTenant = true; try { + var redisCache = scope.ServiceProvider.GetService(); + await using var handler = await redisCache.LockAsync($"Scheduled:{key}"); if (handler.Acquired) { - Logger.LogInformation("[{name}]开始执行...", name); - - await RunAsync(scope.ServiceProvider); + Logger.LogDebug("[{name}]开始执行...", name); + await DbContext.IgnoreAsync(async () => { await RunAsync(scope.ServiceProvider); }); } } catch (Exception ex) @@ -53,8 +47,6 @@ public abstract class BaseJob : IJob finally { Logger.LogDebug("[{name}]执行结束...", name); - DbContext.Client.QueryFilter.Restore(); - sqlSugarOptionsService.IgnoreTenant = false; } } } diff --git a/Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs b/Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs index 37c2b3a4..3a4652b3 100644 --- a/Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs +++ b/Src/Dlhis.ScheduledTask/Jobs/DeleteApiLogTaskJob.cs @@ -9,14 +9,13 @@ namespace Dlhis.ScheduledTask.Jobs; [RecurringJob(nameof(DeleteApiLogTaskJob), "0 0 0 */6 * ?", Name = "删除过期日志")] public class DeleteApiLogTaskJob : BaseJob { - public DeleteApiLogTaskJob(IServiceProvider serviceProvider) : base(serviceProvider) { } protected override async Task RunAsync(IServiceProvider serviceProvider) { - var before = DateTime.Now.Date.AddDays(-7); + var before = DateTime.Now.Date.AddDays(-60); await DbContext.ChangeDb("log").Client.Deleteable().Where(x => x._ts <= before).ExecuteCommandAsync(); } } diff --git a/Src/Dlhis.Sys/Identity/Controllers/RolesController.cs b/Src/Dlhis.Sys/Identity/Controllers/RolesController.cs index e2638836..b17eccb8 100644 --- a/Src/Dlhis.Sys/Identity/Controllers/RolesController.cs +++ b/Src/Dlhis.Sys/Identity/Controllers/RolesController.cs @@ -89,4 +89,25 @@ public class RolesController : ControllerBase { return await _roleService.GetMyRoleAsync(userId); } -} + + /// + /// 设置混淆 + /// + /// + [HttpPost("obfuscate")] + public async Task SaveRoleObfuscateAsync(RoleObfuscateRequest request) + { + await _roleService.SaveRoleObfuscateAsync(request); + } + + /// + /// 获取混淆状态 + /// + /// + /// + [HttpGet("obfuscate")] + public async Task GetRoleObfuscateAsync(int id) + { + return await _roleService.GetRoleObfuscateAsync(id); + } +} \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Controllers/UsersController.cs b/Src/Dlhis.Sys/Identity/Controllers/UsersController.cs index 58fb47b5..7bb6941d 100644 --- a/Src/Dlhis.Sys/Identity/Controllers/UsersController.cs +++ b/Src/Dlhis.Sys/Identity/Controllers/UsersController.cs @@ -2,6 +2,7 @@ using Dlhis.Sys.Identity.Response; using Dlhis.Sys.Identity.Services; using Kurisu.AspNetCore.DataAccess.Dto; +using Kurisu.AspNetCore.DataAccess.SqlSugar.Aop; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -86,4 +87,15 @@ public class UsersController : ControllerBase { await _userService.UploadUserAvatarAsync(request); } -} + + /// + /// 重置登陆 + /// + /// + [Transactional] + [HttpPost("reloginInfo")] + public async Task ResetLoginTenantAsync(UserResetLoginTenantRequest request) + { + await _userService.ResetLoginTenantAsync(request); + } +} \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Request/RoleObfuscateRequest.cs b/Src/Dlhis.Sys/Identity/Request/RoleObfuscateRequest.cs new file mode 100644 index 00000000..df2a88dd --- /dev/null +++ b/Src/Dlhis.Sys/Identity/Request/RoleObfuscateRequest.cs @@ -0,0 +1,9 @@ +namespace Dlhis.Sys.Identity.Request +{ + public class RoleObfuscateRequest + { + public int Id { get; set; } + + public bool IsShow { get; set; } + } +} \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Request/UserResetLoginTenantRequest.cs b/Src/Dlhis.Sys/Identity/Request/UserResetLoginTenantRequest.cs new file mode 100644 index 00000000..c9a90d3b --- /dev/null +++ b/Src/Dlhis.Sys/Identity/Request/UserResetLoginTenantRequest.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace Dlhis.Sys.Identity.Request; + +public class UserResetLoginTenantRequest +{ + /// + /// 租户 + /// + [Required(ErrorMessage = "{0}不可为空")] + public string Tenant { get; set; } +} \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Services/IRoleService.cs b/Src/Dlhis.Sys/Identity/Services/IRoleService.cs index 9590241c..409587b3 100644 --- a/Src/Dlhis.Sys/Identity/Services/IRoleService.cs +++ b/Src/Dlhis.Sys/Identity/Services/IRoleService.cs @@ -17,4 +17,8 @@ public interface IRoleService : IScopeDependency Task RemoveRoleAsync(IdRequest request); Task AssignRoleAsync(RoleAssignRequest request); -} + + Task SaveRoleObfuscateAsync(RoleObfuscateRequest request); + + Task GetRoleObfuscateAsync(int id); +} \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Services/IUserService.cs b/Src/Dlhis.Sys/Identity/Services/IUserService.cs index f50a8977..84c069e7 100644 --- a/Src/Dlhis.Sys/Identity/Services/IUserService.cs +++ b/Src/Dlhis.Sys/Identity/Services/IUserService.cs @@ -20,4 +20,6 @@ public interface IUserService : IScopeDependency Task> GetUserByIdsAsync(List ids); Task CreateUserAsync(UserCreateRequest request); + + Task ResetLoginTenantAsync(UserResetLoginTenantRequest request); } \ No newline at end of file diff --git a/Src/Dlhis.Sys/Identity/Services/Implements/RoleService.cs b/Src/Dlhis.Sys/Identity/Services/Implements/RoleService.cs index a0cf79e9..6f52900c 100644 --- a/Src/Dlhis.Sys/Identity/Services/Implements/RoleService.cs +++ b/Src/Dlhis.Sys/Identity/Services/Implements/RoleService.cs @@ -6,6 +6,7 @@ using Kurisu.AspNetCore.CustomClass; using Kurisu.AspNetCore.DataAccess.Dto; using Kurisu.AspNetCore.DataAccess.SqlSugar.Extensions; using Kurisu.AspNetCore.DataAccess.SqlSugar.Services; +using Kurisu.AspNetCore.Utils; using Kurisu.AspNetCore.Utils.Extensions; namespace Dlhis.Sys.Identity.Services.Implements; @@ -13,11 +14,13 @@ namespace Dlhis.Sys.Identity.Services.Implements; public class RoleService : IRoleService { private readonly ICurrentUser _currentUser; + private readonly RedisCache _redisCache; private readonly IDbContext _dbContext; - public RoleService(ICurrentUser currentUser, IDbContext dbContext) + public RoleService(ICurrentUser currentUser, IDbContext dbContext, RedisCache redisCache) { _currentUser = currentUser; + _redisCache = redisCache; _dbContext = dbContext.ChangeDb("identity"); } @@ -112,6 +115,33 @@ public class RoleService : IRoleService } } + /// + public async Task SaveRoleObfuscateAsync(RoleObfuscateRequest request) + { + var role = await _dbContext.Queryable().FirstAsync(x => x.Id == request.Id); + role.ThrowIfNull("角色不存在"); + + var key = "datapermission:role"; + if (request.IsShow) + { + await _redisCache.ListLeftPushAsync(key, role.Name); + } + else + { + await _redisCache.ListRemoveAsync(key, role.Name); + } + } + + /// + public async Task GetRoleObfuscateAsync(int id) + { + var role = await _dbContext.Queryable().FirstAsync(x => x.Id == id); + var key = "datapermission:role"; + var range = await _redisCache.ListRangeAsync(key); + + return range.Any(x => (string)x == role.Name); + } + public async Task RemoveRoleAsync(IdRequest request) { var role = await _dbContext.Queryable().FirstAsync(x => x.Id == request.Id); diff --git a/Src/Dlhis.Sys/Identity/Services/Implements/UserService.cs b/Src/Dlhis.Sys/Identity/Services/Implements/UserService.cs index 448f0d2a..4561dc55 100644 --- a/Src/Dlhis.Sys/Identity/Services/Implements/UserService.cs +++ b/Src/Dlhis.Sys/Identity/Services/Implements/UserService.cs @@ -16,12 +16,14 @@ public class UserService : IUserService { private readonly IDbContext _dbContext; private readonly ICurrentUser _currentUser; + private readonly ITenantService _tenantService; private readonly IDbContext _identityDbContext; - public UserService(IDbContext dbContext, ICurrentUser currentUser) + public UserService(IDbContext dbContext, ICurrentUser currentUser, ITenantService tenantService) { _dbContext = dbContext; _currentUser = currentUser; + _tenantService = tenantService; _identityDbContext = dbContext.ChangeDb("identity"); } @@ -135,4 +137,25 @@ public class UserService : IUserService }); } } + + public async Task ResetLoginTenantAsync(UserResetLoginTenantRequest request) + { + var tenants = await _tenantService.GetMyTenantsAsync(); + tenants.All(x => x.Code != request.Tenant).ThrowIfTrue($"不可切换登陆:{request.Tenant}"); + + var userId = _currentUser.GetIntSubjectId(); + + await _dbContext.Updateable() + .SetColumns(x => x.ClaimValue == request.Tenant) + .Where(x => x.UserId == userId) + .Where(x => x.ClaimType == "tenant") + .ExecuteCommandAsync(); + + var tenantStr = tenants.Select(x => x.Code).Join(","); + await _dbContext.Updateable() + .SetColumns(x => x.ClaimValue == tenantStr) + .Where(x => x.UserId == userId) + .Where(x => x.ClaimType == "tenants") + .ExecuteCommandAsync(); + } } \ No newline at end of file diff --git a/Src/Dlhis.Sys/Program.cs b/Src/Dlhis.Sys/Program.cs index b01d30b3..e883ec6b 100644 --- a/Src/Dlhis.Sys/Program.cs +++ b/Src/Dlhis.Sys/Program.cs @@ -1,4 +1,5 @@ using Kurisu.AspNetCore.Startup; +using Kurisu.AspNetCore.Utils.Extensions; using Microsoft.IdentityModel.Logging; namespace Dlhis.Sys; @@ -17,4 +18,10 @@ public class Startup : DefaultStartup { IdentityModelEventSource.ShowPII = true; } + + public override void ConfigureServices(IServiceCollection services) + { + base.ConfigureServices(services); + services.AddRedis(); + } } \ No newline at end of file diff --git a/Src/Dlhis.Sys/appsettings.json b/Src/Dlhis.Sys/appsettings.json index 0c250034..6a085be9 100644 --- a/Src/Dlhis.Sys/appsettings.json +++ b/Src/Dlhis.Sys/appsettings.json @@ -18,6 +18,9 @@ "SlowSqlTime": 1, "EnableSqlLog": false }, + "RedisOptions": { + "ConnectionString": "192.168.199.150:30115,defaultDatabase=1,password=dlhis123" + }, "SwaggerOptions": { "Enable": true, "Authority": "http://identity.oauth.svc.cluster.local",