Compare commits

..

No commits in common. "c2f768bef8d95389c0592825f715e5a17bd1a958" and "dfe6d131824f20494beabe8dbdf382a2e38c4376" have entirely different histories.

9 changed files with 47 additions and 161 deletions

View File

@ -186,7 +186,7 @@ namespace IRaCIS.Api.Controllers
[HttpGet("User/UserRedirect")] [HttpGet("User/UserRedirect")]
[AllowAnonymous] [AllowAnonymous]
public async Task<IActionResult> UserRedirect([FromServices] IRepository<IdentityUser> _useRepository, string url, [FromServices] ILogger<ExtraController> _logger, [FromServices] ITokenService _tokenService) public async Task<IActionResult> UserRedirect([FromServices] IRepository<IdentityUser> _useRepository, string url, [FromServices] ILogger<ExtraController> _logger)
{ {
var decodeUrl = System.Web.HttpUtility.UrlDecode(url); var decodeUrl = System.Web.HttpUtility.UrlDecode(url);
@ -212,9 +212,7 @@ namespace IRaCIS.Api.Controllers
CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.en_US); CultureInfo.CurrentUICulture = new CultureInfo(StaticData.CultureInfo.en_US);
} }
var isExpire = _tokenService.IsTokenExpired(token); if (!await _useRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd))
if (!await _useRepository.AnyAsync(t => t.Id == Guid.Parse(userId) && t.EmailToken == token && t.IsFirstAdd) || isExpire)
{ {
decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(I18n.T("UserRedirect_InitializationLinkExpire"))} "; decodeUrl = errorUrl + $"?lang={lang}&ErrorMessage={System.Web.HttpUtility.UrlEncode(I18n.T("UserRedirect_InitializationLinkExpire"))} ";
} }

View File

@ -23,8 +23,7 @@
"AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV", "AccessKeySecret": "FLizxkHsMm4CGYHtkV8E3PNJJZU7oV",
"RoleArn": "acs:ram::1899121822495495:role/dev-oss-access", "RoleArn": "acs:ram::1899121822495495:role/dev-oss-access",
"BucketName": "zy-irc-test-store", "BucketName": "zy-irc-test-store",
//"ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com", "ViewEndpoint": "https://zy-irc-test-store.oss-cn-shanghai.aliyuncs.com",
"ViewEndpoint": "https://zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com",
"Region": "oss-cn-shanghai", "Region": "oss-cn-shanghai",
"DurationSeconds": 7200 "DurationSeconds": 7200
}, },

View File

@ -3,7 +3,7 @@
"SecurityKey": "ShangHaiZhanYing_SecurityKey_SHzyyl@2021", "SecurityKey": "ShangHaiZhanYing_SecurityKey_SHzyyl@2021",
"Issuer": "Extimaging", "Issuer": "Extimaging",
"Audience": "EICS", "Audience": "EICS",
"TokenExpireMinute": "5" "TokenExpireDays": "7"
}, },
"IpRateLimiting": { "IpRateLimiting": {
"EnableEndpointRateLimiting": true, "EnableEndpointRateLimiting": true,

View File

@ -23,7 +23,7 @@ namespace IRaCIS.Core.Application.Auth
/// <summary> /// <summary>
/// 过期时间 /// 过期时间
/// </summary> /// </summary>
public int TokenExpireMinute { get; set; } public int TokenExpireDays { get; set; }
//public Dictionary<string, object> Claims { get; set; } //public Dictionary<string, object> Claims { get; set; }

View File

@ -9,8 +9,6 @@ namespace IRaCIS.Core.Application.Auth
public interface ITokenService public interface ITokenService
{ {
string GetToken(UserTokenInfo user); string GetToken(UserTokenInfo user);
bool IsTokenExpired(string token);
} }
@ -49,27 +47,13 @@ namespace IRaCIS.Core.Application.Auth
signingCredentials: _jwtSetting.Credentials, signingCredentials: _jwtSetting.Credentials,
claims: claims, claims: claims,
notBefore: DateTime.Now, notBefore: DateTime.Now,
expires: DateTime.Now.AddMinutes(_jwtSetting.TokenExpireMinute) expires: DateTime.Now.AddDays(_jwtSetting.TokenExpireDays)
); );
string jwtToken = new JwtSecurityTokenHandler().WriteToken(token); string jwtToken = new JwtSecurityTokenHandler().WriteToken(token);
return jwtToken; return jwtToken;
} }
public bool IsTokenExpired(string token)
{
var handler = new JwtSecurityTokenHandler();
try
{
var jwtToken = handler.ReadJwtToken(token);
return jwtToken.ValidTo < DateTime.UtcNow;
}
catch
{
return true; // 无效 Token 也视为已过期
}
}
} }

