diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs b/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs index fdcb0222d..9dd672d1e 100644 --- a/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs +++ b/IRaCIS.Core.Application/BusinessFilter/Encryption/EncryptionRequestMiddleware.cs @@ -1,4 +1,5 @@ using IRaCIS.Core.Domain.Share; +using IRaCIS.Core.Infrastructure.Encryption; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using Newtonsoft.Json.Linq; diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj index bf0e815b4..5d385a0b9 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.csproj @@ -47,7 +47,6 @@ - diff --git a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml index a1e1d90e5..fed48da3d 100644 --- a/IRaCIS.Core.Application/IRaCIS.Core.Application.xml +++ b/IRaCIS.Core.Application/IRaCIS.Core.Application.xml @@ -11317,7 +11317,7 @@ - + IR影像阅片 @@ -12437,20 +12437,6 @@ 测试加密API 返回的结果 - - - https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html - - - - - RSA解密 - - 私钥 - 待解密的字符串(Base64) - 解密后的字符串 - - 不生效,不知道为啥 diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs index 9c8953122..571f4e1f3 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DTO/UnionStudyViewDodel.cs @@ -415,6 +415,8 @@ namespace IRaCIS.Core.Application.Contracts [NotDefault] public string SubjectCode { get; set; } + + public Guid? VisitTaskId { get; set; } } public class IRTaskUploadedDicomStudyQuery diff --git a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs index 29fedaebe..21f87dece 100644 --- a/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs +++ b/IRaCIS.Core.Application/Service/ImageAndDoc/DownloadAndUploadService.cs @@ -112,8 +112,14 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc { await SubejctRandomReadingTaskNameDeal(inQuery.SubjectId, inQuery.TrialReadingCriterionId); + //要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的 + var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) + .Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync(); + var query = _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) + //满足 有序,或者随机只看到当前任务的dicom 非dicom检查 + .WhereIf(criterionInfo.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) .Select(u => new SubjectImageUploadDTO() { VisitTaskId = u.Id, @@ -587,10 +593,12 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc public async Task> GetIRUploadTaskNoneDicomStudyList(IRUploadStudyQuery inQuery) { var info = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) - .Select(t => new { t.IsImageFilter, t.CriterionModalitys }).FirstNotNullAsync(); + .Select(t => new { t.IsImageFilter, t.CriterionModalitys,t.IsReadingTaskViewInOrder }).FirstNotNullAsync(); var query = from u in _visitTaskRepository.Where(t => t.SubjectId == inQuery.SubjectId && t.TrialReadingCriterionId == inQuery.TrialReadingCriterionId && t.SourceSubjectVisitId != null && t.DoctorUserId == _userInfo.Id && t.TaskState == TaskState.Effect) + //满足 有序,或者随机只看到当前任务的dicom 非dicom检查 + .WhereIf(info.IsReadingTaskViewInOrder != ReadingOrder.SubjectRandom && inQuery.VisitTaskId != null, t => t.Id == inQuery.VisitTaskId) join ns in _noneDicomStudyReposiotry.Where(t => t.SubjectId == inQuery.SubjectId).WhereIf(info.IsImageFilter, t => ("|" + info.CriterionModalitys + "|").Contains("|" + t.Modality + "|")) on u.SourceSubjectVisitId equals ns.SubjectVisitId @@ -745,7 +753,6 @@ namespace IRaCIS.Core.Application.Service.ImageAndDoc public async Task> GetSubjectImageDownloadSelectList(IRReadingDownloadQuery inQuery) { //要根据标准阅片顺序,确定是否查询单个任务的,还是查询所有的 - var criterionInfo = await _readingQuestionCriterionTrialRepository.Where(t => t.Id == inQuery.TrialReadingCriterionId) .Select(t => new { t.IsReadingTaskViewInOrder }).FirstNotNullAsync(); diff --git a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs index 2b1c6b3c8..779c7daf3 100644 --- a/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs +++ b/IRaCIS.Core.Application/Service/Reading/ReadingImageTask/ReadingImageTaskService.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Newtonsoft.Json; using Newtonsoft.Json.Linq; +using NPOI.SS.Formula.Functions; using Panda.DynamicWebApi.Attributes; using ZiggyCreatures.Caching.Fusion; @@ -60,6 +61,7 @@ namespace IRaCIS.Core.Application.Service IRepository _noneDicomStudyFileSystem, IGeneralCalculateService _generalCalculateService, IRepository _readingQuestionTrialRepository, + IRepository _taskStudyRepository, ITrialEmailNoticeConfigService _trialEmailNoticeConfigService) : BaseService, IReadingImageTaskService { @@ -2603,6 +2605,14 @@ namespace IRaCIS.Core.Application.Service [HttpPost] public async Task VerifyVisitTaskQuestions(VerifyVisitTaskQuestionsInDto inDto) { + //验证后处理影像必须传 + if (_visitTaskRepository.Any(t => t.Id==inDto.VisitTaskId && t.TrialReadingCriterion.ImageUploadEnum != ReadingImageUpload.None)) + { + if (!_taskStudyRepository.Any(t => t.VisitTaskId == inDto.VisitTaskId)) + { + return ResponseOutput.NotOk("ReadingImage_BackImageNotExist"); + } + } await VerifyTaskIsSign(inDto.VisitTaskId); await VerifyDefaultQuestionBeAnswer(inDto); diff --git a/IRaCIS.Core.Application/TestService.cs b/IRaCIS.Core.Application/TestService.cs index 8601bda5f..0c91dbb43 100644 --- a/IRaCIS.Core.Application/TestService.cs +++ b/IRaCIS.Core.Application/TestService.cs @@ -6,6 +6,7 @@ using IRaCIS.Core.Application.Helper; using IRaCIS.Core.Application.ViewModel; using IRaCIS.Core.Domain.Share; using IRaCIS.Core.Infrastructure; +using IRaCIS.Core.Infrastructure.Encryption; using IRaCIS.Core.Infrastructure.NewtonsoftJson; using MassTransit; using Medallion.Threading; @@ -104,6 +105,19 @@ namespace IRaCIS.Core.Application.Service public string TestName { get; set; } } + public async Task TestAutoEncretpt([FromServices] IRepository _testLengthRepository) + { + await _testLengthRepository.AddAsync(new TestLength() { Name = "zhouhang1" }); + await _testLengthRepository.AddAsync(new TestLength() { Name = "hewentao" }); + + await _testLengthRepository.SaveChangesAsync(); + var list = _testLengthRepository.Where().ToList(); + + var exist = await _testLengthRepository.AnyAsync(t => t.Name == "zhouhang1"); + + return ResponseOutput.Ok(list, exist); + + } public async Task TestJson() { @@ -280,7 +294,7 @@ namespace IRaCIS.Core.Application.Service var encreptMd5 = AesEncryption.Encrypt(MD5Helper.Md5("123456"), key); Console.WriteLine(encreptMd5); - var decrept= AesEncryption.Decrypt(encreptMd5, key); + var decrept = AesEncryption.Decrypt(encreptMd5, key); Console.WriteLine(); diff --git a/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs b/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs new file mode 100644 index 000000000..7465ce706 --- /dev/null +++ b/IRaCIS.Core.Infra.EFCore/Context/Converter/PartialEncryptionConverter.cs @@ -0,0 +1,21 @@ +using IRaCIS.Core.Infrastructure.Encryption; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.EntityFrameworkCore.ValueGeneration; + +namespace IRaCIS.Core.Infra.EFCore; + +/// +/// 某列保留前面几位,后续加密 +/// +public class PartialEncryptionConverter : ValueConverter +{ + private readonly int _unencryptedPrefixLength; + + public PartialEncryptionConverter(int unencryptedPrefixLength) + : base( + plainText => AesEncryption.EncryptPartial(plainText, unencryptedPrefixLength), + encryptedText => AesEncryption.DecryptPartial(encryptedText, unencryptedPrefixLength)) + { + _unencryptedPrefixLength = unencryptedPrefixLength; + } +} diff --git a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs index 57ba081f2..67e8ebc3c 100644 --- a/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs +++ b/IRaCIS.Core.Infra.EFCore/Context/IRaCISDBContext.cs @@ -1,8 +1,12 @@ using IRaCIS.Core.Domain.Models; using IRaCIS.Core.Infra.EFCore.Common; +using IRaCIS.Core.Infrastructure.Encryption; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using System.ComponentModel; using System.Data; using System.Reflection; +using System.Security.Cryptography; +using System.Text; using UserTypeGroup = IRaCIS.Core.Domain.Models.UserTypeGroup; namespace IRaCIS.Core.Infra.EFCore; @@ -54,6 +58,13 @@ public class IRaCISDBContext : DbContext protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity(entity => + { + // 使用部分加密值转换器,前 2 个字符不加密,方便模糊搜索 + entity.Property(e => e.Name) + .HasConversion(new PartialEncryptionConverter(2)); + }); + #region pgsql codefirst 配置 暂时屏蔽 //if (base.Database.IsNpgsql()) //{ @@ -544,6 +555,18 @@ public class IRaCISDBContext : DbContext public virtual DbSet TrialImageDownload { get; set; } + public virtual DbSet TestLength { get; set; } + + + + + +} + +public class TestLength : Entity +{ + public string Name { get; set; } +} + -} \ No newline at end of file diff --git a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj index e942ff3ee..e5a59bc58 100644 --- a/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj +++ b/IRaCIS.Core.Infrastructure/IRaCIS.Core.Infrastructure.csproj @@ -18,6 +18,7 @@ + diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs similarity index 60% rename from IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs rename to IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs index c19d82cf8..884e8b29b 100644 --- a/IRaCIS.Core.Application/BusinessFilter/Encryption/AesEncryption.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/AesEncryption.cs @@ -3,9 +3,11 @@ using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes; using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; +using System; +using System.Security.Cryptography; using System.Text; -namespace IRaCIS.Core.Application.BusinessFilter; +namespace IRaCIS.Core.Infrastructure.Encryption; public class AesEncryption { @@ -84,4 +86,60 @@ public class AesEncryption Array.Resize(ref output, length); // 调整输出数组大小以适应实际数据长度 return output; } + + public static string DefaultKey = "12345678901234567890123456789012"; + + public static string EncryptPartial(string plainText, int unencryptedPrefixLength) + { + if (plainText.Length <= unencryptedPrefixLength) + { + return Encrypt(plainText, DefaultKey); // 如果文本太短,直接加密 + } + + var prefix = plainText.Substring(0, unencryptedPrefixLength); + var suffix = plainText.Substring(unencryptedPrefixLength); + + return prefix + Encrypt(suffix, DefaultKey); // 前缀保留,后缀加密 + } + + public static string DecryptPartial(string encryptedText, int unencryptedPrefixLength) + { + if (encryptedText.Length <= unencryptedPrefixLength) + { + return Decrypt(encryptedText, DefaultKey); // 如果文本太短,直接解密 + } + + var prefix = encryptedText.Substring(0, unencryptedPrefixLength); + var suffix = encryptedText.Substring(unencryptedPrefixLength); + + return prefix + Decrypt(suffix, DefaultKey); // 前缀保留,后缀解密 + } + + //public static string Encrypt(string plainText) + //{ + // using var aes = Aes.Create(); + // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey); + // aes.Mode = CipherMode.ECB; // 根据需要选择加密模式,这里使用 ECB 模式 + // aes.Padding = PaddingMode.PKCS7; + + // var encryptor = aes.CreateEncryptor(); + // var plainBytes = Encoding.UTF8.GetBytes(plainText); + // var encryptedBytes = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length); + + // return Convert.ToBase64String(encryptedBytes); + //} + + //public static string Decrypt(string encryptedText) + //{ + // using var aes = Aes.Create(); + // aes.Key = Encoding.UTF8.GetBytes(EncryptionKey); + // aes.Mode = CipherMode.ECB; + // aes.Padding = PaddingMode.PKCS7; + + // var decryptor = aes.CreateDecryptor(); + // var encryptedBytes = Convert.FromBase64String(encryptedText); + // var decryptedBytes = decryptor.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); + + // return Encoding.UTF8.GetString(decryptedBytes); + //} } diff --git a/IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs similarity index 97% rename from IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs rename to IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs index dcc610712..3f7d00cbd 100644 --- a/IRaCIS.Core.Application/BusinessFilter/Encryption/RSAEncryption.cs +++ b/IRaCIS.Core.Infrastructure/_IRaCIS/Encryption/RSAEncryption.cs @@ -4,9 +4,11 @@ using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Generators; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; +using System; +using System.IO; using System.Text; -namespace IRaCIS.Core.Application.BusinessFilter; +namespace IRaCIS.Core.Infrastructure.Encryption; /// /// https://www.cnblogs.com/NBDWDYS2214143926/p/13329231.html