匿名化

master
hang 2023-09-26 13:50:24 +08:00
parent bd6ed51a8c
commit f4bbd05671
15 changed files with 170 additions and 50 deletions

View File

@ -24,6 +24,7 @@ using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infrastructure;
using System.Linq;
using Microsoft.Extensions.Logging;
using IRaCIS.Core.Application.Contracts.Dicom.DTO;
namespace IRaCIS.Api.Controllers
{
@ -82,7 +83,49 @@ namespace IRaCIS.Api.Controllers
//[HttpGet, Route("imageShare/VerifyShareImage/{resourceId:guid}/{password}")]
//public async Task<IResponseOutput> VerifyShareImage(Guid resourceId, string password, [FromServices] IRepository<ImageShare> _imageShareRepository)
//{
// var pWord = password.Trim();
// var imageShare = await _imageShareRepository.FirstOrDefaultAsync(t => t.Id == resourceId);
// if (imageShare == null)
// {
// return ResponseOutput.NotOk("资源不存在。");
// }
// if (pWord != imageShare.Password.Trim())
// {
// return ResponseOutput.NotOk("分享密码错误。");
// }
// if (DateTime.Now > imageShare.ExpireTime)
// {
// return ResponseOutput.NotOk("资源分享过期。");
// }
// var resource = new ResourceInfo()
// {
// VisitTaskId = imageShare.VisitTaskId,
// RouteUrl = imageShare.RouteUrl,
// Token = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo()
// {
// Id = Guid.Empty,
// IsReviewer = false,
// IsAdmin = false,
// RealName = "Share001",
// UserName = "Share001",
// Sex = 0,
// //UserType = "ShareType",
// UserTypeEnum = UserTypeEnum.ShareImage,
// Code = "ShareCode001",
// }))
// };
// return ResponseOutput.Ok(resource);
//}
@ -164,8 +207,8 @@ namespace IRaCIS.Api.Controllers
var option = new CookieOptions
{
Expires = DateTime.Now.AddMonths(1), // 设置过期时间为 30 分钟之后
HttpOnly = false, // 确保 cookie 只能通过 HTTP 访问
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None, // 设置 SameSite 属性
HttpOnly = true, // 确保 cookie 只能通过 HTTP 访问
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Unspecified, // 设置 SameSite 属性
Secure = false // 确保 cookie 只能通过 HTTPS 访问
};

View File

@ -187,7 +187,7 @@ namespace IRaCIS.Core.Application.Filter
else
{
//本次请求被配置规则拦截:项目状态处于进行中状态时,才允许操作。
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialResource_InterceptedProjectStatusRule"]));
context.Result = new JsonResult(ResponseOutput.NotOk(_localizer["TrialService_OnlyInInitOrProgress"]));
}

View File

@ -102,8 +102,6 @@ public static class ExcelExportHelper
var (physicalPath, fileNmae) = await FileStoreHelper.GetCommonDocPhysicalFilePathAsync(_hostEnvironment, _commonDocumentRepository, code);

View File

@ -1,6 +1,46 @@
{
"RequiredAttribute": "{0} is required",
"TrialService_OnlyInInitOrProgress": "Operations are allowed only when the trial state is Initializing or Ongoing.",
"TrialService_ExistPN": "The same Trial ID already exists",
"SubjectService_ExistSubjectCode": "A patient with the relevant patient ID already exists.",
"SubjectService_ExistImage": "The patient is not allowed to be deleted for having a study of images uploaded.",
"SubjectVisitServiece_ExistOtherInCurrent": "In the patient's study, there is an unplanned study after the previous study, please re-select the previous study.",
"SubjectVisitServiece_ExistName": "This patient's study already contains a study with the same name.",
"SubjectVisitServiece_ExistImage": "Images have already been uploaded in the current study batch, and deletion is not allowed.",
"SubjectVisitServiece_HaveSetBeforeBatch": "The current study has been set to the previous study of another study and cannot be deleted.",
"TrialResource_InterceptedProjectStatusRule": "This request is blocked by the configuration rule: The operation is allowed only when the trial state is Ongoing.",
"QCOperationService_HaveSubmitted": "IC has been committed, and deletion is not allowed.",
"VisitTaskService_HaveReadingTask": "Currently the doctor has started to review the patient image, it is not allowed to cancel the assignment",
"SystemAnonymization_InvalidGroupOrElement": "Please check whether the element number or group number configured by DicomTag meets the requirements.",
"User_UsernameExist": "The user name already exists.",
"User_PhoneDup": "A user with the same phone number already exists in this user type.",
"User_EmailDup": "A user with the same email already exists in this user type.",
"User_NewOldPwdSame": "The new password is the same as the old one.",
"User_OldPwdInvalid": "Failed to verify the old password.",
"User_LegalEmail": "Please input a legal email.",
"User_VerificationCodeError": "The verification code is wrong.",
"User_VerificationCodeExpired": "The verification code has expired.",
"User_CreateFailed": "Check the email address or contact maintainers. The email fails to be sent and the account cannot be created.",
"User_InvalidEmail": "Please enter a correct E-mail address.",
"User_EmailError": "The email adress is wrong.",
"User_InProject": "The user has participated in the trial and cannot be deleted.",
"User_Disabled": "The user has been disabled.",
//UserTypeService
"UserType_InUse": "User already exists in that user type, and it cannot be deleted.",
"ReadingImage_IDMust": "System call failed. When there is no Read ID, the standard ID must be passed.",
"ReadingImage_TaskFinish": "Please note that all reads of the current subject have been completed.",
"ReadingImage_NeedRest": "You have been continuously reading for {0} hours. Please take a break of {1} minutes before resumption.",
// SiteSurvey --------------------------------------------------------------------------------------------------------------------------
// TrialSiteEquipmentSurveyService
@ -211,9 +251,7 @@
"ReadingImage_PCWGMaximum": "According to the imaging charter, the number of baseline lesions at the same location should enter only {0} time. Please confirm.",
"ReadingImage_RequiredQuestion": "Before submission, please fill in \"{0}\".",
"ReadingImage_ClinicalRead": "The clinical data has not been read. Please confirm!",
"ReadingImage_IDMust": "System call failed. When there is no Read ID, the standard ID must be passed.",
"ReadingImage_TaskFinish": "Please note that all reads of the current subject have been completed.",
"ReadingImage_NeedRest": "You have been continuously reading for {0} hours. Please take a break of {1} minutes before resumption.",
//ReadingJudgeTaskService
"ReadingJudge_SouceIdNull": "'System call failed. The Source ID of the global review which is being adjudicated currently is 'null'. '",
//ReadingOncologyTaskService

View File

@ -1,5 +1,7 @@
{
//
// trial --------------------------------------------------------------------------------------------------------------------------
"TrialService_OnlyInInitOrProgress": "项目状态只有处于:初始化或者进行中时,才允许操作。",
"TrialService_ExistPN": "已经存在相同的项目编号",
@ -11,22 +13,38 @@
"SubjectVisitServiece_ExistName": "该患者的检查批次中已经包含一个具有相同名称的检查批次。",
"SubjectVisitServiece_ExistImage": "当前检查批次已经有影像上传,不允许删除。",
"SubjectVisitServiece_HaveSetBeforeBatch": "当前检查批次已经被设置为另一检查批次的上一检查批次,不允许删除。",
"TrialResource_InterceptedProjectStatusRule": null,
"TrialResource_InterceptedProjectStatusRule": "本次请求被配置规则拦截:项目状态处于进行中状态时,才允许操作。",
"QCOperationService_HaveSubmitted": "IC已经提交不允许删除。",
"VisitTaskService_HaveReadingTask": "当前医生已开始做该Subject任务不允许取消分配",
"SystemAnonymization_InvalidGroupOrElement": "请核对DicomTag 配置的元素号或者组号是否符合要求",
"User_UsernameExist": "用户名已经存在。",
"User_PhoneDup": "该用户类型中已存在具有相同的电话的用户。",
"User_EmailDup": "该用户类型中已存在具有相同邮箱的用户。",
"User_NewOldPwdSame": "新密码与旧密码相同。",
"User_OldPwdInvalid": "旧密码验证失败。",
"User_LegalEmail": "请输入合法的电子邮件。",
"User_VerificationCodeError": "验证码错误。",
"User_VerificationCodeExpired": "验证码已经过期。",
"User_CreateFailed": "请检查邮箱地址或者联系维护人员, 邮件发送失败, 未能创建账户成功。",
"User_InvalidEmail": "请输入一个正确的邮箱。",
"User_EmailError": "邮箱错误。",
"User_InProject": "该用户已经参加项目,不能够删除。",
"User_Disabled": "该用户已经被禁用。",
//UserTypeService
"UserType_InUse": "该用户类型中已存在用户,不能删除。",
//
"ReadingImage_IDMust": "系统调用失败当没有任务ID的时候标准ID必传。",
"ReadingImage_TaskFinish": "当前患者所有阅片任务已完成,请知悉。",
"ReadingImage_NeedRest": "您已连续阅片{0}个小时,请休息{1}分钟后,再继续阅片。",
"RequiredAttribute": "{0} 字段是必须的",
@ -240,9 +258,7 @@
"ReadingImage_PCWGMaximum": "按照《独立影像评估章程》的相关规则,同一部位的基线病灶只需录入{0}次,请确认。",
"ReadingImage_RequiredQuestion": "提交前,请完成\"{0}\"",
"ReadingImage_ClinicalRead": "临床数据未阅读,请确认!",
"ReadingImage_IDMust": "系统调用失败当没有任务ID的时候标准ID必传。",
"ReadingImage_TaskFinish": "当前患者所有阅片任务已完成,请知悉。",
"ReadingImage_NeedRest": "您已连续阅片{0}个小时,请休息{1}分钟后,再继续阅片。",
//ReadingJudgeTaskService
"ReadingJudge_SouceIdNull": "系统调用失败当前裁判的全局任务的SouceId为null。",
//ReadingOncologyTaskService

View File

@ -250,7 +250,10 @@ namespace IRaCIS.Core.Application.Service.Allocation
{
if (await _visitTaskRepository.AnyAsync(t => t.TrialReadingCriterionId == cancelCommand.TrialReadingCriterionId && t.SubjectId == command.SubjectId && t.DoctorUserId == command.DoctorUserId && t.ArmEnum == command.ArmEnum && t.ReadingTaskState != ReadingTaskState.WaitReading))
{
throw new BusinessValidationFailedException("当前医生已开始做该Subject 该标准的任务,不允许取消分配");
//当前医生已开始做该Subject任务不允许取消分配
throw new BusinessValidationFailedException(_localizer["VisitTaskService_HaveReadingTask"]);
}
await _subjectUserRepository.DeleteFromQueryAsync(t => t.Id == command.Id);

View File

@ -5,25 +5,27 @@ using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using IRaCIS.Core.Application.Auth;
using EasyCaching.Core;
namespace IRaCIS.Core.Application.Services
{
[AllowAnonymous, ApiExplorerSettings(GroupName = "Image")]
public class ImageShareService : BaseService, IImageShareService
{
private readonly IEasyCachingProvider _provider;
private readonly IRepository<ImageShare> _imageShareRepository;
private readonly IRepository<DicomStudy> _studyRepository;
private readonly IConfiguration _configuration;
private readonly ITokenService _tokenService;
public ImageShareService(IRepository<ImageShare> imageShareRepository, IRepository<DicomStudy> studyRepository, IConfiguration configuration, ITokenService tokenService)
public ImageShareService(IRepository<ImageShare> imageShareRepository, IRepository<DicomStudy> studyRepository, IConfiguration configuration, ITokenService tokenService, IEasyCachingProvider provider)
{
_imageShareRepository = imageShareRepository;
_studyRepository = studyRepository;
_configuration = configuration;
_tokenService = tokenService;
_provider = provider;
}
[HttpPost]
@ -75,13 +77,14 @@ namespace IRaCIS.Core.Application.Services
return ResponseOutput.NotOk("资源分享过期。");
}
var vitrualUserId = Guid.NewGuid();
var resource = new ResourceInfo()
{
VisitTaskId = imageShare.VisitTaskId,
RouteUrl=imageShare.RouteUrl,
Token = _tokenService.GetToken(IRaCISClaims.Create(new UserBasicInfo()
{
Id = Guid.Empty,
Id = vitrualUserId,
IsReviewer = false,
IsAdmin = false,
RealName = "Share001",
@ -93,6 +96,7 @@ namespace IRaCIS.Core.Application.Services
}))
};
await _provider.SetAsync(vitrualUserId.ToString(), resource.Token, TimeSpan.FromDays(7));
return ResponseOutput.Ok(resource);

View File

@ -5,6 +5,6 @@ namespace IRaCIS.Core.Application.Services
public interface IImageShareService
{
Task<IResponseOutput> CreateImageShare(ImageShareCommand imageShareCommand);
Task<IResponseOutput> VerifyShareImage(Guid resourceId, string password);
//Task<IResponseOutput> VerifyShareImage(Guid resourceId, string password);
}
}

View File

@ -51,7 +51,8 @@ namespace IRaCIS.Core.Application.Service
ushort result;
if ((UInt16.TryParse(addOrEditSystemAnonymization.Group, System.Globalization.NumberStyles.HexNumber, null, out result)==false) || (UInt16.TryParse(addOrEditSystemAnonymization.Element, System.Globalization.NumberStyles.HexNumber, null, out result) == false))
{
return ResponseOutput.NotOk("请核对DicomTag 配置的元素号或者组号是否符合要求");
//请核对DicomTag 配置的元素号或者组号是否符合要求
return ResponseOutput.NotOk(_localizer["SystemAnonymization_InvalidGroupOrElement"]);
}

View File

@ -54,7 +54,8 @@ namespace IRaCIS.Application.Services
{
if (await _userRepository.WhereIf(userId != null, t => t.Id != userId).AnyAsync(t => t.UserName == userName))
{
throw new BusinessValidationFailedException("用户名已经存在。");
//---用户名已经存在。
throw new BusinessValidationFailedException(_localizer["User_UsernameExist"]);
}
}
@ -62,7 +63,8 @@ namespace IRaCIS.Application.Services
{
if (await _userRepository.WhereIf(userId != null, t => t.Id != userId).AnyAsync(t => (t.Phone == phone && t.UserTypeId == userTypeId)))
{
throw new BusinessValidationFailedException("该用户类型中已存在具有相同的电话的用户。");
//---该用户类型中已存在具有相同的电话的用户。
throw new BusinessValidationFailedException(_localizer["User_PhoneDup"]);
}
}
@ -71,7 +73,8 @@ namespace IRaCIS.Application.Services
{
if (await _userRepository.WhereIf(userId != null, t => t.Id != userId).AnyAsync(t => (t.EMail == email && t.UserTypeId == userTypeId)))
{
throw new BusinessValidationFailedException("该用户类型中已存在具有相同邮箱的用户。");
//---该用户类型中已存在具有相同邮箱的用户。
throw new BusinessValidationFailedException(_localizer["User_EmailDup"]);
}
}
@ -84,7 +87,8 @@ namespace IRaCIS.Application.Services
if (oldPwd != null && oldPwd == newPwd)
{
throw new BusinessValidationFailedException("新密码与旧密码相同。");
//---新密码与旧密码相同。
throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
}
@ -92,12 +96,14 @@ namespace IRaCIS.Application.Services
if (oldPwd != null && dbUser.Password != oldPwd)
{
throw new BusinessValidationFailedException("旧密码验证失败。");
//---旧密码验证失败。
throw new BusinessValidationFailedException(_localizer["User_OldPwdInvalid"]);
}
if (dbUser.Password == newPwd)
{
throw new BusinessValidationFailedException("新密码与旧密码相同。");
//---新密码与旧密码相同。
throw new BusinessValidationFailedException(_localizer["User_NewOldPwdSame"]);
}
@ -118,7 +124,8 @@ namespace IRaCIS.Application.Services
//检查手机或者邮箱是否有效
if (!Regex.IsMatch(email, @"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"))
{
return ResponseOutput.NotOk("Please input a legal email");
//---Please input a legal email
return ResponseOutput.NotOk(_localizer["User_LegalEmail"]);
}
@ -145,7 +152,8 @@ namespace IRaCIS.Application.Services
if (verificationRecord == null)
{
return ResponseOutput.NotOk("验证码错误。");
//---验证码错误。
return ResponseOutput.NotOk(_localizer["User_VerificationCodeError"]);
}
else
@ -153,14 +161,13 @@ namespace IRaCIS.Application.Services
//检查验证码是否失效
if (verificationRecord.ExpirationTime < DateTime.Now)
{
return ResponseOutput.NotOk("验证码已经过期。");
//---验证码已经过期。
return ResponseOutput.NotOk(_localizer["User_VerificationCodeExpired"]);
}
else //验证码正确 并且 没有超时
{
//更新密码
//var pwd = MD5Helper.Md5(newPwd);
//var count = _doctorRepository.Update<Doctor>().Where(t => t.Id == doctor.Id).Set(d => d.Password == pwd).ExecuteAffrows();
await VerifyUserEmailAsync(_userInfo.Id, _userInfo.UserTypeId, newEmail);
@ -173,6 +180,7 @@ namespace IRaCIS.Application.Services
//删除验证码历史记录
await _verificationCodeRepository.BatchDeleteNoTrackingAsync(t => t.UserId == _userInfo.Id && t.CodeType == 0);
return ResponseOutput.Ok();
}
@ -180,6 +188,7 @@ namespace IRaCIS.Application.Services
}
[HttpPut("{newPhone}")]
public async Task<IResponseOutput> SetNewPhone(string newPhone)
{
@ -272,7 +281,7 @@ namespace IRaCIS.Application.Services
}
catch (Exception ex)
{
throw new BusinessValidationFailedException("请检查邮箱地址或者联系维护人员, 邮件发送失败");
throw new BusinessValidationFailedException(_localizer["User_CreateFailed"]);
}
@ -301,7 +310,7 @@ namespace IRaCIS.Application.Services
if (!Regex.IsMatch(email, @"^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$"))
{
return ResponseOutput.NotOk("请输入一个正确的邮箱。");
return ResponseOutput.NotOk(_localizer["User_InvalidEmail"]);
}
@ -310,7 +319,7 @@ namespace IRaCIS.Application.Services
if (!exist)
{
return ResponseOutput.NotOk("邮箱错误。");
return ResponseOutput.NotOk(_localizer["User_EmailError"]);
}
@ -342,7 +351,7 @@ namespace IRaCIS.Application.Services
if (verificationRecord == null)
{
throw new BusinessValidationFailedException("验证码错误。");
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeError"]);
}
else
{
@ -350,7 +359,7 @@ namespace IRaCIS.Application.Services
if (verificationRecord.ExpirationTime < DateTime.Now)
{
throw new BusinessValidationFailedException("验证码已经过期。");
throw new BusinessValidationFailedException(_localizer["User_VerificationCodeError"]);
}
else //验证码正确 并且 没有超时
{
@ -519,7 +528,7 @@ namespace IRaCIS.Application.Services
catch (Exception ex)
{
_logger.LogError(ex.Message);
throw new BusinessValidationFailedException("发送邮件失败, 未能创建账户成功");
throw new BusinessValidationFailedException(_localizer["User_CreateFailed"]);
}
@ -566,7 +575,7 @@ namespace IRaCIS.Application.Services
{
if (await _userTrialRepository.AnyAsync(t => t.Id == userId))
{
return ResponseOutput.NotOk("该用户已经参加项目,不能够删除。");
return ResponseOutput.NotOk(_localizer["User_InProject"]);
}
var success = await _userRepository.BatchDeleteNoTrackingAsync(t => t.Id == userId);
@ -630,7 +639,7 @@ namespace IRaCIS.Application.Services
if (loginUser.Status == 0)
{
return ResponseOutput.NotOk("该用户已经被禁用。", new LoginReturnDTO());
return ResponseOutput.NotOk(_localizer["User_Disabled"], new LoginReturnDTO());
}
userLoginReturnModel.BasicInfo = loginUser;

View File

@ -748,7 +748,8 @@ namespace IRaCIS.Core.Application.Image.QA
if (await _subjectVisitRepository.AnyAsync(t => t.Id == subjectVisitId && t.SubmitState == SubmitStateEnum.Submitted &&
(!t.QCChallengeList.Any(u => u.ReuploadEnum == QCChanllengeReuploadEnum.QCAgreeUpload))))
{
return ResponseOutput.NotOk("IC已经提交不允许删除。");
//IC已经提交不允许删除。
return ResponseOutput.NotOk(_localizer["QCOperationService_HaveSubmitted"]);
}
var waitDeleteStudyList = await _dicomStudyRepository.Where(x => ids.Contains(x.Id)).ToListAsync();

View File

@ -92,7 +92,7 @@ namespace IRaCIS.Application.Contracts
[JsonIgnore]
public List<DicView> DictionaryList { get; set; } = new List<DicView>();
public List<string> ModalityList => DictionaryList.Where(t => t.ParentCode == StaticData.Modality).OrderBy(t => t.ShowOrder).Select(t => t.ValueCN).ToList();
public List<string> ModalityList => DictionaryList.Where(t => t.ParentCode == StaticData.Modality).OrderBy(t => t.ShowOrder).Select(t => t.Value).ToList();
public List<Guid> ModalityIds => DictionaryList.Where(t => t.ParentCode == StaticData.Modality).OrderBy(t => t.ShowOrder).Select(t => t.Id).ToList();
public List<string> CriterionList { get; set; }
@ -105,7 +105,7 @@ namespace IRaCIS.Application.Contracts
public List<Guid> ReviewTypeIds => DictionaryList.Where(t => t.ParentCode == StaticData.ReviewType).OrderBy(t => t.ShowOrder).Select(t => t.Id).ToList();
public List<string> ReviewTypeList => DictionaryList.Where(t => t.ParentCode == StaticData.ReviewType).OrderBy(t => t.ShowOrder).Select(t => t.ValueCN ).ToList();
public List<string> ReviewTypeList => DictionaryList.Where(t => t.ParentCode == StaticData.ReviewType).OrderBy(t => t.ShowOrder).Select(t => t.Value ).ToList();
//public string ReviewType { get; set; } = string.Empty;

View File

@ -186,6 +186,13 @@ namespace IRaCIS.Core.Domain.Share
{
return token;
}
var cookieToken = _accessor?.HttpContext?.Request.Cookies["access_token"].ToString();
if (!string.IsNullOrWhiteSpace(cookieToken))
{
return cookieToken;
}
return string.Empty;

View File

@ -177,7 +177,7 @@ namespace IRaCIS.Core.Domain.Models
public PackState PackState { get; set; }
public string PackRelativePath { get; set; }
public string PackRelativePath { get; set; } = string.Empty;
/// <summary>
/// 首次阅片时间

View File

@ -193,7 +193,7 @@ namespace IRaCIS.Core.Domain.Models
public string BodyPartTypes { get; set; } = "鼻咽部|脑部|颈部|胸部|上/下腹部|盆腔|全身|其他";
public string BodyPartTypes { get; set; } = "Nasopharynx|Brain|Neck|Chest|Upper/Lower Abdomen|Pelvis|Whole body|Other";
public string Modalitys { get; set; } = "CT|MRI|BoneScan|Photograph|PET|X-ray|US";