View File

@ -9,10 +9,8 @@ using Amazon.SecurityToken.Model;
using IRaCIS.Core.Infrastructure; using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.NewtonsoftJson; using IRaCIS.Core.Infrastructure.NewtonsoftJson;
using MassTransit; using MassTransit;
using MassTransit.Caching.Internals;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Minio; using Minio;
using Minio.DataModel;
using Minio.DataModel.Args; using Minio.DataModel.Args;
using System.Reactive.Linq; using System.Reactive.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -145,9 +143,7 @@ public interface IOSSService
public Task<string> GetSignedUrl(string ossRelativePath); public Task<string> GetSignedUrl(string ossRelativePath);
public Task DeleteFromPrefix(string prefix, bool isCache = false); public Task DeleteFromPrefix(string prefix);
public Task DeleteObjects(List<string> objectKeys);
List<string> GetRootFolderNames(); List<string> GetRootFolderNames();
@ -586,7 +582,7 @@ public class OSSService : IOSSService
/// </summary> /// </summary>
/// <param name="prefix"></param> /// <param name="prefix"></param>
/// <returns></returns> /// <returns></returns>
public async Task DeleteFromPrefix(string prefix, bool isCache = false) public async Task DeleteFromPrefix(string prefix)
{ {
GetObjectStoreTempToken(); GetObjectStoreTempToken();
@ -596,21 +592,6 @@ public class OSSService : IOSSService
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken); var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
var bucketName = string.Empty;
if (isCache)
{
Uri uri = new Uri(aliConfig.ViewEndpoint);
string host = uri.Host; // 获取 "zy-irc-test-dev-cache.oss-cn-shanghai.aliyuncs.com"
string[] parts = host.Split('.');
bucketName = parts[0];
}
else
{
bucketName = aliConfig.BucketName;
}
try try
{ {
@ -619,7 +600,7 @@ public class OSSService : IOSSService
do do
{ {
// 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker // 使用 prefix 模拟目录结构,设置 MaxKeys 和 NextMarker
objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(bucketName) objectListing = _ossClient.ListObjects(new Aliyun.OSS.ListObjectsRequest(aliConfig.BucketName)
{ {
Prefix = prefix, Prefix = prefix,
MaxKeys = 1000, MaxKeys = 1000,
@ -631,7 +612,7 @@ public class OSSService : IOSSService
// 删除获取到的文件 // 删除获取到的文件
if (keys.Count > 0) if (keys.Count > 0)
{ {
_ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(bucketName, keys, false)); _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, keys, false));
} }
// 设置 NextMarker 以获取下一页的数据 // 设置 NextMarker 以获取下一页的数据
@ -740,81 +721,6 @@ public class OSSService : IOSSService
} }
} }
public async Task DeleteObjects(List<string> objectKeys)
{
GetObjectStoreTempToken();
if (ObjectStoreServiceOptions.ObjectStoreUse == "AliyunOSS")
{
var aliConfig = ObjectStoreServiceOptions.AliyunOSS;
var _ossClient = new OssClient(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? aliConfig.EndPoint : aliConfig.InternalEndpoint, AliyunOSSTempToken.AccessKeyId, AliyunOSSTempToken.AccessKeySecret, AliyunOSSTempToken.SecurityToken);
if (objectKeys.Count > 0)
{
var result = _ossClient.DeleteObjects(new Aliyun.OSS.DeleteObjectsRequest(aliConfig.BucketName, objectKeys, false));
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "MinIO")
{
var minIOConfig = ObjectStoreServiceOptions.MinIO;
var minioClient = new MinioClient().WithEndpoint($"{minIOConfig.EndPoint}:{minIOConfig.Port}")
.WithCredentials(minIOConfig.AccessKeyId, minIOConfig.SecretAccessKey).WithSSL(minIOConfig.UseSSL)
.Build();
if (objectKeys.Count > 0)
{
var objArgs = new RemoveObjectsArgs()
.WithBucket(minIOConfig.BucketName)
.WithObjects(objectKeys);
// 删除对象
await minioClient.RemoveObjectsAsync(objArgs);
}
}
else if (ObjectStoreServiceOptions.ObjectStoreUse == "AWS")
{
var awsConfig = ObjectStoreServiceOptions.AWS;
// 提供awsAccessKeyId和awsSecretAccessKey构造凭证
var credentials = new SessionAWSCredentials(AWSTempToken.AccessKeyId, AWSTempToken.SecretAccessKey, AWSTempToken.SessionToken);
//提供awsEndPoint域名进行访问配置
var clientConfig = new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.USEast1,
UseHttp = true,
};
var amazonS3Client = new AmazonS3Client(credentials, clientConfig);
if (objectKeys.Count > 0)
{
// 准备删除请求
var deleteObjectsRequest = new Amazon.S3.Model.DeleteObjectsRequest
{
BucketName = awsConfig.BucketName,
Objects = objectKeys.Select(t => new KeyVersion() { Key = t }).ToList()
};
// 批量删除对象
var deleteObjectsResponse = await amazonS3Client.DeleteObjectsAsync(deleteObjectsRequest);
}
}
else
{
throw new BusinessValidationFailedException("未定义的存储介质类型");
}
}
public ObjectStoreDTO GetObjectStoreTempToken() public ObjectStoreDTO GetObjectStoreTempToken()
{ {

View File

@ -19,7 +19,7 @@
令牌密码 令牌密码
</summary> </summary>
</member> </member>
<member name="P:IRaCIS.Core.Application.Auth.JwtSetting.TokenExpireMinute"> <member name="P:IRaCIS.Core.Application.Auth.JwtSetting.TokenExpireDays">
<summary> <summary>
过期时间 过期时间
</summary> </summary>
@ -13490,7 +13490,7 @@
</summary> </summary>
<returns></returns> <returns></returns>
</member> </member>
<member name="M:IRaCIS.Core.Application.Helper.OSSService.DeleteFromPrefix(System.String,System.Boolean)"> <member name="M:IRaCIS.Core.Application.Helper.OSSService.DeleteFromPrefix(System.String)">
<summary> <summary>
删除某个目录的文件 删除某个目录的文件
</summary> </summary>

View File

@ -620,25 +620,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc
{ {
if (dicomStudyId == null) if (dicomStudyId == null)
{ {
var deleteStudyPathList = await _taskInstanceRepository.Where(t => t.VisitTaskId == visitTaskId).GroupBy(t => t.StudyId).Select(g => g.First().Path).ToListAsync();
foreach (var fisrtPath in deleteStudyPathList)
{
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
await _oSSService.DeleteFromPrefix(prefix, true);
}
await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId); await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId);
await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId); await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId);
await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId); await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId);
} }
else else
{ {
var fisrtPath = await _taskInstanceRepository.Where(t => t.VisitTaskId == visitTaskId && t.StudyId == dicomStudyId).Select(t => t.Path).FirstOrDefaultAsync();
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
await _oSSService.DeleteFromPrefix(prefix, true);
await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId); await _taskStudyRepository.DeleteFromQueryAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);
await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId); await _taskSeriesRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);
await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId); await _taskInstanceRepository.BatchDeleteNoTrackingAsync(t => t.VisitTaskId == visitTaskId && t.Id == dicomStudyId);

