Merge branch 'Test_IRC_Net8' of https://gitea.frp.extimaging.com/XCKJ/irc-netcore-api into Test_IRC_Net8
continuous-integration/drone/push Build is passing Details

Uat_IRC_Net8
he 2025-01-16 15:06:52 +08:00
commit 77798e929e
7 changed files with 123 additions and 278 deletions

View File

@ -106,195 +106,6 @@ namespace IRaCIS.Api.Controllers
/// <summary> 系统用户登录接口[New] </summary>
[HttpPost, Route("user/login")]
[AllowAnonymous]
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
[FromServices] IFusionCache _fusionCache,
[FromServices] IUserService _userService,
[FromServices] ITokenService _tokenService,
[FromServices] IReadingImageTaskService readingImageTaskService,
[FromServices] IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig,
[FromServices] IMapper _mapper,
[FromServices] IMailVerificationService _mailVerificationService)
{
var emailConfig = _emailConfig.CurrentValue;
var companyInfo = new SystemEmailSendConfigView() { CompanyName = emailConfig.CompanyName, CompanyNameCN = emailConfig.CompanyNameCN, CompanyShortName = emailConfig.CompanyShortName, CompanyShortNameCN = emailConfig.CompanyShortNameCN };
//MFA 邮箱验证 前端传递用户Id 和MFACode
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
{
Guid userId = (Guid)loginUser.UserId;
//验证MFA 编码是否有问题 ,前端要拆开,自己调用验证的逻辑
//await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode);
//var loginUser = await _userRoleRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo<UserBasicInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
var basicInfo = await _userService.GetUserBasicInfo(userId, loginUser.Password);
var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo };
loginReturn.JWTStr = _tokenService.GetToken(new UserTokenInfo() { IdentityUserId = basicInfo.IdentityUserId });
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
var option = new CookieOptions
{
Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
Secure = false // 确保 cookie 只能通过 HTTPS 访问
};
HttpContext.Response.Cookies.Append("access_token", loginReturn.JWTStr, option);
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(userId);
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
loginReturn.CompanyInfo = companyInfo;
return ResponseOutput.Ok(loginReturn);
}
else
{
var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
if (returnModel.IsSuccess)
{
#region GRPC 调用鉴权中心因为服务器IIS问题 http/2 故而没法使用
////重试策略
//var defaultMethodConfig = new MethodConfig
//{
// Names = { MethodName.Default },
// RetryPolicy = new RetryPolicy
// {
// MaxAttempts = 3,
// InitialBackoff = TimeSpan.FromSeconds(1),
// MaxBackoff = TimeSpan.FromSeconds(5),
// BackoffMultiplier = 1.5,
// RetryableStatusCodes = { Grpc.Core.StatusCode.Unavailable }
// }
//};
//#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
//var httpHandler = new HttpClientHandler();
//// Return `true` to allow certificates that are untrusted/invalid
//httpHandler.ServerCertificateCustomValidationCallback =
// HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
//////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
//AppContext.SetSwitch(
// "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
//#endregion
//var grpcAdress = configuration.GetValue<string>("GrpcAddress");
////var grpcAdress = "http://localhost:7200";
//var channel = GrpcChannel.ForAddress(grpcAdress, new GrpcChannelOptions
//{
// HttpHandler = httpHandler,
// ServiceConfig = new ServiceConfig { MethodConfigs = { defaultMethodConfig } }
//});
////var channel = GrpcChannel.ForAddress(grpcAdress);
//var grpcClient = new TokenGrpcService.TokenGrpcServiceClient(channel);
//var userInfo = returnModel.Data.BasicInfo;
//var tokenResponse = grpcClient.GetUserToken(new GetTokenReuqest()
//{
// Id = userInfo.Id.ToString(),
// ReviewerCode = userInfo.ReviewerCode,
// IsAdmin = userInfo.IsAdmin,
// RealName = userInfo.RealName,
// UserTypeEnumInt = (int)userInfo.UserTypeEnum,
// UserTypeShortName = userInfo.UserTypeShortName,
// UserName = userInfo.UserName
//});
//returnModel.Data.JWTStr = tokenResponse.Token;
#endregion
var userId = returnModel.Data.BasicInfo.IdentityUserId;
if (_verifyConfig.CurrentValue.OpenLoginMFA)
{
//MFA 发送邮件
returnModel.Data.IsMFA = true;
var email = returnModel.Data.BasicInfo.EMail;
var hiddenEmail = IRCEmailPasswordHelper.MaskEmail(email);
returnModel.Data.BasicInfo.EMail = hiddenEmail;
//修改密码
if (returnModel.Data.BasicInfo.IsFirstAdd || returnModel.Data.BasicInfo.LoginState == 1)
{
returnModel.Data.JWTStr = _tokenService.GetToken(_mapper.Map<UserTokenInfo>(returnModel.Data.BasicInfo));
}
else
{
//正常登录才发送邮件
await _userService.SendMFAEmail(new Core.Application.ViewModel.SendMfaCommand() { IdentityUserId= userId });
}
}
else
{
returnModel.Data.JWTStr = _tokenService.GetToken(_mapper.Map<UserTokenInfo>(returnModel.Data.BasicInfo));
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
var option = new CookieOptions
{
Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
Secure = false // 确保 cookie 只能通过 HTTPS 访问
};
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.IdentityUserId);
await _fusionCache.SetAsync(CacheKeys.UserAutoLoginOut(userId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
}
}
returnModel.Data.CompanyInfo = companyInfo;
return returnModel;
}
}
[AllowAnonymous] [AllowAnonymous]
[HttpGet, Route("user/getPublicKey")] [HttpGet, Route("user/getPublicKey")]
public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption) public IResponseOutput GetPublicKey([FromServices] IOptionsMonitor<IRCEncreptOption> _IRCEncreptOption)

