From 083090ca05cda4ac268aebcce5a1ecb04f9dc4dd Mon Sep 17 00:00:00 2001 From: hang <872297557@qq.com> Date: Fri, 15 Aug 2025 14:35:03 +0800 Subject: [PATCH] =?UTF-8?q?swagger=20bug=20=E6=A0=B8=E5=AF=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- IRaCIS.Core.API/IRaCIS.Core.API.xml | 39 ++++ .../IRaCIS.Core.Application.xml | 15 +- .../Service/Management/UserService.cs | 207 ++++++++---------- 3 files changed, 142 insertions(+), 119 deletions(-) diff --git a/IRaCIS.Core.API/IRaCIS.Core.API.xml b/IRaCIS.Core.API/IRaCIS.Core.API.xml index 0c6a9ce27..7ef85e91f 100644 --- a/IRaCIS.Core.API/IRaCIS.Core.API.xml +++ b/IRaCIS.Core.API/IRaCIS.Core.API.xml @@ -11,6 +11,45 @@ + + + 医生基本信息 、工作信息 专业信息、审核状态 + + + + + 医生基本信息 、工作信息 专业信息、审核状态 + + + + + 获取医生详情 + + + + + + + + + + + + + 回调到前端,前端调用后端的接口 + 参考链接:https://www.ruanyifeng.com/blog/2019/04/oauth-grant-types.html + 后端通过这个code ,带上客户端信息,和授权类型 可以向单点登录提供商,获取厂商token + + 但是单点登录提供商提供的token 和我们系统的token 是有区别的,我们的token里面有我们业务系统的UserId,涉及到很多业务操作,所以在此出现了两种方案 + 1、前端使用厂商的Token。 后端通过code 获取厂商的Token 返回前端的同时返回我们系统的UserId,前段在http 请求头加上一个自定义参数,带上UserId 后端取用户Id的地方变动下, + 但是除了UserId外,后端还有其他信息也是从Token取的,所以在请求头也需要带上,此外后端认证Token的方式也需要变化,改造成本稍大(如果是微服务,做这种处理还是可以的)。 + 2、前端还是使用我们后台自己的Token。后端通过code 获取厂商Token的同时,后端做一个隐藏登录,返回厂商的Token的同时,也返回我们系统的Token。 + (像我们单体,这种方式最简单,我们用单点登录,无非就是不想记多个系统的密码,自动登录而已,其他不支持的项目改造成本也是最低的) + + 回调的厂商类型 比如github, google, 我们用的logto ,不同的厂商回调到前端的地址可以不同的,但是请求后端的接口可以是同一个 + 在第三方平台登录成功后,回调前端的时候会返回一个code + + 添加实验项目-返回新增Id[AUTH] 新记录Id diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index 907b24688..43b70bb67 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -2082,6 +2082,12 @@ + + + 修改密码,当前支持旧密码修改密码 + + + 获取用户列表 @@ -2093,7 +2099,6 @@ 根据用户Id获取用户详细信息[New] - xiuga @@ -2110,7 +2115,7 @@ - + 同济生成账号 @@ -2128,12 +2133,6 @@ - - - 修改密码,当前支持旧密码修改密码 - - - 账号验证,获取账号角色信息 获取临时token diff --git a/IRaCIS.Core.Application/Service/Management/UserService.cs b/IRaCIS.Core.Application/Service/Management/UserService.cs index 4ef340f2d..fff35de2a 100644 --- a/IRaCIS.Core.Application/Service/Management/UserService.cs +++ b/IRaCIS.Core.Application/Service/Management/UserService.cs @@ -1,10 +1,10 @@ -using DocumentFormat.OpenXml.Spreadsheet; -using IP2Region.Net.Abstractions; +using IP2Region.Net.Abstractions; using IRaCIS.Application.Contracts; using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Contracts; using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper.OtherTool; +using IRaCIS.Core.Application.Service.OAuth; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Share; @@ -12,14 +12,13 @@ using IRaCIS.Core.Infrastructure; using MassTransit; using Medallion.Threading; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; -using NPOI.SS.Formula.Functions; +using Org.BouncyCastle.Utilities.Encoders; using Panda.DynamicWebApi.Attributes; using System.Text.RegularExpressions; using ZiggyCreatures.Caching.Fusion; -using IdentityUser = IRaCIS.Core.Domain.Models.IdentityUser; + using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO; namespace IRaCIS.Core.Application.Service @@ -28,6 +27,7 @@ namespace IRaCIS.Core.Application.Service public class UserService(IRepository _userRoleRepository, IMailVerificationService _mailVerificationService, IRepository _verificationCodeRepository, + IRepository _hirHospitalRepository, IRepository _userTrialRepository, IRepository _userLogRepository, IRepository _userPassWordLogRepository, @@ -35,15 +35,13 @@ namespace IRaCIS.Core.Application.Service IRepository _trialRepository, IOptionsMonitor _verifyConfig, IOptionsMonitor systemEmailConfig, - IRepository _hirHospitalRepository, - ITokenService _tokenService, - IRepository _identityUserRepository, + IRepository _identityUserRepository, + IRepository _doctorRepository, ISearcher _searcher, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IFusionCache _fusionCache) : BaseService, IUserService { private SystemEmailSendConfig _systemEmailConfig = systemEmailConfig.CurrentValue; - private async Task VerifyUserNameAsync(Guid? identityUserId, string userName) { if (await _identityUserRepository.WhereIf(identityUserId != null, t => t.Id != identityUserId).AnyAsync(t => t.UserName == userName)) @@ -63,7 +61,7 @@ namespace IRaCIS.Core.Application.Service } - private async Task VerifyUserEmailAsync(Guid? identityUserId, string email) + private async Task VerifyUserEmailAsync(Guid? identityUserId, string email) { if (await _identityUserRepository.WhereIf(identityUserId != null, t => t.Id != identityUserId).AnyAsync(t => t.EMail == email)) { @@ -74,6 +72,8 @@ namespace IRaCIS.Core.Application.Service private async Task VerifyUserPwdAsync(Guid identityUserId, string newPwd, string? oldPwd = null) { + //var dbUser = (await _userRoleRepository.FirstOrDefaultAsync(t => t.Id == userId)).IfNullThrowException(); + if (_verifyConfig.CurrentValue.OpenUserComplexPassword) { if (oldPwd != null && oldPwd == newPwd) @@ -238,8 +238,10 @@ namespace IRaCIS.Core.Application.Service } + + [HttpGet] - public async Task InitSetUserNameAndPwd( string newUserName, string newPWd) + public async Task InitSetUserNameAndPwd(string newUserName, string newPWd) { @@ -284,6 +286,7 @@ namespace IRaCIS.Core.Application.Service [UnitOfWork] public async Task ResetPassword(Guid identityUserId) { + var hospitalInfo = await _fusionCache.GetOrSetAsync(CacheKeys.Hospital, async _ => await CacheHelper.GetHospitalCode(_hirHospitalRepository), TimeSpan.FromDays(7)); @@ -350,7 +353,6 @@ namespace IRaCIS.Core.Application.Service } - //验证码 6位 int verificationCode = new Random().Next(100000, 1000000); @@ -361,7 +363,6 @@ namespace IRaCIS.Core.Application.Service } - /// /// (未登陆) 设置新密码 /// @@ -398,7 +399,52 @@ namespace IRaCIS.Core.Application.Service } + /// + /// 修改密码,当前支持旧密码修改密码 + /// + /// + [HttpPost] + [UnitOfWork] + public async Task ModifyPassword(EditPasswordCommand editPwModel) + { + await VerifyUserPwdAsync(_userInfo.IdentityUserId, editPwModel.NewPassWord, editPwModel.OldPassWord); + + + if (!string.IsNullOrEmpty(editPwModel.NewUserName)) + { + + await VerifyUserNameAsync(_userInfo.IdentityUserId, editPwModel.NewUserName); + + await _identityUserRepository.UpdatePartialFromQueryAsync(t => t.Id == _userInfo.IdentityUserId, u => new IdentityUser() + { + UserName = editPwModel.NewUserName, + }); + + } + + var success = await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == _userInfo.IdentityUserId, u => new IdentityUser() + { + Password = editPwModel.NewPassWord, + LastChangePassWordTime = DateTime.Now, + IsFirstAdd = false + }); + + await _userPassWordLogRepository.AddAsync(new UserPassWordLog() + { + + CreateTime = DateTime.Now, + PassWord = editPwModel.NewPassWord, + IdentityUserId = _userInfo.IdentityUserId, + }); + + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.LoginModifyPassword }, true); + + return ResponseOutput.Result(success); + + + + } @@ -410,8 +456,9 @@ namespace IRaCIS.Core.Application.Service [HttpPost] public async Task> GetUserList(UserListQueryDTO inQuery) { + var userQueryable = _identityUserRepository.Where(x => x.UserRoleList.Any(x => x.UserTypeEnum != UserTypeEnum.SuperAdmin)) - .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName)) + .WhereIf(!string.IsNullOrWhiteSpace(inQuery.UserName), t => t.UserName.Contains(inQuery.UserName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.RealName), t => t.FullName.Contains(inQuery.RealName)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.Phone), t => t.Phone.Contains(inQuery.Phone)) .WhereIf(!string.IsNullOrWhiteSpace(inQuery.OrganizationName), t => t.OrganizationName.Contains(inQuery.OrganizationName)) @@ -422,12 +469,11 @@ namespace IRaCIS.Core.Application.Service .WhereIf(inQuery.EndLastLoginTime != null, t => t.LastLoginTime <= inQuery.EndLastLoginTime) .WhereIf(inQuery.BeginLastChangePassWordTime != null, t => t.LastChangePassWordTime >= inQuery.BeginLastChangePassWordTime) .WhereIf(inQuery.EndLastChangePassWordTime != null, t => t.LastChangePassWordTime <= inQuery.EndLastChangePassWordTime) - .WhereIf(inQuery.UserType != null, t => t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserType && t.IsUserRoleDisabled == false)) + .WhereIf(inQuery.UserType != null, t => t.UserRoleList.Any(t => t.UserTypeId == inQuery.UserType && t.IsUserRoleDisabled==false)) .WhereIf(inQuery.UserState != null, t => t.Status == inQuery.UserState) .WhereIf(inQuery.IsTestUser != null, t => t.IsTestUser == inQuery.IsTestUser) .WhereIf(inQuery.IsZhiZhun != null, t => t.IsZhiZhun == inQuery.IsZhiZhun) - //.WhereIf(_userInfo.UserTypeEnumInt == (int)UserTypeEnum.OA, t => t.UserTypeEnum != UserTypeEnum.Admin) - .ProjectTo(_mapper.ConfigurationProvider); + .ProjectTo(_mapper.ConfigurationProvider); return await userQueryable.ToPagedListAsync(inQuery); @@ -436,11 +482,11 @@ namespace IRaCIS.Core.Application.Service /// /// 根据用户Id获取用户详细信息[New] /// - /// /// xiuga - [HttpGet("{identityUserId:guid}")] + public async Task GetUser(Guid identityUserId) { + identityUserId = identityUserId != Guid.Empty ? identityUserId : _userInfo.IdentityUserId; var user = await _identityUserRepository.Where(t => t.Id == identityUserId).ProjectTo(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); @@ -453,6 +499,9 @@ namespace IRaCIS.Core.Application.Service return user; } + + + /// /// 添加用户 /// @@ -469,12 +518,12 @@ namespace IRaCIS.Core.Application.Service } - await VerifyUserEmailAsync(null, userAddModel.EMail); - - + await VerifyUserEmailAsync(null, userAddModel.EMail); var saveItem = _mapper.Map(userAddModel); + + var @lock = _distributedLockProvider.CreateLock($"UserAccount"); using (await @lock.AcquireAsync()) @@ -490,12 +539,9 @@ namespace IRaCIS.Core.Application.Service // saveItem.OrganizationName = organizationName; //} - // IRCEmailPasswordHelper.GenerateRandomPassword(10) + //saveItem.Password = MD5Helper.Md5(IRCEmailPasswordHelper.GenerateRandomPassword(10)); saveItem.Password = MD5Helper.Md5("123456"); - - - var addRoleList = new List(); foreach (var role in userAddModel.UserRoleList) @@ -527,6 +573,7 @@ namespace IRaCIS.Core.Application.Service } + /// /// 更新用户 /// @@ -536,9 +583,10 @@ namespace IRaCIS.Core.Application.Service { + await VerifyUserNameAsync(model.Id, model.UserName); - await VerifyUserEmailAsync(model.Id, model.EMail); + await VerifyUserEmailAsync(model.Id, model.EMail); //await VerifyUserPhoneAsync(model.Id, model.UserTypeId, model.Phone); @@ -556,6 +604,7 @@ namespace IRaCIS.Core.Application.Service } + _mapper.Map(model, user); //if (user.IsZhiZhun) @@ -600,6 +649,7 @@ namespace IRaCIS.Core.Application.Service } + [HttpPut] public async Task UpdateUserBasicInfo(UserBasicInfoCommand command) { @@ -654,6 +704,7 @@ namespace IRaCIS.Core.Application.Service return ResponseOutput.Ok(); } + public async Task GetUserBasicInfo(Guid userId, string pwd) @@ -662,10 +713,6 @@ namespace IRaCIS.Core.Application.Service return info; } - - - - /// /// 同济生成账号 /// @@ -677,6 +724,7 @@ namespace IRaCIS.Core.Application.Service [HttpGet] public async Task TJUserLoginInfo(string token, [FromServices] IRepository _userTypeRepository, + [FromServices] ITokenService _tokenService, [FromServices] IRepository _hirHospitalRepository) { #region MyRegion @@ -813,7 +861,7 @@ namespace IRaCIS.Core.Application.Service } } - + await _userRoleRepository.SaveChangesAsync(); } @@ -845,6 +893,9 @@ namespace IRaCIS.Core.Application.Service + + + [HttpPost] public async Task> GetUserLogList(UserLogQuery inQuery) { @@ -861,8 +912,8 @@ namespace IRaCIS.Core.Application.Service .WhereIf(inQuery.OptTypeList != null && inQuery.OptTypeList.Count > 0, t => inQuery.OptTypeList.Contains(t.OptType)) .WhereIf(inQuery.BeginDate != null, t => t.CreateTime >= inQuery.BeginDate) .WhereIf(inQuery.EndDate != null, t => t.CreateTime <= inQuery.EndDate) - .WhereIf(inQuery.IsLoginUncommonly != null, t => t.IsLoginUncommonly == inQuery.IsLoginUncommonly) - + .WhereIf(inQuery.IsLoginUncommonly != null , t => t.IsLoginUncommonly== inQuery.IsLoginUncommonly) + .WhereIf(!string.IsNullOrEmpty(inQuery.LoginUserName), t => t.ActionUserName.Contains(inQuery.LoginUserName!)) .WhereIf(!string.IsNullOrEmpty(inQuery.LoginFaildName), t => t.ActionUserName.Contains(inQuery.LoginFaildName!)) .WhereIf(!string.IsNullOrEmpty(inQuery.IP), t => t.IP.Contains(inQuery.IP!)) @@ -889,17 +940,16 @@ namespace IRaCIS.Core.Application.Service [AllowAnonymous] [HttpGet] - public async Task LoginOut(Guid userId) + public async Task LoginOut(Guid identityUserId, Guid userRoleId) { - await _fusionCache.RemoveAsync(CacheKeys.UserToken(_userInfo.UserRoleId)); - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = userId, OptUserId = _userInfo.UserRoleId, OptType = UserOptType.LoginOut }, true); + await _fusionCache.RemoveAsync(CacheKeys.UserToken(identityUserId)); + + var userName = await _userRoleRepository.Where(t => t.Id == userRoleId).Select(t => t.IdentityUser.UserName).FirstOrDefaultAsync(); + + await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = identityUserId, ActionUserName = userName, OptType = UserOptType.LoginOut }, true); return ResponseOutput.Ok(); } - - - #region HIR 修改 - /// /// 验证验证码,没问题就返回用户所有的账户 /// @@ -961,72 +1011,6 @@ namespace IRaCIS.Core.Application.Service return list; } - - [HttpPut("{newCheckCode}")] - public async Task SetNewCheckCode(string newCheckCode) - { - var user = await _userRoleRepository.FirstOrDefaultNoTrackingAsync(t => t.Id == _userInfo.UserRoleId); - - await _userRoleRepository.UpdatePartialFromQueryAsync(t => t.EMail == user.EMail, u => new UserRole() - { - CheckCode = newCheckCode - }); - - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, LoginUserId = _userInfo.UserRoleId, OptUserId = _userInfo.UserRoleId, OptType = UserOptType.ModifyCheckCode }, true); - return ResponseOutput.Ok(); - } - - - /// - /// 修改密码,当前支持旧密码修改密码 - /// - /// - [HttpPost] - [UnitOfWork] - public async Task ModifyPassword(EditPasswordCommand editPwModel) - { - - await VerifyUserPwdAsync(_userInfo.IdentityUserId, editPwModel.NewPassWord, editPwModel.OldPassWord); - - - if (!string.IsNullOrEmpty(editPwModel.NewUserName)) - { - - await VerifyUserNameAsync(_userInfo.IdentityUserId, editPwModel.NewUserName); - - await _identityUserRepository.UpdatePartialFromQueryAsync(t => t.Id == _userInfo.IdentityUserId, u => new IdentityUser() - { - UserName = editPwModel.NewUserName, - }); - - } - - var success = await _identityUserRepository.BatchUpdateNoTrackingAsync(t => t.Id == _userInfo.IdentityUserId, u => new IdentityUser() - { - Password = editPwModel.NewPassWord, - CheckCode = editPwModel.CheckCode, - LastChangePassWordTime = DateTime.Now, - IsFirstAdd = false - }); - - await _userPassWordLogRepository.AddAsync(new UserPassWordLog() - { - - CreateTime = DateTime.Now, - PassWord = editPwModel.NewPassWord, - IdentityUserId = _userInfo.IdentityUserId, - }); - - await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, ActionUserName = _userInfo.UserName, TargetIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.LoginModifyPassword }, true); - - return ResponseOutput.Result(success); - - - - } - - #endregion - #region 多账号修改 /// @@ -1046,7 +1030,7 @@ namespace IRaCIS.Core.Application.Service var password = loginDto.Password; var emailConfig = _emailConfig.CurrentValue; - var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN, SystemShortName = emailConfig.SystemShortName, EmailRegexStr = emailConfig.EmailRegexStr }; + var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN,SystemShortName=emailConfig.SystemShortName ,EmailRegexStr=emailConfig.EmailRegexStr}; int maxFailures = _verifyConfig.CurrentValue.LoginMaxFailCount; @@ -1115,7 +1099,7 @@ namespace IRaCIS.Core.Application.Service //超过90天没修改密码 - if (loginUser != null && _verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) + if (loginUser!= null&&_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) { loginUser.NeedChangePassWord = true; } @@ -1126,7 +1110,7 @@ namespace IRaCIS.Core.Application.Service UserOptType.LoginLockedAccount }; - var actionUserName = loginUser != null ? loginUser.UserName : userName; + var actionUserName= loginUser!= null ? loginUser.UserName : userName; var lastLoginIPRegion = await _userLogRepository.Where(t => t.ActionUserName == actionUserName && userOptTypes.Contains(t.OptType)) .OrderByDescending(t => t.CreateTime).Select(t => t.IPRegion).FirstOrDefaultAsync(); @@ -1146,7 +1130,7 @@ namespace IRaCIS.Core.Application.Service //异地登录 loginUser.LoginState = 2; - + } } } @@ -1207,6 +1191,7 @@ namespace IRaCIS.Core.Application.Service + await _fusionCache.SetAsync(CacheKeys.UserToken(identityUserId), userLoginReturnModel.JWTStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(identityUserId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));