View File

@ -35,7 +35,6 @@ namespace IRaCIS.Core.Application.Image.QA
IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository, IRepository<TrialQCQuestionAnswer> _trialQCQuestionAnswerRepository,
IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository, IRepository<ReadingQuestionCriterionTrial> _readingQuestionCriterionTrialRepository,
IDistributedLockProvider _distributedLockProvider, IReadingClinicalDataService _readingClinicalDataService, IDistributedLockProvider _distributedLockProvider, IReadingClinicalDataService _readingClinicalDataService,
IOSSService _oSSService,
IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService, IQCOperationService IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer, IWebHostEnvironment _hostEnvironment) : BaseService, IQCOperationService
{ {
@ -836,8 +835,6 @@ namespace IRaCIS.Core.Application.Image.QA
await _dicomStudyRepository.DeleteAsync(study); await _dicomStudyRepository.DeleteAsync(study);
var fisrtPath = await _dicomInstanceRepository.Where(t => t.StudyId == id).Select(t => t.Path).FirstOrDefaultAsync();
var succeess2 = await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id); var succeess2 = await _dicomInstanceRepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
var success3 = await _dicomSeriesrepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id); var success3 = await _dicomSeriesrepository.BatchDeleteNoTrackingAsync(t => t.StudyId == id);
@ -845,9 +842,6 @@ namespace IRaCIS.Core.Application.Image.QA
await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null }); await _scpStudyRepository.BatchUpdateNoTrackingAsync(t => t.Id == id, u => new SCPStudy() { SubjectVisitId = null });
var prefix = fisrtPath.Substring(1, fisrtPath.LastIndexOf('/') - 1);
await _oSSService.DeleteFromPrefix(prefix, true);
//var success3 = await _dicomSeriesrepository.DeleteFromQueryAsync(t => t.StudyId == id, true); //var success3 = await _dicomSeriesrepository.DeleteFromQueryAsync(t => t.StudyId == id, true);
//var success4 = await _repository.BatchDeleteAsync<StudyMonitor>(t => t.StudyId == id); //var success4 = await _repository.BatchDeleteAsync<StudyMonitor>(t => t.StudyId == id);
@ -1633,7 +1627,7 @@ namespace IRaCIS.Core.Application.Image.QA
//删除 软删除的物理文件 //删除 软删除的物理文件
var instancePathList = await _dicomInstanceRepository.Where(t => (t.DicomSerie.IsDeleted || t.IsDeleted) && t.SubjectVisitId == subjectVisitId, false, true) var instancePathList = await _dicomInstanceRepository.Where(t => t.DicomSerie.IsDeleted && t.SubjectVisitId == subjectVisitId)
.Select(t => t.Path).ToListAsync(); .Select(t => t.Path).ToListAsync();
//维护统一状态 //维护统一状态
@ -1672,9 +1666,17 @@ namespace IRaCIS.Core.Application.Image.QA
dbSubjectVisit.ReadingStatus = trialConfig.IsImageConsistencyVerification ? ReadingStatusEnum.ConsistencyCheck : ReadingStatusEnum.TaskAllocate; dbSubjectVisit.ReadingStatus = trialConfig.IsImageConsistencyVerification ? ReadingStatusEnum.ConsistencyCheck : ReadingStatusEnum.TaskAllocate;
//删除影像 //删除影像
instancePathList.ForEach(path =>
{
await _oSSService.DeleteObjects(instancePathList.Select(t => t.TrimStart('/')).ToList()); var physicalPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, path);
if (System.IO.File.Exists(physicalPath))
{
File.Delete(physicalPath);
}
});
} }
else else
@ -1728,7 +1730,17 @@ namespace IRaCIS.Core.Application.Image.QA
dbSubjectVisit.ReadingStatus = trialConfig.IsImageConsistencyVerification ? ReadingStatusEnum.ConsistencyCheck : ReadingStatusEnum.TaskAllocate; dbSubjectVisit.ReadingStatus = trialConfig.IsImageConsistencyVerification ? ReadingStatusEnum.ConsistencyCheck : ReadingStatusEnum.TaskAllocate;
//删除影像 //删除影像
await _oSSService.DeleteObjects(instancePathList.Select(t => t.TrimStart('/')).ToList()); instancePathList.ForEach(path =>
{
var physicalPath = FileStoreHelper.GetPhysicalFilePath(_hostEnvironment, path);
if (System.IO.File.Exists(physicalPath))
{
File.Delete(physicalPath);
}
});
} }
else else