View File

@ -34,9 +34,6 @@
<param name="doctorId"></param> <param name="doctorId"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.Login(IRaCIS.Application.Contracts.UserLoginDTO,ZiggyCreatures.Caching.Fusion.IFusionCache,IRaCIS.Core.Application.Service.IUserService,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},AutoMapper.IMapper,IRaCIS.Core.Application.Service.IMailVerificationService)">
<summary> 系统用户登录接口[New] </summary>
</member>
<member name="M:IRaCIS.Api.Controllers.ExtraController.OAuthCallBack(System.String,System.String)"> <member name="M:IRaCIS.Api.Controllers.ExtraController.OAuthCallBack(System.String,System.String)">
<summary> <summary>
回调到前端,前端调用后端的接口 回调到前端,前端调用后端的接口

View File

@ -2288,14 +2288,14 @@
<param name="password"></param> <param name="password"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.UserService.GetUserLoginRoleList(IRaCIS.Application.Contracts.IRCLoginDto,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig},IRaCIS.Core.Application.Contracts.IReadingImageTaskService)"> <member name="M:IRaCIS.Core.Application.Service.UserService.GetUserLoginRoleList(IRaCIS.Application.Contracts.IRCLoginDto,IRaCIS.Core.Application.Auth.ITokenService,Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.SystemEmailSendConfig})">
<summary> <summary>
账号验证,获取账号角色信息 获取临时token 账号验证,获取账号角色信息 获取临时token
</summary> </summary>
<returns></returns> <returns></returns>
<exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception> <exception cref="T:IRaCIS.Core.Infrastructure.BusinessValidationFailedException"></exception>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.UserService.LoginSelectUserRole(System.Guid,IRaCIS.Core.Application.Auth.ITokenService)"> <member name="M:IRaCIS.Core.Application.Service.UserService.LoginSelectUserRole(System.Guid,IRaCIS.Core.Application.Auth.ITokenService,IRaCIS.Core.Application.Contracts.IReadingImageTaskService)">
<summary> <summary>
验证密码成功后选定角色然后获取当前角色的Token 验证密码成功后选定角色然后获取当前角色的Token
</summary> </summary>
@ -12047,7 +12047,7 @@
<param name="inDto"></param> <param name="inDto"></param>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCustomTag},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)"> <member name="M:IRaCIS.Core.Application.Service.ReadingImageTaskService.#ctor(IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudy},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.VisitTask},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Trial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.UserLog},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingOncologyTaskInfo},IRaCIS.Core.Application.Service.IVisitTaskHelpeService,IRaCIS.Core.Application.Service.IVisitTaskService,IRaCIS.Core.Application.Contracts.IReadingClinicalDataService,IRaCIS.Core.Application.Service.IReadingCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.SubjectVisit},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.Subject},Microsoft.Extensions.Options.IOptionsMonitor{IRaCIS.Core.Domain.Share.ServiceVerifyConfigOption},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingGlobalTaskInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCriterionPage},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskRelation},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingJudgeInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadModule},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.DicomInstance},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.OrganInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TrialDocument},IRaCIS.Core.Application.Service.ReadingCalculate.Interface.ILuganoCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingCustomTag},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionMark},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTrialCriterionDictionary},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableAnswerRowInfo},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTableQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingTaskQuestionAnswer},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionCriterionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionSystem},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.NoneDicomStudyFile},IRaCIS.Core.Application.Service.IGeneralCalculateService,IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.ReadingQuestionTrial},IRaCIS.Core.Infra.EFCore.IRepository{IRaCIS.Core.Domain.Models.TaskStudy},IRaCIS.Core.Application.Service.ImageAndDoc.IDownloadAndUploadService,IRaCIS.Core.Application.Interfaces.ITrialEmailNoticeConfigService,AutoMapper.IMapper,IRaCIS.Core.Domain.Share.IUserInfo,Microsoft.Extensions.Localization.IStringLocalizer,ZiggyCreatures.Caching.Fusion.IFusionCache)">
<summary> <summary>
IR影像阅片 IR影像阅片
</summary> </summary>

