@@ -30,6 +30,8 @@ using IRaCIS.Core.Application.Helper;
|
||||
using Microsoft.Extensions.Options;
|
||||
using IRaCIS.Core.Application.Contracts;
|
||||
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
|
||||
using DocumentFormat.OpenXml.Spreadsheet;
|
||||
using AutoMapper.QueryableExtensions;
|
||||
|
||||
namespace IRaCIS.Api.Controllers
|
||||
{
|
||||
@@ -53,8 +55,8 @@ namespace IRaCIS.Api.Controllers
|
||||
/// <param name="doctorId"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet, Route("doctor/getDetail/{doctorId:guid}")]
|
||||
|
||||
public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
|
||||
|
||||
public async Task<IResponseOutput<DoctorDetailDTO>> GetDoctorDetail([FromServices] IAttachmentService attachmentService, [FromServices] IDoctorService _doctorService,
|
||||
[FromServices] IEducationService _educationService, [FromServices] ITrialExperienceService _trialExperienceService,
|
||||
|
||||
[FromServices] IResearchPublicationService _researchPublicationService, [FromServices] IVacationService _vacationService, Guid doctorId)
|
||||
@@ -66,7 +68,7 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var doctorDetail = new DoctorDetailDTO
|
||||
{
|
||||
AuditView =await _doctorService.GetAuditState(doctorId),
|
||||
AuditView = await _doctorService.GetAuditState(doctorId),
|
||||
BasicInfoView = await _doctorService.GetBasicInfo(doctorId),
|
||||
EmploymentView = await _doctorService.GetEmploymentInfo(doctorId),
|
||||
AttachmentList = await attachmentService.GetAttachments(doctorId),
|
||||
@@ -77,7 +79,7 @@ namespace IRaCIS.Api.Controllers
|
||||
TrialExperienceView = await _trialExperienceService.GetTrialExperience(doctorId),
|
||||
ResearchPublicationView = await _researchPublicationService.GetResearchPublication(doctorId),
|
||||
|
||||
SpecialtyView =await _doctorService.GetSpecialtyInfo(doctorId),
|
||||
SpecialtyView = await _doctorService.GetSpecialtyInfo(doctorId),
|
||||
InHoliday = (await _vacationService.OnVacation(doctorId)).IsSuccess,
|
||||
IntoGroupInfo = _doctorService.GetDoctorIntoGroupInfo(doctorId),
|
||||
SowList = sowList,
|
||||
@@ -96,80 +98,30 @@ namespace IRaCIS.Api.Controllers
|
||||
/// <summary> 系统用户登录接口[New] </summary>
|
||||
[HttpPost, Route("user/login")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IResponseOutput<LoginReturnDTO>> Login(UserLoginDTO loginUser, [FromServices] IEasyCachingProvider provider, [FromServices] IUserService _userService,
|
||||
[FromServices] ITokenService _tokenService,
|
||||
|
||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||
[FromServices] IConfiguration configuration)
|
||||
public async Task<IResponseOutput> Login(UserLoginDTO loginUser,
|
||||
[FromServices] IEasyCachingProvider provider,
|
||||
[FromServices] IUserService _userService,
|
||||
[FromServices] ITokenService _tokenService,
|
||||
[FromServices] IReadingImageTaskService readingImageTaskService,
|
||||
IOptionsMonitor<ServiceVerifyConfigOption> _verifyConfig,
|
||||
IMailVerificationService _mailVerificationService)
|
||||
{
|
||||
|
||||
|
||||
var returnModel = await _userService.Login(loginUser.UserName, loginUser.Password);
|
||||
|
||||
if (returnModel.IsSuccess)
|
||||
//MFA 邮箱验证 前端传递用户Id 和MFACode
|
||||
if (loginUser.UserId != null && !string.IsNullOrEmpty(loginUser.MFACode) && _verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
#region GRPC 调用鉴权中心,因为服务器IIS问题 http/2 故而没法使用
|
||||
Guid userId = (Guid)loginUser.UserId;
|
||||
|
||||
////重试策略
|
||||
//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 }
|
||||
// }
|
||||
//};
|
||||
//验证MFA 编码是否有问题
|
||||
|
||||
//#region unable to trust the certificate then the gRPC client can be configured to ignore the invalid certificate
|
||||
await _userService.VerifyMFACodeAsync(userId, loginUser.MFACode);
|
||||
|
||||
//var httpHandler = new HttpClientHandler();
|
||||
//// Return `true` to allow certificates that are untrusted/invalid
|
||||
//httpHandler.ServerCertificateCustomValidationCallback =
|
||||
// HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
|
||||
var basicInfo = await _userService.GetUserBasicInfo(userId);
|
||||
|
||||
var loginReturn = new LoginReturnDTO() { BasicInfo = basicInfo };
|
||||
|
||||
//////这一句是让grpc支持本地 http 如果本地访问部署在服务器上,那么是访问不成功的
|
||||
//AppContext.SetSwitch(
|
||||
// "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
|
||||
loginReturn.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(loginReturn.BasicInfo));
|
||||
|
||||
//#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
|
||||
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
// 创建一个 CookieOptions 对象,用于设置 Cookie 的属性
|
||||
var option = new CookieOptions
|
||||
@@ -180,20 +132,161 @@ namespace IRaCIS.Api.Controllers
|
||||
Secure = false // 确保 cookie 只能通过 HTTPS 访问
|
||||
};
|
||||
|
||||
HttpContext.Response.Cookies.Append("access_token", returnModel.Data.JWTStr, option);
|
||||
HttpContext.Response.Cookies.Append("access_token", loginReturn.JWTStr, option);
|
||||
|
||||
// 验证阅片休息时间
|
||||
await readingImageTaskService.ResetReadingRestTime(userId);
|
||||
|
||||
await provider.SetAsync(userId.ToString(), loginReturn.JWTStr, TimeSpan.FromDays(7));
|
||||
|
||||
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||
|
||||
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.Id;
|
||||
|
||||
if (_verifyConfig.CurrentValue.OpenLoginMFA)
|
||||
{
|
||||
//发版屏蔽
|
||||
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(returnModel.Data.BasicInfo));
|
||||
|
||||
//MFA 发送邮件
|
||||
|
||||
returnModel.Data.IsMFA = true;
|
||||
|
||||
var email = returnModel.Data.BasicInfo.EMail;
|
||||
|
||||
#region 隐藏Email
|
||||
// 找到 "@" 符号的位置
|
||||
int atIndex = email.IndexOf('@');
|
||||
|
||||
// 替换 "@" 符号前的中间两位为星号
|
||||
string visiblePart = email.Substring(0, atIndex);
|
||||
|
||||
int startIndex = (visiblePart.Length - 2) / 2;
|
||||
|
||||
// 替换中间两位字符为星号
|
||||
string hiddenPartBeforeAt = visiblePart.Substring(0, startIndex) + "**" + visiblePart.Substring(startIndex + 2);
|
||||
|
||||
string afterAt = email.Substring(atIndex + 1);
|
||||
|
||||
// 组合隐藏和可见部分
|
||||
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
|
||||
#endregion
|
||||
|
||||
returnModel.Data.BasicInfo.EMail = hiddenEmail;
|
||||
|
||||
await _userService.SendMFAEmail(userId);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
returnModel.Data.JWTStr = _tokenService.GetToken(IRaCISClaims.Create(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.Id);
|
||||
|
||||
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||
|
||||
await provider.SetAsync($"{userId.ToString()}_Online", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), TimeSpan.FromMinutes(_verifyConfig.CurrentValue.AutoLoginOutMinutes));
|
||||
}
|
||||
|
||||
}
|
||||
return returnModel;
|
||||
|
||||
}
|
||||
|
||||
var userId = returnModel.Data.BasicInfo.Id.ToString();
|
||||
//provider.Set(userId, userId, TimeSpan.FromMinutes(AppSettings.LoginExpiredTimeSpan));
|
||||
// 验证阅片休息时间
|
||||
await readingImageTaskService.ResetReadingRestTime(returnModel.Data.BasicInfo.Id);
|
||||
await provider.SetAsync(userId.ToString(), returnModel.Data.JWTStr, TimeSpan.FromDays(7));
|
||||
return returnModel;
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[HttpGet, Route("imageShare/ShareImage")]
|
||||
[AllowAnonymous]
|
||||
public IResponseOutput ShareImage([FromServices] ITokenService _tokenService)
|
||||
@@ -223,7 +316,7 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var ossOptions = serviceOption.AliyunOSS;
|
||||
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO ,AliyunOSS= serviceOption.AliyunOSS,AWS=serviceOption.AWS });
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AliyunOSS = serviceOption.AliyunOSS, AWS = serviceOption.AWS });
|
||||
|
||||
#region 临时token 屏蔽
|
||||
//IClientProfile profile = DefaultProfile.GetProfile(ossOptions.RegionId, ossOptions.AccessKeyId, ossOptions.AccessKeySecret);
|
||||
@@ -264,19 +357,19 @@ namespace IRaCIS.Api.Controllers
|
||||
#endregion
|
||||
|
||||
}
|
||||
else if(Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
|
||||
else if (Enum.TryParse<ObjectStoreUse>(serviceOption.ObjectStoreUse, out var parsedValue) && parsedValue == ObjectStoreUse.MinIO)
|
||||
{
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse=serviceOption.ObjectStoreUse,MinIO=serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||
}
|
||||
else
|
||||
{
|
||||
return ResponseOutput.Ok(new ObjectStoreDTO() { ObjectStoreUse = serviceOption.ObjectStoreUse, MinIO = serviceOption.MinIO, AWS = serviceOption.AWS });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
[HttpGet("user/GenerateSTS")]
|
||||
public IResponseOutput GenerateSTS([FromServices]IOptionsMonitor<AliyunOSSOptions> options )
|
||||
[HttpGet("user/GenerateSTS")]
|
||||
public IResponseOutput GenerateSTS([FromServices] IOptionsMonitor<AliyunOSSOptions> options)
|
||||
{
|
||||
var ossOptions = options.CurrentValue;
|
||||
|
||||
@@ -304,9 +397,9 @@ namespace IRaCIS.Api.Controllers
|
||||
SecurityToken = response.Credentials.SecurityToken,
|
||||
Expiration = response.Credentials.Expiration,
|
||||
|
||||
Region = ossOptions.region ,
|
||||
BucketName = ossOptions.bucketName ,
|
||||
ViewEndpoint = ossOptions.viewEndpoint ,
|
||||
Region = ossOptions.region,
|
||||
BucketName = ossOptions.bucketName,
|
||||
ViewEndpoint = ossOptions.viewEndpoint,
|
||||
|
||||
};
|
||||
|
||||
@@ -318,12 +411,12 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
[HttpGet("User/UserRedirect")]
|
||||
[AllowAnonymous]
|
||||
public async Task<IActionResult> UserRedirect([FromServices] IRepository<User> _userRepository, string url ,[FromServices]ILogger<ExtraController> _logger)
|
||||
public async Task<IActionResult> UserRedirect([FromServices] IRepository<User> _userRepository, string url, [FromServices] ILogger<ExtraController> _logger)
|
||||
{
|
||||
|
||||
var decodeUrl = System.Web.HttpUtility.UrlDecode(url);
|
||||
|
||||
var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length , 36) ;
|
||||
var userId = decodeUrl.Substring(decodeUrl.IndexOf("UserId=") + "UserId=".Length, 36);
|
||||
|
||||
var token = decodeUrl.Substring(decodeUrl.IndexOf("access_token=") + "access_token=".Length);
|
||||
|
||||
@@ -331,12 +424,12 @@ namespace IRaCIS.Api.Controllers
|
||||
|
||||
var domainStrList = decodeUrl.Split("/").ToList().Take(3).ToList();
|
||||
|
||||
var errorUrl = domainStrList[0]+"//"+ domainStrList[2]+ "/error";
|
||||
var errorUrl = domainStrList[0] + "//" + domainStrList[2] + "/error";
|
||||
|
||||
|
||||
if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
|
||||
if (!await _userRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
|
||||
{
|
||||
decodeUrl = errorUrl+ $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang=="zh"? "您的初始化链接已过期": "Error!The initialization link has expired. Return")} ";
|
||||
decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(lang == "zh" ? "您的初始化链接已过期" : "Error!The initialization link has expired. Return")} ";
|
||||
}
|
||||
|
||||
return Redirect(decodeUrl);
|
||||
|
||||
Reference in New Issue
Block a user