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

IRC_NewDev
he 2024-07-31 10:40:44 +08:00
commit da102dfed2
15 changed files with 191 additions and 66 deletions

View File

@ -32,6 +32,7 @@ using IRaCIS.Core.Application.Contracts;
using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO; using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Spreadsheet;
using AutoMapper.QueryableExtensions; using AutoMapper.QueryableExtensions;
using NetTopologySuite.Algorithm;
namespace IRaCIS.Api.Controllers namespace IRaCIS.Api.Controllers
{ {
@ -108,7 +109,7 @@ namespace IRaCIS.Api.Controllers
{ {
//MFA 邮箱验证 前端传递用户Id 和MFACode //MFA 邮箱验证 前端传递用户Id 和MFACode
if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA) if (loginUser.UserId != null && _verifyConfig.CurrentValue.OpenLoginMFA)
{ {
Guid userId = (Guid)loginUser.UserId; Guid userId = (Guid)loginUser.UserId;
@ -226,23 +227,7 @@ namespace IRaCIS.Api.Controllers
var email = returnModel.Data.BasicInfo.EMail; var email = returnModel.Data.BasicInfo.EMail;
#region 隐藏Email var hiddenEmail = EmailMaskHelper.MaskEmail(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; returnModel.Data.BasicInfo.EMail = hiddenEmail;

View File

@ -71,6 +71,7 @@
</PackageReference> </PackageReference>
<PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" /> <PackageReference Include="Hangfire.AspNetCore" Version="1.8.14" />
<PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" /> <PackageReference Include="Hangfire.Dashboard.BasicAuthorization" Version="1.0.2" />
<PackageReference Include="Hangfire.InMemory" Version="0.10.3" />
<PackageReference Include="Hangfire.SqlServer" Version="1.8.14" /> <PackageReference Include="Hangfire.SqlServer" Version="1.8.14" />
<PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" /> <PackageReference Include="Invio.Extensions.Authentication.JwtBearer" Version="2.0.1" />
<PackageReference Include="LogDashboard" Version="1.4.8" /> <PackageReference Include="LogDashboard" Version="1.4.8" />

View File

@ -28,6 +28,7 @@ using FellowOakDicom.Network;
using IRaCIS.Core.Application.Service.ImageAndDoc; using IRaCIS.Core.Application.Service.ImageAndDoc;
using IP2Region.Net.Abstractions; using IP2Region.Net.Abstractions;
using IP2Region.Net.XDB; using IP2Region.Net.XDB;
using IRaCIS.Core.Application.BusinessFilter;
#region 获取环境变量 #region 获取环境变量
@ -104,11 +105,9 @@ builder.Services.AddControllers(options =>
options.Filters.Add<ModelActionFilter>(); options.Filters.Add<ModelActionFilter>();
options.Filters.Add<ProjectExceptionFilter>(); options.Filters.Add<ProjectExceptionFilter>();
options.Filters.Add<UnitOfWorkFilter>(); options.Filters.Add<UnitOfWorkFilter>();
options.Filters.Add<EncreptApiResultFilter>(10);
options.Filters.Add<LimitUserRequestAuthorization>();
if (_configuration.GetSection("BasicSystemConfig").GetValue<bool>("OpenLoginLimit"))
{
options.Filters.Add<LimitUserRequestAuthorization>();
}
}) })
.AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理 .AddNewtonsoftJsonSetup(builder.Services); // NewtonsoftJson 序列化 处理
@ -117,6 +116,8 @@ builder.Services.AddOptions().Configure<SystemEmailSendConfig>(_configuration.Ge
builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig")); builder.Services.AddOptions().Configure<ServiceVerifyConfigOption>(_configuration.GetSection("BasicSystemConfig"));
builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS")); builder.Services.AddOptions().Configure<AliyunOSSOptions>(_configuration.GetSection("AliyunOSS"));
builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService")); builder.Services.AddOptions().Configure<ObjectStoreServiceOptions>(_configuration.GetSection("ObjectStoreService"));
builder.Services.AddOptions().Configure<EncreptResponseOption>(_configuration.GetSection("EncrypteResponseConfig"));
//动态WebApi + UnifiedApiResultFilter 省掉控制器代码 //动态WebApi + UnifiedApiResultFilter 省掉控制器代码
@ -297,7 +298,7 @@ try
var server = DicomServerFactory.Create<CStoreSCPService>(11112,userState: app.Services); var server = DicomServerFactory.Create<CStoreSCPService>(11112, userState: app.Services);
app.Run(); app.Run();

View File

@ -3,6 +3,7 @@ using Hangfire.SqlServer;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System; using System;
using System.Runtime.InteropServices;
namespace IRaCIS.Core.API namespace IRaCIS.Core.API
{ {
@ -14,19 +15,29 @@ namespace IRaCIS.Core.API
services.AddHangfire(hangFireConfig => services.AddHangfire(hangFireConfig =>
{ {
//本地window 调试 使用内存,服务器部署使用数据库,防止服务器任务调度到本地
//hangFireConfig.UseInMemoryStorage(); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
//指定存储介质
hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
{ {
SchemaName = "dbo", hangFireConfig.UseInMemoryStorage();
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5), }
QueuePollInterval = TimeSpan.Zero, else
UseRecommendedIsolationLevel = true, {
DisableGlobalLocks = true //指定存储介质
}); hangFireConfig.UseSqlServerStorage(hangFireConnStr, new SqlServerStorageOptions()
{
SchemaName = "dbo",
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
});
}
//hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer //hangFireConfig.UseTagsWithSql(); //nuget引入Hangfire.Tags.SqlServer
//.UseHangfireHttpJob(); //.UseHangfireHttpJob();

View File

@ -92,5 +92,12 @@
"DefaultPassword": "123456", "DefaultPassword": "123456",
"DefaultInternalOrganizationName": "ExtImaging", "DefaultInternalOrganizationName": "ExtImaging",
"ImageShareExpireDays": 10 "ImageShareExpireDays": 10
},
"EncrypteResponseConfig": {
"IsEnable": true,
"ApiPathList": [
"/test/get"
]
} }
} }

View File

@ -0,0 +1,71 @@
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.BusinessFilter
{
public class EncreptApiResultFilter : IAsyncResultFilter
{
private readonly IOptionsMonitor<EncreptResponseOption> _encreptResponseMonitor;
public EncreptApiResultFilter(IOptionsMonitor<EncreptResponseOption> encreptResponseMonitor)
{
_encreptResponseMonitor = encreptResponseMonitor;
}
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if(_encreptResponseMonitor.CurrentValue.IsEnable)
{
if (context.Result is ObjectResult objectResult)
{
var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;
var objectValue = objectResult.Value;
if (objectValue is IResponseOutput)
{
var responseOutput = objectValue as IResponseOutput<object>;
var path = context.HttpContext?.Request.Path.Value?.ToLower();
if(!string.IsNullOrEmpty(path) && path.Length>5 && _encreptResponseMonitor.CurrentValue.ApiPathList.Contains(path.ToLower()))
{
if(responseOutput.IsSuccess)
{
responseOutput.Code = ApiResponseCodeEnum.ResultEncrepted;
responseOutput.Data = JsonConvert.SerializeObject(Convert.ToBase64String(Encoding.UTF8.GetBytes(responseOutput.Data.ToString())));
objectResult.Value = responseOutput;
}
}
}
}
}
await next.Invoke();
}
}
}

View File

@ -8,8 +8,9 @@ namespace IRaCIS.Application.Services.BusinessFilter
/// 统一返回前端数据包装之前在控制器包装现在修改为动态Api 在ResultFilter这里包装减少重复冗余代码 /// 统一返回前端数据包装之前在控制器包装现在修改为动态Api 在ResultFilter这里包装减少重复冗余代码
/// by zhouhang 2021.09.12 周末 /// by zhouhang 2021.09.12 周末
/// </summary> /// </summary>
public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter
{ {
/// <summary> /// <summary>
/// 异步版本 /// 异步版本
/// </summary> /// </summary>
@ -26,15 +27,6 @@ namespace IRaCIS.Application.Services.BusinessFilter
//是200 并且没有包装 那么包装结果 //是200 并且没有包装 那么包装结果
if (statusCode == 200 && !(objectResult.Value is IResponseOutput)) if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
{ {
//if (objectResult.Value == null)
//{
// var apiResponse = ResponseOutput.DBNotExist();
// objectResult.Value = apiResponse;
// objectResult.DeclaredType = apiResponse.GetType();
//}
//else
//{
var type = objectResult.Value?.GetType(); var type = objectResult.Value?.GetType();
@ -64,8 +56,6 @@ namespace IRaCIS.Application.Services.BusinessFilter
objectResult.DeclaredType = apiResponse.GetType(); objectResult.DeclaredType = apiResponse.GetType();
} }
//}
} }
//如果不是200 是IResponseOutput 不处理 //如果不是200 是IResponseOutput 不处理

View File

@ -0,0 +1,44 @@
using NPOI.SS.Formula.Functions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IRaCIS.Core.Application.Helper
{
public static class EmailMaskHelper
{
//显示位数3分之2的位数向上取整
//取哪几个个值:最后一位和前面几位
//其他3个***。
//比如hlj23@126.com
//为hlj***3@126.com
//he@126.com
//为h*** e@126.com
public static string MaskEmail(string email)
{
// 找到 "@" 符号的位置
int atIndex = email.IndexOf('@');
string visiblePartBefore = email.Substring(0, atIndex);
string afterAt = email.Substring(atIndex + 1);
int visibleLength = (int)Math.Ceiling((double)visiblePartBefore.Length * 2 / 3);
// 替换中间两位字符为星号
string hiddenPartBeforeAt = visiblePartBefore.Substring(0, visibleLength - 1) + "***" + visiblePartBefore.Last();
// 组合隐藏和可见部分
string hiddenEmail = hiddenPartBeforeAt + "@" + afterAt;
return hiddenEmail;
}
}
}

View File

@ -256,7 +256,7 @@ namespace IRaCIS.Application.Services
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
"", "Sir/Madam",
//---您正在进行邮箱重置密码操作 //---您正在进行邮箱重置密码操作
_localizer["Mail_ResettingPassword"], _localizer["Mail_ResettingPassword"],
verificationCode verificationCode
@ -300,7 +300,7 @@ namespace IRaCIS.Application.Services
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
"Sir or Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目 //---您正在参与展影医疗IRC项目
_localizer["Mail_IRCProject", companyName], _localizer["Mail_IRCProject", companyName],
verificationCode verificationCode
@ -342,7 +342,7 @@ namespace IRaCIS.Application.Services
var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr), var htmlBodyStr = string.Format(ReplaceCompanyName(input.htmlBodyStr),
"Sir or Madam", "Sir/Madam",
//---您正在参与展影医疗IRC项目中心调研工作 //---您正在参与展影医疗IRC项目中心调研工作
_localizer["Mail_CenterResearchReminder", companyName], _localizer["Mail_CenterResearchReminder", companyName],
verificationCode verificationCode

View File

@ -18,6 +18,7 @@ using LoginReturnDTO = IRaCIS.Application.Contracts.LoginReturnDTO;
using IRaCIS.Core.Application.Auth; using IRaCIS.Core.Application.Auth;
using BeetleX.Redis.Commands; using BeetleX.Redis.Commands;
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Application.Helper;
namespace IRaCIS.Application.Services namespace IRaCIS.Application.Services
{ {
@ -676,7 +677,8 @@ namespace IRaCIS.Application.Services
await _mailVerificationService.SenMFAVerifyEmail(userId, userInfo.FullName, userInfo.EMail, verificationCode, (UserMFAType)mfaType); await _mailVerificationService.SenMFAVerifyEmail(userId, userInfo.FullName, userInfo.EMail, verificationCode, (UserMFAType)mfaType);
return ResponseOutput.Ok(); var hiddenEmail = EmailMaskHelper.MaskEmail(userInfo.EMail);
return ResponseOutput.Ok(hiddenEmail);
} }
/// <summary> /// <summary>

View File

@ -261,9 +261,12 @@ namespace IRaCIS.Application.Services
[AllowAnonymous] [AllowAnonymous]
public async Task testwwwww([FromServices] IWebHostEnvironment env) public async Task<string> testEmail([FromServices] IWebHostEnvironment env ,string email)
{ {
await Task.CompletedTask;
var hiddenEmail = EmailMaskHelper.MaskEmail(email);
return hiddenEmail;
} }

View File

@ -1,6 +1,7 @@
using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Domain.Models;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.Json; using Microsoft.Extensions.Configuration.Json;
using System.Collections.Generic;
namespace IRaCIS.Core.Domain.Share namespace IRaCIS.Core.Domain.Share
{ {
@ -19,7 +20,7 @@ namespace IRaCIS.Core.Domain.Share
public int LoginMaxFailCount { get; set; } public int LoginMaxFailCount { get; set; }
public int LoginFailLockMinutes { get; set; } public int LoginFailLockMinutes { get; set; }
public int AutoLoginOutMinutes { get; set; } public int AutoLoginOutMinutes { get; set; }
@ -39,9 +40,9 @@ namespace IRaCIS.Core.Domain.Share
public class SystemEmailSendConfig public class SystemEmailSendConfig
{ {
public int Port { get; set; } public int Port { get; set; }
public string Host { get; set; } public string Host { get; set; }
public string FromEmail { get; set; } public string FromEmail { get; set; }
@ -66,6 +67,13 @@ namespace IRaCIS.Core.Domain.Share
} }
public class EncreptResponseOption
{
public bool IsEnable { get; set; }
public List<string> ApiPathList { get; set; }
}
/// <summary> /// <summary>
/// 项目基础配置规则 /// 项目基础配置规则
@ -89,7 +97,7 @@ namespace IRaCIS.Core.Domain.Share
public static string SystemSiteCodePrefix { get; set; } public static string SystemSiteCodePrefix { get; set; }
public static string BlindTaskPrefix { get; set; } public static string BlindTaskPrefix { get; set; }
/// <summary> /// <summary>
/// 用户默认密码 /// 用户默认密码
@ -104,7 +112,7 @@ namespace IRaCIS.Core.Domain.Share
{ {
Path = "appsettings.json", Path = "appsettings.json",
ReloadOnChange = true ReloadOnChange = true
}) })
.Build(); .Build();
DoctorCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DoctorCodePrefix"); DoctorCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DoctorCodePrefix");
@ -112,7 +120,7 @@ namespace IRaCIS.Core.Domain.Share
QCChallengeCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("QCChallengeCodePrefix"); QCChallengeCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("QCChallengeCodePrefix");
NoneDicomStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("NoneDicomStudyCodePrefix"); NoneDicomStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("NoneDicomStudyCodePrefix");
DicomStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DicomStudyCodePrefix"); DicomStudyCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DicomStudyCodePrefix");
DefaultPassword= configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DefaultPassword"); DefaultPassword = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DefaultPassword");
SystemSiteCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("SystemSiteCodePrefix"); SystemSiteCodePrefix = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("SystemSiteCodePrefix");
DefaultInternalOrganizationName = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DefaultInternalOrganizationName"); DefaultInternalOrganizationName = configuration.GetSection("IRaCISBasicConfig").GetValue<string>("DefaultInternalOrganizationName");
@ -125,7 +133,7 @@ namespace IRaCIS.Core.Domain.Share
//获取实体编码字符串 //获取实体编码字符串
public static string GetCodeStr(int codeInt ,string typeStr) public static string GetCodeStr(int codeInt, string typeStr)
{ {
switch (typeStr) switch (typeStr)
{ {
@ -139,7 +147,7 @@ namespace IRaCIS.Core.Domain.Share
case nameof(QCChallenge): case nameof(QCChallenge):
return QCChallengeCodePrefix+ codeInt.ToString("D5"); return QCChallengeCodePrefix + codeInt.ToString("D5");
case nameof(NoneDicomStudy): case nameof(NoneDicomStudy):
@ -164,5 +172,5 @@ namespace IRaCIS.Core.Domain.Share
} }
} }

View File

@ -54,7 +54,9 @@ namespace IRaCIS.Core.Infrastructure.Extention
NoToken = 10, NoToken = 10,
//带了Token,但是没有相应权限(该用户类型不能做) //带了Token,但是没有相应权限(该用户类型不能做)
HaveTokenNotAccess = 11 HaveTokenNotAccess = 11,
ResultEncrepted=12
} }

View File

@ -27,7 +27,7 @@
/// <summary> /// <summary>
/// 返回数据 /// 返回数据
/// </summary> /// </summary>
T Data { get; } T Data { get; set; }
} }
//public interface IResponseOutput<T,T2> : IResponseOutput //public interface IResponseOutput<T,T2> : IResponseOutput

View File

@ -25,7 +25,7 @@ namespace IRaCIS.Core.Infrastructure.Extention
/// 数据 兼顾以前 Json序列化的时候返回属性名为“Result” /// 数据 兼顾以前 Json序列化的时候返回属性名为“Result”
/// </summary> /// </summary>
[JsonProperty("Result")] [JsonProperty("Result")]
public T Data { get; private set; } public T Data { get; set; }
[JsonProperty("OtherInfo")] [JsonProperty("OtherInfo")]