View File

@ -2224,12 +2224,6 @@ namespace IRaCIS.Core.Application.Service.Common
if (inQuery.ReadingExportType == ExportResult.DetailedTableOfAdjudicationResults) if (inQuery.ReadingExportType == ExportResult.DetailedTableOfAdjudicationResults)
{ {
//R1 R2 两个人的访视都阅片完成了才可以,去除只有一个人阅片完成的访视
//找到只有一个人阅片的受试者 和访视
var exceptVisit = list.GroupBy(t => new { t.SubjectCode, t.TaskName }).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList();
list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList();
//裁判明表 //裁判明表
export_Template = StaticData.Export.CommonJudgeReadingDetail_Export; export_Template = StaticData.Export.CommonJudgeReadingDetail_Export;
} }
@ -2704,12 +2698,23 @@ namespace IRaCIS.Core.Application.Service.Common
#region 最终导出参数处理 #region 最终导出参数处理
if (inQuery.ReadingExportType == ExportResult.DetailedTableOfAdjudicationResults)
{
//R1 R2 两个人的访视都阅片完成了才可以,去除只有一个人阅片完成的访视
//找到只有一个人阅片的受试者 和访视
var exceptVisit = list.Where(t => t.ReadingCategory == ReadingCategory.Visit)
.GroupBy(t => new { t.SubjectCode, t.TaskName}).Where(g => g.Count() == 1).Select(g => new { g.Key.SubjectCode, g.Key.TaskName }).ToList();
list = list.Where(t => !exceptVisit.Any(ev => ev.SubjectCode == t.SubjectCode && ev.TaskName == t.TaskName)).ToList();
}
list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList(); list = list.OrderBy(t => t.SubjectCode).ThenBy(t => t.ArmEnum).ThenBy(t => t.VisitTaskNum).ToList();
//处理裁判标记 //处理裁判标记
list = DealJudgeMark(criterion.ArbitrationRule, criterion.IsGlobalReading, list); list = DealJudgeMark(criterion.ArbitrationRule, criterion.IsGlobalReading, list);
//裁判阅片明细表
if (export_Template == StaticData.Export.CommonJudgeReadingDetail_Export) if (export_Template == StaticData.Export.CommonJudgeReadingDetail_Export)
{ {
//裁判产生标记为空的数据过滤掉 //裁判产生标记为空的数据过滤掉

View File

@ -968,8 +968,8 @@ namespace IRaCIS.Core.Application.Service
[HttpPost] [HttpPost]
public async Task<IResponseOutput<IRCLoginReturnDTO>> GetUserLoginRoleList(IRCLoginDto loginDto, public async Task<IResponseOutput<IRCLoginReturnDTO>> GetUserLoginRoleList(IRCLoginDto loginDto,
[FromServices] ITokenService _tokenService, [FromServices] ITokenService _tokenService,
[FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig, [FromServices] IOptionsMonitor<SystemEmailSendConfig> _emailConfig
[FromServices] IReadingImageTaskService readingImageTaskService) )
{ {
var userName = loginDto.UserName; var userName = loginDto.UserName;
@ -1012,26 +1012,17 @@ namespace IRaCIS.Core.Application.Service
var loginUser = await _identityUserRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo<UserBasicInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync(); var loginUser = await _identityUserRepository.Where(u => u.UserName.Equals(userName) && u.Password == password).ProjectTo<UserBasicInfo>(_mapper.ConfigurationProvider).FirstOrDefaultAsync();
if (loginUser == null) var existUserLoginInfo = await _identityUserRepository.Where(u => u.UserName == userName).Select(t => new { t.LastLoginIP, t.LastChangePassWordTime, t.Id }).FirstOrDefaultAsync();
var isExistAccount = existUserLoginInfo != null;
var isLoginUncommonly = false;
#region //登录用户是系统用户的时候,就要要记录异地登录
//账号在系统存在
if (isExistAccount || loginUser != null)
{ {
//错误次数累加
failCount++;
await _fusionCache.SetAsync(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes));
var errorPwdUserId = await _identityUserRepository.Where(u => u.UserName == userName).Select(t => t.Id).FirstOrDefaultAsync();
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionUserName = userName, LoginPassword = password, OptType = UserOptType.AccountOrPasswordError }, true);
return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new IRCLoginReturnDTO());
}
//登录用户是系统用户的时候,就要要记录异地登录
#region 处理用户状态
var ipinfo = _searcher.Search(_userInfo.IP); var ipinfo = _searcher.Search(_userInfo.IP);
var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3)); var iPRegion = string.Join('|', ipinfo.Split('|').TakeLast(3));
@ -1042,25 +1033,62 @@ namespace IRaCIS.Core.Application.Service
return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts); return parts.Length >= 3 ? parts[0] + parts[1] : string.Join("", parts);
} }
if (loginUser.LastLoginIP != string.Empty) if (existUserLoginInfo.LastLoginIP != string.Empty)
{ {
// 与上一次区域不一致 // 与上一次区域不一致
if (SplitAndConcatenate(loginUser.LastLoginIP) != SplitAndConcatenate(iPRegion)) if (SplitAndConcatenate(existUserLoginInfo.LastLoginIP) != SplitAndConcatenate(iPRegion))
{ {
isLoginUncommonly = true;
//设置上次登录的IP
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == existUserLoginInfo.Id, x => new IdentityUser()
{
LastLoginIP = iPRegion,
LastLoginTime = DateTime.Now
});
if (loginUser != null)
{
//异地登录
loginUser.LoginState = 2; loginUser.LoginState = 2;
}
}
//超过90天没修改密码 //超过90天没修改密码
if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value) if (_verifyConfig.CurrentValue.IsNeedChangePassWord && loginUser.LastChangePassWordTime != null && DateTime.Now.AddDays(-_verifyConfig.CurrentValue.ChangePassWordDays) > loginUser.LastChangePassWordTime.Value)
{ {
loginUser.NeedChangePassWord = true; loginUser.NeedChangePassWord = true;
} }
}
}
}
}
#endregion #endregion
if (loginUser == null)
{
//错误次数累加
failCount++;
await _fusionCache.SetAsync(cacheKey, failCount, TimeSpan.FromMinutes(lockoutMinutes));
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionUserName = userName, LoginPassword = password, OptType = UserOptType.AccountOrPasswordError, IsLoginUncommonly = isLoginUncommonly }, true);
return ResponseOutput.NotOk(_localizer["User_CheckNameOrPw"], new IRCLoginReturnDTO());
}
if (loginUser.Status == 0) if (loginUser.Status == 0)
{ {
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = userName, OptType = UserOptType.LoginLockedAccount, IsLoginUncommonly = (loginUser.LoginState == 2) }, true); await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, ActionUserName = userName, OptType = UserOptType.LoginLockedAccount, IsLoginUncommonly = isLoginUncommonly }, true);
//---该用户已经被禁用。 //---该用户已经被禁用。
return ResponseOutput.NotOk(_localizer["User_Disabled"], new IRCLoginReturnDTO()); return ResponseOutput.NotOk(_localizer["User_Disabled"], new IRCLoginReturnDTO());
@ -1070,7 +1098,7 @@ namespace IRaCIS.Core.Application.Service
await _fusionCache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes)); await _fusionCache.SetAsync(cacheKey, 0, TimeSpan.FromMinutes(lockoutMinutes));
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, OptType = UserOptType.Login, IsLoginUncommonly = (loginUser.LoginState == 2) }, true); await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = loginUser.IdentityUserId, OptType = UserOptType.Login, IsLoginUncommonly = isLoginUncommonly }, true);
userLoginReturnModel.BasicInfo = loginUser; userLoginReturnModel.BasicInfo = loginUser;
@ -1084,12 +1112,7 @@ namespace IRaCIS.Core.Application.Service
} }
await _identityUserRepository.BatchUpdateNoTrackingAsync(x => x.Id == loginUser.IdentityUserId, x => new IdentityUser()
{
LastLoginIP = iPRegion,
LastLoginTime = DateTime.Now
});
//返回临时token //返回临时token
userLoginReturnModel.JWTStr = _tokenService.GetToken(new UserTokenInfo() { IdentityUserId = loginUser.IdentityUserId, UserName = userName }); userLoginReturnModel.JWTStr = _tokenService.GetToken(new UserTokenInfo() { IdentityUserId = loginUser.IdentityUserId, UserName = userName });
@ -1112,7 +1135,7 @@ namespace IRaCIS.Core.Application.Service
userLoginReturnModel.BasicInfo.EMail = hiddenEmail; userLoginReturnModel.BasicInfo.EMail = hiddenEmail;
//修改密码 || 90天修改密码再mfa 之前 //修改密码 || 90天修改密码再mfa 之前
if (userLoginReturnModel.BasicInfo.IsFirstAdd || userLoginReturnModel.BasicInfo.LoginState == 1) if (userLoginReturnModel.BasicInfo.IsFirstAdd || userLoginReturnModel.BasicInfo.NeedChangePassWord)
{ {
//userLoginReturnModel.JWTStr = _tokenService.GetToken(userLoginReturnModel.BasicInfo); //userLoginReturnModel.JWTStr = _tokenService.GetToken(userLoginReturnModel.BasicInfo);
} }
@ -1126,8 +1149,6 @@ namespace IRaCIS.Core.Application.Service
} }
else else
{ {
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(userLoginReturnModel.BasicInfo.IdentityUserId);
await _fusionCache.SetAsync(CacheKeys.UserToken(identityUserId), userLoginReturnModel.JWTStr, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.UserToken(identityUserId), userLoginReturnModel.JWTStr, TimeSpan.FromDays(7));
@ -1149,7 +1170,7 @@ namespace IRaCIS.Core.Application.Service
/// <returns></returns> /// <returns></returns>
/// <exception cref="BusinessValidationFailedException"></exception> /// <exception cref="BusinessValidationFailedException"></exception>
[HttpGet] [HttpGet]
public async Task<string> LoginSelectUserRole(Guid userRoleId, [FromServices] ITokenService _tokenService) public async Task<string> LoginSelectUserRole(Guid userRoleId, [FromServices] ITokenService _tokenService, [FromServices] IReadingImageTaskService readingImageTaskService)
{ {
var identityUserId = _userInfo.IdentityUserId; var identityUserId = _userInfo.IdentityUserId;
@ -1173,6 +1194,8 @@ namespace IRaCIS.Core.Application.Service
{ {
var jwt = _tokenService.GetToken(userTokenInfo); var jwt = _tokenService.GetToken(userTokenInfo);
// 验证阅片休息时间
await readingImageTaskService.ResetReadingRestTime(userTokenInfo.UserRoleId);
await _fusionCache.SetAsync(CacheKeys.UserToken(userTokenInfo.IdentityUserId), jwt, TimeSpan.FromDays(7)); await _fusionCache.SetAsync(CacheKeys.UserToken(userTokenInfo.IdentityUserId), jwt, TimeSpan.FromDays(7));

View File

@ -4,6 +4,7 @@ using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.Helper;
using IRaCIS.Core.Application.Interfaces; using IRaCIS.Core.Application.Interfaces;
using IRaCIS.Core.Application.Service.ImageAndDoc; using IRaCIS.Core.Application.Service.ImageAndDoc;
using IRaCIS.Core.Application.Service.OAuth;
using IRaCIS.Core.Application.Service.Reading.Dto; using IRaCIS.Core.Application.Service.Reading.Dto;
using IRaCIS.Core.Application.Service.ReadingCalculate.Interface; using IRaCIS.Core.Application.Service.ReadingCalculate.Interface;
using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Application.ViewModel;
@ -31,6 +32,7 @@ namespace IRaCIS.Core.Application.Service
IRepository<NoneDicomStudy> _noneDicomStudyRepository, IRepository<NoneDicomStudy> _noneDicomStudyRepository,
IRepository<VisitTask> _visitTaskRepository, IRepository<VisitTask> _visitTaskRepository,
IRepository<Trial> _trialRepository, IRepository<Trial> _trialRepository,
IRepository<UserLog> _userLogRepository,
IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository, IRepository<ReadingTableQuestionAnswer> _readingTableQuestionAnswerRepository,
IRepository<ReadingOncologyTaskInfo> _readingOncologyTaskInfoRepository, IRepository<ReadingOncologyTaskInfo> _readingOncologyTaskInfoRepository,
IVisitTaskHelpeService _visitTaskHelpeService, IVisitTaskHelpeService _visitTaskHelpeService,
@ -3273,31 +3275,36 @@ namespace IRaCIS.Core.Application.Service
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public async Task<bool> ResetReadingRestTime(Guid? userID) public async Task<bool> ResetReadingRestTime(Guid? userRoleId)
{ {
if (userID == null) var roleId = (userRoleId != null && userRoleId != Guid.Empty) ? (Guid) userRoleId : _userInfo.UserRoleId;
{
userID = _userInfo.UserRoleId;
}
//int readingMinute = 120; // 为60整数 //int readingMinute = 120; // 为60整数
int restMinute = 10; // int restMinute = 10; //
var startReadingTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId)); var startReadingTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartReadingTimeKey(roleId));
var startRestTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartRestTime(_userInfo.UserRoleId)); var startRestTime = await _fusionCache.GetOrDefaultAsync<string>(CacheKeys.StartRestTime(roleId));
if (startRestTime != null) if (startRestTime != null)
{ {
var cacheStartRestTime = DateTime.Parse(startRestTime!.ToString()); var cacheStartRestTime = DateTime.Parse(startRestTime!.ToString());
int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes; int timespanMin = (DateTime.Now - cacheStartRestTime).Minutes;
if (timespanMin > restMinute) if (timespanMin > restMinute)
{ {
await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(_userInfo.UserRoleId)); await _fusionCache.RemoveAsync(CacheKeys.StartRestTime(roleId));
} }
} }
else if (startReadingTime != null) else if (startReadingTime != null)
{ {
await _fusionCache.SetAsync<string>(CacheKeys.StartReadingTimeKey(_userInfo.UserRoleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48)); await _fusionCache.SetAsync<string>(CacheKeys.StartReadingTimeKey(roleId), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromHours(48));
} }
//前端屏幕解锁才调用
if (userRoleId == null)
{
await _userLogRepository.AddAsync(new UserLog() { IP = _userInfo.IP, ActionIdentityUserId = _userInfo.IdentityUserId, OptType = UserOptType.WebUnlock }, true);
}
return true; return true;
} }

View File

@ -50,7 +50,9 @@ public enum UserOptType
TempLockLogin = 13, TempLockLogin = 13,
AddUser = 14 AddUser = 14,
WebUnlock=16
} }
[Description("影像下载打包状态")] [Description("影像下载打包状态")]